2023-10-20 19:31:12 +08:00
|
|
|
using System;
|
|
|
|
using System.Collections;
|
|
|
|
using System.Collections.Generic;
|
2023-10-24 23:37:59 +08:00
|
|
|
using BITFALL.Entities.Inventory;
|
2023-10-20 19:31:12 +08:00
|
|
|
using BITFALL.Items;
|
|
|
|
using BITKit;
|
|
|
|
using BITKit.Entities;
|
2023-12-26 20:07:19 +08:00
|
|
|
using Cysharp.Threading.Tasks;
|
2023-10-20 19:31:12 +08:00
|
|
|
using UnityEditor;
|
2023-12-26 20:07:19 +08:00
|
|
|
using UnityEditorInternal;
|
2023-10-20 19:31:12 +08:00
|
|
|
using UnityEngine;
|
2023-12-26 20:07:19 +08:00
|
|
|
using UnityEngine.InputSystem;
|
|
|
|
using UnityEngine.InputSystem.Interactions;
|
2023-10-20 19:31:12 +08:00
|
|
|
|
|
|
|
namespace BITFALL.Entities
|
|
|
|
{
|
|
|
|
[CustomType(typeof(IKnockdown))]
|
2023-10-30 01:25:53 +08:00
|
|
|
public sealed class EntityKnockdown :EntityBehavior,IKnockdown
|
2023-10-20 19:31:12 +08:00
|
|
|
{
|
2023-12-26 20:07:19 +08:00
|
|
|
[SerializeField,ReadOnly] private int knockedHealth;
|
2023-10-20 19:31:12 +08:00
|
|
|
[SerializeField] private int initialKnockedHealth;
|
2023-11-15 23:54:54 +08:00
|
|
|
|
|
|
|
[SerializeField] private Optional<float> invincibilityTimes;
|
2023-12-26 20:07:19 +08:00
|
|
|
|
|
|
|
[SerializeField] private InputActionReference pressureAction;
|
|
|
|
|
|
|
|
[SerializeReference,SubclassSelector] private ITicker ticker;
|
|
|
|
|
|
|
|
[Inject(true)] private InputActionGroup _inputActionGroup;
|
|
|
|
|
2023-10-20 19:31:12 +08:00
|
|
|
|
|
|
|
public int KnockedHealth=>knockedHealth;
|
|
|
|
public int InitialKnockedHealth
|
|
|
|
{
|
|
|
|
get => initialKnockedHealth;
|
|
|
|
set => initialKnockedHealth = value;
|
|
|
|
}
|
|
|
|
public event Action OnKnockdown;
|
|
|
|
public event Action OnRevive;
|
|
|
|
public bool IsKnockdown { get;private set; }
|
2023-12-26 20:07:19 +08:00
|
|
|
|
|
|
|
public bool IsPressured => _isPressured;
|
|
|
|
|
2023-11-15 23:54:54 +08:00
|
|
|
private readonly IntervalUpdate invincibilityInterval = new();
|
2023-10-20 19:31:12 +08:00
|
|
|
|
|
|
|
[Inject]
|
|
|
|
private IHealth _health;
|
|
|
|
|
|
|
|
[Inject]
|
2023-10-24 23:37:59 +08:00
|
|
|
private IEntityInventory _inventory;
|
2023-12-26 20:07:19 +08:00
|
|
|
|
|
|
|
private readonly ValidHandle _isPressured=new();
|
2023-10-20 19:31:12 +08:00
|
|
|
|
|
|
|
public override void OnStart()
|
|
|
|
{
|
2023-10-24 23:37:59 +08:00
|
|
|
_health.OnDamageFactory += OnDamageFactory;
|
2023-10-20 19:31:12 +08:00
|
|
|
_health.OnSetAlive += OnSetAlive;
|
|
|
|
_health.OnSetHealthPoint += OnSetHealthPoint;
|
|
|
|
|
2023-11-30 00:23:23 +08:00
|
|
|
_inventory.TryUseItemFactory+=TryUseItem;
|
2023-10-24 23:37:59 +08:00
|
|
|
_inventory.OnUsedItem += OnUseItem;
|
2023-12-26 20:07:19 +08:00
|
|
|
|
|
|
|
if (_inputActionGroup is not null)
|
|
|
|
{
|
|
|
|
_inputActionGroup.RegisterCallback(pressureAction, OnPressureAction);
|
|
|
|
}
|
|
|
|
|
|
|
|
ticker?.Add(OnTick);
|
|
|
|
destroyCancellationToken.Register(() =>
|
|
|
|
{
|
|
|
|
ticker?.Remove(OnTick);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
private void OnTick(float obj)
|
|
|
|
{
|
|
|
|
if (IsKnockdown is false || _health.HealthPoint<0) return;
|
|
|
|
|
|
|
|
knockedHealth-=_isPressured?1:2;
|
|
|
|
|
|
|
|
if (knockedHealth < 0)
|
|
|
|
{
|
|
|
|
_health.HealthPoint =-1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void OnPressureAction(InputAction.CallbackContext obj)
|
|
|
|
{
|
|
|
|
if (IsKnockdown is false) return;
|
|
|
|
switch (obj)
|
|
|
|
{
|
|
|
|
case {interaction:PressInteraction,performed:true}:
|
|
|
|
_isPressured.AddElement("123");
|
|
|
|
break;
|
|
|
|
case {interaction:PressInteraction,canceled:true}:
|
|
|
|
_isPressured.RemoveElement("123");
|
|
|
|
break;
|
|
|
|
}
|
2023-10-20 19:31:12 +08:00
|
|
|
}
|
|
|
|
|
2023-11-30 00:23:23 +08:00
|
|
|
private bool TryUseItem(IBasicItem arg)
|
|
|
|
{
|
|
|
|
if (IsKnockdown is false) return false;
|
|
|
|
if (arg is not null && arg.GetAssetable().TryGetProperty<PlayerReviveItem>(out _))
|
|
|
|
{
|
|
|
|
_inventory.UseItem(arg);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-10-20 19:31:12 +08:00
|
|
|
private void OnSetHealthPoint(int obj)
|
|
|
|
{
|
2023-10-24 23:37:59 +08:00
|
|
|
if (obj <= 0 || !IsKnockdown || !_health.IsAlive) return;
|
|
|
|
IsKnockdown = false;
|
|
|
|
OnRevive?.Invoke();
|
2023-10-20 19:31:12 +08:00
|
|
|
}
|
2023-10-24 23:37:59 +08:00
|
|
|
private void OnUseItem(IBasicItem arg)
|
2023-10-20 19:31:12 +08:00
|
|
|
{
|
2023-10-24 23:37:59 +08:00
|
|
|
if (IsKnockdown is false ||
|
|
|
|
arg.GetAssetable().TryGetProperty<PlayerReviveItem>(out var reviveItem) is false) return;
|
2023-10-20 19:31:12 +08:00
|
|
|
IsKnockdown = false;
|
2023-10-24 23:37:59 +08:00
|
|
|
OnRevive?.Invoke();
|
|
|
|
|
2023-10-20 19:31:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
private void OnSetAlive(bool obj)
|
|
|
|
{
|
|
|
|
IsKnockdown = false;
|
|
|
|
}
|
|
|
|
|
2023-11-30 00:23:23 +08:00
|
|
|
private int OnDamageFactory(DamageMessage arg, int currentDamage)
|
2023-10-20 19:31:12 +08:00
|
|
|
{
|
2023-11-30 00:23:23 +08:00
|
|
|
if (Data.Get<bool>(BITConstant.Environment.sp_knockdown_disabled)) return currentDamage;
|
|
|
|
|
2023-12-26 20:07:19 +08:00
|
|
|
if (IsKnockdown && invincibilityTimes.Allow && invincibilityInterval.AllowUpdateWithoutReset is false)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (currentDamage > _health.MaxHealthPoint + initialKnockedHealth) return currentDamage;
|
|
|
|
|
|
|
|
if (IsKnockdown is false && _health.HealthPoint - currentDamage >= 0) return currentDamage;
|
|
|
|
|
|
|
|
if (IsKnockdown && knockedHealth is 0)
|
|
|
|
{
|
|
|
|
return currentDamage;
|
|
|
|
}
|
|
|
|
if (IsKnockdown && KnockedHealth >= 0)
|
2023-11-15 23:54:54 +08:00
|
|
|
{
|
2023-12-26 20:07:19 +08:00
|
|
|
knockedHealth -= currentDamage;
|
2023-11-15 23:54:54 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2023-11-30 00:23:23 +08:00
|
|
|
|
2023-10-20 19:31:12 +08:00
|
|
|
IsKnockdown = true;
|
2023-11-30 00:23:23 +08:00
|
|
|
|
2023-12-26 20:07:19 +08:00
|
|
|
knockedHealth = initialKnockedHealth;
|
|
|
|
|
2023-11-15 23:54:54 +08:00
|
|
|
if (invincibilityTimes.Allow)
|
|
|
|
{
|
|
|
|
invincibilityInterval.Interval = invincibilityTimes.Value;
|
|
|
|
invincibilityInterval.Reset();
|
|
|
|
}
|
2023-11-30 00:23:23 +08:00
|
|
|
|
2023-10-20 19:31:12 +08:00
|
|
|
OnKnockdown?.Invoke();
|
|
|
|
_health.HealthPoint = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|