引入属性、伤害管线
This commit is contained in:
@@ -13,23 +13,17 @@ namespace SepCore.Components
|
||||
|
||||
private StatComponent _statComponent;
|
||||
|
||||
private StatProperty _maxHealthStat;
|
||||
private Action<modifier, bool> _maxHealthStatCallback;
|
||||
public StatProperty MaxHealthStat => _maxHealthStat;
|
||||
|
||||
private StatProperty _defenseStat;
|
||||
private Action<modifier, bool> _defenseStatCallback;
|
||||
public StatProperty DefenseStat => _defenseStat;
|
||||
|
||||
private StatProperty _dodgeStat;
|
||||
private Action<modifier, bool> _dodgeStatCallback;
|
||||
public StatProperty DodgeStat => _dodgeStat;
|
||||
private Action<StatType, float> _onStatChangedAction;
|
||||
private float _lastLifeStealTime = -1f;
|
||||
public const float LifeStealIcd = 0.1f;
|
||||
|
||||
private bool _isPlayer => _statComponent != null;
|
||||
|
||||
public float HealthRatio => MaxHealth > 0 ? (float)CurrentHealth / MaxHealth : 0f;
|
||||
|
||||
public int MaxHealth => Mathf.CeilToInt((_maxHealthBase + _maxHealthStat.Value) * _maxHealthStat.Percent);
|
||||
public int MaxHealth => _statComponent != null
|
||||
? Mathf.CeilToInt(_statComponent.GetStatValue(StatType.MaxHp))
|
||||
: _maxHealthBase;
|
||||
|
||||
public int CurrentHealth
|
||||
{
|
||||
@@ -46,82 +40,115 @@ namespace SepCore.Components
|
||||
_statComponent = statComponent;
|
||||
if (_statComponent != null)
|
||||
{
|
||||
_maxHealthStat = _statComponent.GetStat(StatType.MaxHealth);
|
||||
_maxHealthStatCallback = (modifier, isApply) =>
|
||||
{
|
||||
_statComponent.UpdateStat(_maxHealthStat, modifier, isApply);
|
||||
GameEntry.Event.Fire(this, PlayerHealthChangeEventArgs.Create(0, CurrentHealth, MaxHealth));
|
||||
};
|
||||
_statComponent.Subscribe(StatType.MaxHealth, _maxHealthStatCallback);
|
||||
|
||||
_defenseStat = _statComponent.GetStat(StatType.Defense);
|
||||
_defenseStatCallback = (modifier, isApply) =>
|
||||
_statComponent.UpdateStat(_defenseStat, modifier, isApply);
|
||||
_statComponent.Subscribe(StatType.Defense, _defenseStatCallback);
|
||||
|
||||
_dodgeStat = _statComponent.GetStat(StatType.Dodge);
|
||||
_dodgeStatCallback = (modifier, isApply) =>
|
||||
_statComponent.UpdateStat(_dodgeStat, modifier, isApply);
|
||||
_statComponent.Subscribe(StatType.Dodge, _dodgeStatCallback);
|
||||
}
|
||||
else
|
||||
{
|
||||
_maxHealthStat = new StatProperty();
|
||||
_defenseStat = new StatProperty();
|
||||
_dodgeStat = new StatProperty();
|
||||
_statComponent.Pipeline.SetBaseValue(StatType.MaxHp, maxHealth);
|
||||
_onStatChangedAction = OnStatChanged;
|
||||
_statComponent.Pipeline.OnStatChanged += _onStatChangedAction;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnReset()
|
||||
{
|
||||
if (_statComponent != null)
|
||||
if (_statComponent != null && _onStatChangedAction != null)
|
||||
{
|
||||
_statComponent.Unsubscribe(StatType.MaxHealth, _maxHealthStatCallback);
|
||||
_maxHealthStatCallback = null;
|
||||
|
||||
_statComponent.Unsubscribe(StatType.Defense, _defenseStatCallback);
|
||||
_defenseStatCallback = null;
|
||||
|
||||
_statComponent.Unsubscribe(StatType.Dodge, _dodgeStatCallback);
|
||||
_dodgeStatCallback = null;
|
||||
_statComponent.Pipeline.OnStatChanged -= _onStatChangedAction;
|
||||
_onStatChangedAction = null;
|
||||
}
|
||||
|
||||
_statComponent = null;
|
||||
_lastLifeStealTime = -1f;
|
||||
}
|
||||
|
||||
private void OnStatChanged(StatType statType, float newValue)
|
||||
{
|
||||
if (statType == StatType.MaxHp)
|
||||
{
|
||||
if (_currentHealth > MaxHealth)
|
||||
{
|
||||
_currentHealth = MaxHealth;
|
||||
}
|
||||
|
||||
if (GameEntry.Event != null)
|
||||
{
|
||||
GameEntry.Event.Fire(this, PlayerHealthChangeEventArgs.Create(0, CurrentHealth, MaxHealth));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
public void TakeDamage(int damage)
|
||||
public void TakeDamage(int damage, bool isCrit = false, bool isDodge = false, Vector3? hitPosition = null)
|
||||
{
|
||||
if (_isDead) return;
|
||||
|
||||
float maxDodge = GameEntry.Luban.Global.MaxDodgeRate / 1000f;
|
||||
if (UnityEngine.Random.value < Mathf.Clamp(_dodgeStat.Value, 0f, maxDodge))
|
||||
if (isDodge)
|
||||
{
|
||||
damage = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int defenseValue = (int)_defenseStat.Value;
|
||||
float defensePercent = _defenseStat.Percent;
|
||||
damage -= defenseValue;
|
||||
damage = Mathf.CeilToInt(damage / defensePercent);
|
||||
int minDamage = GameEntry.Luban.Global.MinDamage;
|
||||
if (damage < minDamage) damage = minDamage;
|
||||
float yOffset = GameEntry.Luban != null && GameEntry.Luban.IsReady
|
||||
? GameEntry.Luban.Global.DamageTextYOffset / 1000f
|
||||
: 1f;
|
||||
Vector3 pos = hitPosition ?? (transform.position + Vector3.up * yOffset);
|
||||
if (GameEntry.DamageText != null)
|
||||
{
|
||||
GameEntry.DamageText.ShowDamage(pos, 0, false, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
_currentHealth -= damage;
|
||||
CauseDamage(damage);
|
||||
if (_isPlayer)
|
||||
if (damage <= 0) return;
|
||||
|
||||
_currentHealth = Mathf.Max(0, _currentHealth - damage);
|
||||
CauseDamage(damage, isCrit, hitPosition);
|
||||
|
||||
if (_isPlayer && GameEntry.Event != null)
|
||||
{
|
||||
GameEntry.Event.Fire(this, PlayerHealthChangeEventArgs.Create(damage, CurrentHealth, MaxHealth));
|
||||
}
|
||||
}
|
||||
|
||||
private void CauseDamage(int damage)
|
||||
public void TakeDamage(int damage)
|
||||
{
|
||||
TakeDamage(damage, false, false, null);
|
||||
}
|
||||
|
||||
public void Heal(int healAmount)
|
||||
{
|
||||
if (_isDead || healAmount <= 0) return;
|
||||
|
||||
int oldHealth = _currentHealth;
|
||||
_currentHealth = Mathf.Min(_currentHealth + healAmount, MaxHealth);
|
||||
int healed = _currentHealth - oldHealth;
|
||||
|
||||
if (healed > 0 && _isPlayer && GameEntry.Event != null)
|
||||
{
|
||||
GameEntry.Event.Fire(this, PlayerHealthChangeEventArgs.Create(-healed, CurrentHealth, MaxHealth));
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryTriggerLifeSteal(int healAmount, float? customTime = null)
|
||||
{
|
||||
if (_isDead || healAmount <= 0) return false;
|
||||
float currentTime = customTime ?? Time.time;
|
||||
if (_lastLifeStealTime >= 0f && currentTime - _lastLifeStealTime < LifeStealIcd)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_lastLifeStealTime = currentTime;
|
||||
Heal(healAmount);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void CauseDamage(int damage, bool isCrit = false, Vector3? hitPosition = null)
|
||||
{
|
||||
if (damage <= 0) return;
|
||||
float yOffset = GameEntry.Luban.Global.DamageTextYOffset / 1000f;
|
||||
GameEntry.DamageText.ShowDamage(transform.position + Vector3.up * yOffset, damage);
|
||||
float yOffset = GameEntry.Luban != null && GameEntry.Luban.IsReady
|
||||
? GameEntry.Luban.Global.DamageTextYOffset / 1000f
|
||||
: 1f;
|
||||
Vector3 pos = hitPosition ?? (transform.position + Vector3.up * yOffset);
|
||||
if (GameEntry.DamageText != null)
|
||||
{
|
||||
GameEntry.DamageText.ShowDamage(pos, damage, isCrit, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user