using Fie.Manager; using System; using System.Collections; using System.Collections.Generic; using UnityEngine; namespace Fie.Object { public class FieDamageSystem : MonoBehaviour { public struct DamageMagniContainer { public int abilityID; public float magni; public DamageMagniContainer(int abilityID, float magni) { this.abilityID = abilityID; this.magni = magni; } } public delegate void ReviveDelegate(); public delegate void DeathDelegate(FieGameCharacter killer, FieDamage damage); public delegate void StaggerDelegate(FieDamage damage); public delegate bool DamageCheckDelegate(FieGameCharacter attacker, FieDamage damage); public delegate void BeforeDamageDelegate(FieGameCharacter attacker, ref FieDamage damage); public delegate void DamageDelegate(FieGameCharacter attacker, FieDamage damage); public delegate void StatusEffectDelegate(FieStatusEffectEntityBase statusEffect, FieGameCharacter attacker, FieDamage damage); public const float HITPOINT_GATE_RATE = 0.05f; public const float HITPOINT_GATE_DELAY = 12f; public const float HITPOINT_GATE_IMMUNITY_SEC = 0.3f; public const float SHIELD_GATE_DELAY = 8f; public const float DEFAULT_DYING_SEC = 12f; public const float DEFAULT_REVIVE_SEC = 3f; private Dictionary _statusEffectCallbacks = new Dictionary(); private FieGameCharacter _ownerCharacter; private FieGameCharacter _latestPerpetrator; private FieDamage _latestDamage; private FieHealthStats _healthStats = new FieHealthStats(); private FieHealthStats _healthStatsSandbox = new FieHealthStats(); private bool _isDead; private float _dyingCount; private float _reviveCount; private float _currentRegenerateDelay; private float _hitPointGateDelay; private float _hitPointGateImunitySec; private float _shieldGateDelay; private bool _isEnableRegenerate = true; private bool _isEnableHitPointGate = true; private bool _isEnableShieldGate = true; private bool _isEnableHealthImmunity; private bool _isEnableStaggerImmunity; private bool _revivable; private float _dyingNeedSec = 12f; private float _reviveNeedSec = 3f; private Dictionary> _attackMagniStack = new Dictionary>(); private Dictionary> _defenceMagniStack = new Dictionary>(); private Dictionary _takenDamages = new Dictionary(); private FieHealthStats healthStats { get { if (_ownerCharacter == null || _ownerCharacter.photonView == null || !_ownerCharacter.photonView.isMine) { return _healthStatsSandbox; } return _healthStats; } } public bool isEnableRegenerate { get { return _isEnableRegenerate; } set { _isEnableRegenerate = value; } } public bool isEnableHitPointGate { get { return _isEnableHitPointGate; } set { _isEnableHitPointGate = value; } } public bool isEnableShieldGate { get { return _isEnableShieldGate; } set { _isEnableShieldGate = value; } } public bool isEnableHealthImmunity { get { return _isEnableHealthImmunity; } set { _isEnableHealthImmunity = value; } } public bool isEnableStaggerImmunity { get { return _isEnableStaggerImmunity; } set { _isEnableStaggerImmunity = value; } } public float dyingNeedSec { get { return _dyingNeedSec; } set { _dyingNeedSec = Mathf.Max(value, 0f); } } public float reviveNeedSec { get { return _reviveNeedSec; } set { _reviveNeedSec = Mathf.Max(value, 0f); } } public bool isDying { get { if (healthStats == null) { return true; } return healthStats.hitPoint <= 0f; } } public bool isDead => _isDead; public bool revivable { get { return _revivable; } set { if (_revivable != value) { _reviveCount = 0f; _revivable = value; } } } public Dictionary takenDamage => _takenDamages; public event DeathDelegate deathEvent; public event ReviveDelegate reviveEvent; public event StaggerDelegate staggerEvent; public event DamageCheckDelegate damageCheckEvent; public event BeforeDamageDelegate beforeDamageEvent; public event DamageDelegate damagedEvent; private IEnumerator addAttackMagniStackCoroutine(int skillID, int abilityID, float magni, float duration, bool isEnableStack = false) { if (!_attackMagniStack.ContainsKey(skillID) || _attackMagniStack[skillID] == null) { _attackMagniStack[skillID] = new Queue(); } int stackedCount = _attackMagniStack[skillID].Count; if (stackedCount > 0 && !isEnableStack) { if (stackedCount == 1) { _attackMagniStack[skillID].Dequeue(); } else { _attackMagniStack[skillID].Clear(); } } _attackMagniStack[skillID].Enqueue(new DamageMagniContainer(abilityID, magni)); yield return (object)new WaitForSeconds(duration); /*Error: Unable to find new state assignment for yield return*/; } private IEnumerator addDefenceMagniStackCoroutine(int skillID, float magni, float duration, bool isEnableStack = false) { if (!_defenceMagniStack.ContainsKey(skillID) || _defenceMagniStack[skillID] == null) { _defenceMagniStack[skillID] = new Queue(); } int stackedCount = _defenceMagniStack[skillID].Count; if (stackedCount > 0 && !isEnableStack) { if (stackedCount == 1) { _defenceMagniStack[skillID].Dequeue(); } else { _defenceMagniStack[skillID].Clear(); } } _defenceMagniStack[skillID].Enqueue(magni); yield return (object)new WaitForSeconds(duration); /*Error: Unable to find new state assignment for yield return*/; } public void AddAttackMagni(int skillID, float magni, float duration, int abilityID = -1, bool isEnableStack = false) { StartCoroutine(addAttackMagniStackCoroutine(skillID, abilityID, magni, duration, isEnableStack)); } public void AddDefenceMagni(int skillID, float magni, float duration, bool isEnableStack = false) { StartCoroutine(addDefenceMagniStackCoroutine(skillID, magni, duration, isEnableStack)); } public float GetAttackMagni(int abilityID = -1) { float num = 0f; if (_attackMagniStack == null || _attackMagniStack.Count <= 0) { return num; } foreach (KeyValuePair> item in _attackMagniStack) { if (item.Value != null && item.Value.Count > 0) { foreach (DamageMagniContainer item2 in item.Value) { DamageMagniContainer current2 = item2; if (current2.abilityID == abilityID || current2.abilityID == -1) { num += current2.magni; } } } } return num; } public float GetDeffenceMagni() { float num = 0f; if (_defenceMagniStack == null || _defenceMagniStack.Count <= 0) { return num; } foreach (KeyValuePair> item in _defenceMagniStack) { if (item.Value != null && item.Value.Count > 0) { foreach (float item2 in item.Value) { num += item2; } } } return num; } public void Regen(float regenPoint) { if (healthStats.shield <= 0f) { float num = Mathf.Clamp(healthStats.hitPoint + regenPoint, 0f, healthStats.maxHitPoint); regenPoint -= num - healthStats.hitPoint; healthStats.hitPoint = num; } healthStats.shield = Mathf.Clamp(healthStats.shield + regenPoint, 0f, healthStats.maxShield); } public void initHealthSystem(FieGameCharacter ownerCharacter, ref FieHealthStats parameters) { _ownerCharacter = ownerCharacter; _healthStats = parameters; resetHealthSystem(); } public void resetHealthSystem() { healthStats.hitPoint = healthStats.maxHitPoint; healthStats.shield = healthStats.maxShield; _isEnableRegenerate = true; _isEnableHitPointGate = true; _isEnableShieldGate = true; _isEnableHealthImmunity = false; _isEnableStaggerImmunity = false; _revivable = false; _isDead = false; _dyingCount = 0f; _reviveCount = 0f; _currentRegenerateDelay = 0f; _hitPointGateDelay = 0f; _hitPointGateImunitySec = 0f; _shieldGateDelay = 0f; _dyingNeedSec = 12f; _reviveNeedSec = 3f; } public void calcHitPoitDirect(float additionalHitpoint) { if (!(_ownerCharacter.photonView != null) || _ownerCharacter.photonView.isMine) { healthStats.hitPoint += additionalHitpoint; healthStats.hitPoint = Mathf.Max(Mathf.Min(healthStats.hitPoint, healthStats.maxHitPoint), 0f); } } public void calcShieldDirect(float additionalShield) { if (!(_ownerCharacter.photonView != null) || _ownerCharacter.photonView.isMine) { healthStats.shield += additionalShield; healthStats.shield = Mathf.Max(Mathf.Min(healthStats.shield, healthStats.maxShield), 0f); } } public void setRegenerateDelay(float delayTime, bool roundToBigger = false) { if (!roundToBigger || !(delayTime < _currentRegenerateDelay)) { _currentRegenerateDelay = Mathf.Max(delayTime, 0f); } } public void ResetStaggerEvent() { this.staggerEvent = null; } public void updateHealthSystem(float time) { if (isDying) { if (!_isDead) { _isDead = true; if (this.deathEvent != null) { this.deathEvent(_latestPerpetrator, _latestDamage); } } } else { if (healthStats.stagger > 0f) { healthStats.stagger -= healthStats.staggerResistance * healthStats.staggerAttenuationPerSec * time; healthStats.stagger = Mathf.Max(healthStats.stagger, 0f); } if (_hitPointGateImunitySec > 0f) { _hitPointGateImunitySec -= time; } if (_hitPointGateDelay > 0f) { _hitPointGateDelay -= time; } if (_shieldGateDelay > 0f) { _shieldGateDelay -= time; } if (_currentRegenerateDelay > 0f) { _currentRegenerateDelay -= time; } else if (_isEnableRegenerate) { if (healthStats.hitPoint < healthStats.maxHitPoint) { healthStats.hitPoint += healthStats.maxHitPoint * healthStats.hitPointRegeneratePerSec * time; } if (healthStats.hitPoint >= healthStats.maxHitPoint && healthStats.shield < healthStats.maxShield) { healthStats.shield += healthStats.maxShield * healthStats.shieldRegeneratePerSec * time; } healthStats.hitPoint = Mathf.Min(healthStats.hitPoint, healthStats.maxHitPoint); healthStats.shield = Mathf.Min(healthStats.shield, healthStats.maxShield); } } } public FieDamageSystem addDamage(FieGameCharacter attacker, FieDamage damageObject, bool isPenetration = false) { if (damageObject == null) { return this; } bool flag = false; if (this.damageCheckEvent != null && !this.damageCheckEvent(attacker, damageObject)) { return this; } if (damageObject.statusEffects != null) { foreach (FieStatusEffectEntityBase statusEffect in damageObject.statusEffects) { flag |= statusEffect.ApplyStatusEffect(this, attacker, damageObject); } } if (flag) { return this; } damageObject.damage *= Mathf.Max(0f, 1f - GetDeffenceMagni()); if (this.beforeDamageEvent != null) { this.beforeDamageEvent(attacker, ref damageObject); } healthStats.stagger += damageObject.stagger; if (_healthStats.stagger >= _healthStats.staggerResistance && !isEnableStaggerImmunity) { if (this.staggerEvent != null) { this.staggerEvent(damageObject); } healthStats.stagger = 0f; } if (damageObject.damage > 0f && !isEnableHealthImmunity) { float num = damageObject.damage + damageObject.damage * (((UnityEngine.Random.Range(0, 100) < 50) ? (-1f) : 1f) * UnityEngine.Random.Range(0f, damageObject.fluctuatingRate)); damageObject.finallyDamage = 0f; bool flag2 = false; if (_healthStats.shield > 0f) { float num2 = 1f; switch (damageObject.attribute) { case FieAttribute.MAGIC: if (_healthStats.shieldType == FieAttribute.WING) { num2 += _healthStats.weakAttributeDamageMagnify; damageObject.attributeDamageState = FieDamage.FieAttributeDamageState.EFFECTIVE; } else if (_healthStats.shieldType == FieAttribute.EARTH) { num2 += _healthStats.strongAttributeDamageMagnify; damageObject.attributeDamageState = FieDamage.FieAttributeDamageState.NONEFFECTIVE; } break; case FieAttribute.WING: if (_healthStats.shieldType == FieAttribute.EARTH) { num2 += _healthStats.weakAttributeDamageMagnify; damageObject.attributeDamageState = FieDamage.FieAttributeDamageState.EFFECTIVE; } else if (_healthStats.shieldType == FieAttribute.MAGIC) { num2 += _healthStats.strongAttributeDamageMagnify; damageObject.attributeDamageState = FieDamage.FieAttributeDamageState.NONEFFECTIVE; } break; case FieAttribute.EARTH: if (_healthStats.shieldType == FieAttribute.MAGIC) { damageObject.attributeDamageState = FieDamage.FieAttributeDamageState.EFFECTIVE; num2 += _healthStats.weakAttributeDamageMagnify; } else if (_healthStats.shieldType == FieAttribute.WING) { num2 += _healthStats.strongAttributeDamageMagnify; damageObject.attributeDamageState = FieDamage.FieAttributeDamageState.NONEFFECTIVE; } break; } num = damageObject.damage * num2; float num3 = Mathf.Max(_healthStats.shield - num, 0f); if (num3 <= 0f) { num = Mathf.Abs(_healthStats.shield - num); flag2 = true; } if (_isEnableShieldGate && _shieldGateDelay <= 0f && !isPenetration && FieManagerBehaviour.I.currentDifficulty < FieEnvironmentManager.Difficulty.NIGHTMARE) { flag2 = false; if (num3 <= 0f) { _shieldGateDelay = 8f; } } float shield = _healthStats.shield; healthStats.shield = num3; damageObject.finallyDamage += shield - healthStats.shield; } else { flag2 = true; } if (flag2 && num > 0f) { float hitPoint = _healthStats.hitPoint; float num4 = hitPoint; if (_isEnableHitPointGate && !isPenetration && FieManagerBehaviour.I.currentDifficulty != FieEnvironmentManager.Difficulty.CHAOS) { if (_hitPointGateDelay <= 0f && _healthStats.hitPoint - num <= _healthStats.maxHitPoint * 0.05f) { _hitPointGateImunitySec = 0.3f; _hitPointGateDelay = 12f; } float b = (!(_hitPointGateImunitySec > 0f)) ? 0f : (_healthStats.maxHitPoint * 0.05f); healthStats.hitPoint = Mathf.Max(_healthStats.hitPoint - num, b); num4 = healthStats.hitPoint; } else { num4 = _healthStats.hitPoint - num; healthStats.hitPoint = Mathf.Max(_healthStats.hitPoint - num, 0f); } damageObject.finallyDamage += hitPoint - num4; } _currentRegenerateDelay = _healthStats.regenerateDelay; } if (this.damagedEvent != null) { this.damagedEvent(attacker, damageObject); } if (attacker != null && damageObject.finallyDamage > 0f) { _latestPerpetrator = attacker; if (!_takenDamages.ContainsKey(attacker)) { _takenDamages[attacker] = 0f; } Dictionary takenDamages; FieGameCharacter key; (takenDamages = _takenDamages)[key = attacker] = takenDamages[key] + damageObject.finallyDamage; } if (damageObject != null) { _latestDamage = damageObject; } return this; } public void addStatusEffectCallback(StatusEffectDelegate callback) where T : FieStatusEffectEntityBase { _statusEffectCallbacks[typeof(T)] = callback; } public void applyStatusEffectCallback(T statusEffectObject, FieGameCharacter attacker, FieDamage damage) where T : FieStatusEffectEntityBase { if (statusEffectObject != null) { Type type = statusEffectObject.GetType(); if (_statusEffectCallbacks.ContainsKey(type) && _statusEffectCallbacks[type] != null) { _statusEffectCallbacks[type](statusEffectObject, attacker, damage); } } } public void Heal(float healingRate) { } private void initializeByRevive() { healthStats.hitPoint = healthStats.maxHitPoint; healthStats.shield = 0f; _isDead = false; _revivable = false; _reviveCount = 0f; _dyingCount = 0f; _currentRegenerateDelay = healthStats.regenerateDelay; _hitPointGateDelay = 0f; _hitPointGateImunitySec = 0f; } } }