using System.Collections; using System.Collections.Generic; using UnityEngine; using RPGCreationKit; using RPGCreationKit.SaveSystem; namespace RPGCreationKit { public enum EntityBaseAttributes { Strength = 0, Dexterity = 1, Agility = 2, Constitution = 3, Speed = 4, Endurance = 5, Charisma = 6, Intelligence = 7, Willpower = 8 }; public enum EntityBaseAttributesState { Normal = 0, Buffed = 1, Debuffed = 2 } [System.Serializable] public class BaseAttributes { public int Strength = 5; public int Dexterity = 5; public int Agility = 5; public int Constitution = 5; public int Speed = 5; public int Endurance = 5; public int Charisma = 5; public int Intelligence = 5; public int Willpower = 5; } [System.Serializable] public class EntityDerivedAttributes { public float maxHealth = RCKSettings.ATTRIBUTES_DEF_HEALTH; public float curHealth = RCKSettings.ATTRIBUTES_DEF_HEALTH; public float curMana = RCKSettings.ATTRIBUTES_DEF_MANA; public float maxStamina = RCKSettings.ATTRIBUTES_DEF_STAMINA; public float curStamina = RCKSettings.ATTRIBUTES_DEF_STAMINA; public float maxMana = RCKSettings.ATTRIBUTES_DEF_MANA; public int maxEncumbrance = 150; public float walkSpeed = 1.4f; public float runSpeed = 2.5f; [Range(20, 200), Tooltip("Determines the accuracy of the shots of this AI, 100 means it will always aim correctly, 0 means it will likely never get the target")] public float rangedCombatAccuracy = 70; [Range(0, 100), Tooltip("Determines the ability of this AI to Predict the position of its target while using a ranged weapon. This includes aiming higher to get targets that are further away (or just too far away for the Weapon's Reach")] public float rangedCombatPrediction = 70; } public class EntityAttributes : MonoBehaviour { #region PlayerAttributes public static EntityAttributes PlayerAttributes; private void Awake() { if (!PlayerAttributes) if (gameObject.CompareTag("Player")) PlayerAttributes = this; } [SerializeField] Transform activeEffectsUIContainer; #endregion [Header("Attributes")] [SerializeField] public BaseAttributes attributes; [Space(5)] [SerializeField] public EntityDerivedAttributes derivedAttributes; public bool bleeds = true; public GameObject bloodPrefab; public float CurHealth { get { return derivedAttributes.curHealth; } set { derivedAttributes.curHealth = value; } } public float CurStamina { get { return derivedAttributes.curStamina; } set { derivedAttributes.curStamina = value; } } public float CurMana { get { return derivedAttributes.curMana; } set { derivedAttributes.curMana = value; } } public float MaxHealth { get { return derivedAttributes.maxHealth; } set { derivedAttributes.maxHealth = value; if (CurHealth >= derivedAttributes.maxHealth) CurHealth = derivedAttributes.maxHealth; if (PlayerAttributes == this) Player.RckPlayer.instance.UpdateHealthStaminaGUI(); } } public float MaxStamina { get { return derivedAttributes.maxStamina; } set { derivedAttributes.maxStamina = value; if (CurStamina >= derivedAttributes.maxStamina) CurStamina = derivedAttributes.maxStamina; if (PlayerAttributes == this) Player.RckPlayer.instance.UpdateHealthStaminaGUI(); } } public float MaxMana { get { return derivedAttributes.maxMana; } set { derivedAttributes.maxMana = value; if (CurMana >= derivedAttributes.maxMana) CurMana = derivedAttributes.maxStamina; if (PlayerAttributes == this) Player.RckPlayer.instance.UpdateHealthStaminaGUI(); } } [Space(5)] public List activeEffects; //public Dictionary activeEffects; public void ExecuteEffects(EffectOnEntity[] effects) { bool overtime = false; for (int i = 0; i < effects.Length; i++) { EffectOnEntity effectCopy = new EffectOnEntity(effects[i]); switch (effects[i].effectType) { case ConsumableEffectType.DamageAttribute: effectCopy.isOnDuration = true; overtime = (effectCopy.duration != 0); effectCopy.magnitudeAlreadyApplied = effects[i].magnitudeAlreadyApplied; DamageAttribute(effectCopy, overtime); activeEffects.Add(effectCopy); break; case ConsumableEffectType.DamageHealth: effectCopy.isOnDuration = false; effectCopy.magnitudeAlreadyApplied = effects[i].magnitudeAlreadyApplied; overtime = (effectCopy.duration != 0); DamageHealth(effectCopy, overtime); activeEffects.Add(effectCopy); break; case ConsumableEffectType.DamageStamina: effectCopy.isOnDuration = false; effectCopy.magnitudeAlreadyApplied = effects[i].magnitudeAlreadyApplied; overtime = (effectCopy.duration != 0); DamageStamina(effectCopy, overtime); activeEffects.Add(effectCopy); break; case ConsumableEffectType.DamageMana: effectCopy.isOnDuration = true; overtime = (effectCopy.duration != 0); effectCopy.magnitudeAlreadyApplied = effects[i].magnitudeAlreadyApplied; DamageMana(effectCopy, overtime); activeEffects.Add(effectCopy); break; case ConsumableEffectType.FortifyAttribute: effectCopy.isOnDuration = true; effectCopy.magnitudeAlreadyApplied = effects[i].magnitudeAlreadyApplied; overtime = (effectCopy.duration != 0); FortifyAttribute(effectCopy, overtime); activeEffects.Add(effectCopy); break; case ConsumableEffectType.FortifyHealth: effectCopy.isOnDuration = true; overtime = (effectCopy.duration != 0); effectCopy.magnitudeAlreadyApplied = effects[i].magnitudeAlreadyApplied; FortifyHealth(effectCopy, overtime); activeEffects.Add(effectCopy); break; case ConsumableEffectType.FortifyStamina: effectCopy.isOnDuration = true; overtime = (effectCopy.duration != 0); effectCopy.magnitudeAlreadyApplied = effects[i].magnitudeAlreadyApplied; FortifyStamina(effectCopy, overtime); activeEffects.Add(effectCopy); break; case ConsumableEffectType.FortifyMana: effectCopy.isOnDuration = true; overtime = (effectCopy.duration != 0); effectCopy.magnitudeAlreadyApplied = effects[i].magnitudeAlreadyApplied; FortifyMana(effectCopy, overtime); activeEffects.Add(effectCopy); break; case ConsumableEffectType.RestoreAttribute: break; case ConsumableEffectType.RestoreHealth: overtime = (effectCopy.duration != 0); effectCopy.magnitudeAlreadyApplied = effects[i].magnitudeAlreadyApplied; RestoreHealth(effectCopy, overtime); activeEffects.Add(effectCopy); break; case ConsumableEffectType.RestoreStamina: overtime = (effectCopy.duration != 0); effectCopy.magnitudeAlreadyApplied = effects[i].magnitudeAlreadyApplied; RestoreStamina(effectCopy, overtime); activeEffects.Add(effectCopy); break; case ConsumableEffectType.RestoreMana: overtime = (effectCopy.duration != 0); effectCopy.magnitudeAlreadyApplied = effects[i].magnitudeAlreadyApplied; RestoreMana(effectCopy, overtime); activeEffects.Add(effectCopy); break; } } } public void DamageAttribute(EffectOnEntity effect, bool _overtime = false) { if (_overtime) { StartCoroutine(DamageAttributeUpdate(effect)); if (PlayerAttributes == this && effect.showInEffectsUI) { EffectOnEntityUI effectUI = EffectsOnPlayerUIPoolManager.pool.GetPooledObject(); effectUI.gameObject.SetActive(true); effectUI.Init(effect, true); } } else AlterAttribute(effect, false); } public void FortifyAttribute(EffectOnEntity effect, bool _overtime = false) { if (_overtime) { StartCoroutine(FortifyAttributeUpdate(effect)); if (PlayerAttributes == this && effect.showInEffectsUI) { EffectOnEntityUI effectUI = EffectsOnPlayerUIPoolManager.pool.GetPooledObject(); effectUI.gameObject.SetActive(true); effectUI.Init(effect, true); } } else AlterAttribute(effect, true); } public void RestoreAttribute(EntityBaseAttributes _attribute, float _duration, float _magnitude) { } public void DamageHealth(EffectOnEntity effect, bool _overtime = false) { if (_overtime) { StartCoroutine(DecreaseHealth(effect)); // Show on UI if (PlayerAttributes == this && effect.showInEffectsUI) { EffectOnEntityUI effectUI = EffectsOnPlayerUIPoolManager.pool.GetPooledObject(); effectUI.gameObject.SetActive(true); effectUI.Init(effect, false); } } else CurHealth -= effect.magnitude; } public void DamageHealth(float _amount, bool _overtime, float rate) { if (_overtime) StartCoroutine(DecreaseHealth(_amount, rate)); else CurHealth -= _amount; } public void DamageStamina(EffectOnEntity effect, bool _overtime = false) { if (_overtime) { StartCoroutine(DecreaseStamina(effect)); if (PlayerAttributes == this && effect.showInEffectsUI) { EffectOnEntityUI effectUI = EffectsOnPlayerUIPoolManager.pool.GetPooledObject(); effectUI.gameObject.SetActive(true); effectUI.Init(effect, false); } } else CurStamina -= effect.magnitude; } public void DamageMana(EffectOnEntity effect, bool _overtime = false) { if (_overtime) { StartCoroutine(DecreaseMana(effect)); if (PlayerAttributes == this && effect.showInEffectsUI) { EffectOnEntityUI effectUI = EffectsOnPlayerUIPoolManager.pool.GetPooledObject(); effectUI.gameObject.SetActive(true); effectUI.Init(effect, false); } } else CurMana -= effect.magnitude; } public void DamageStamina(float _amount, bool _overtime, float rate) { if (_overtime) StartCoroutine(DecreaseStamina(_amount, rate)); else CurStamina -= _amount; } public void DamageMana(float _amount, bool _overtime, float rate) { if (_overtime) StartCoroutine(DecreaseMana(_amount, rate)); else CurMana -= _amount; } public void RestoreHealth(EffectOnEntity effect, bool _overtime = false) { if (_overtime) { StartCoroutine(IncreaseHealth(effect)); if (PlayerAttributes == this && effect.showInEffectsUI) { EffectOnEntityUI effectUI = EffectsOnPlayerUIPoolManager.pool.GetPooledObject(); effectUI.gameObject.SetActive(true); effectUI.Init(effect, false); } } else CurHealth += effect.magnitude; } public void RestoreStamina(EffectOnEntity effect, bool _overtime = false) { if (_overtime) { StartCoroutine(IncreaseStamina(effect)); if (PlayerAttributes == this && effect.showInEffectsUI) { EffectOnEntityUI effectUI = EffectsOnPlayerUIPoolManager.pool.GetPooledObject(); effectUI.gameObject.SetActive(true); effectUI.Init(effect, false); } } else CurStamina += effect.magnitude; } public void RestoreMana(EffectOnEntity effect, bool _overtime = false) { if (_overtime) { StartCoroutine(IncreaseMana(effect)); if (PlayerAttributes == this && effect.showInEffectsUI) { EffectOnEntityUI effectUI = EffectsOnPlayerUIPoolManager.pool.GetPooledObject(); effectUI.gameObject.SetActive(true); effectUI.Init(effect, false); } } else CurMana += effect.magnitude; } public void FortifyHealth(EffectOnEntity effect, bool _overtime = false) { if (_overtime) { StartCoroutine(FortifyHealthUpdate(effect)); if (PlayerAttributes == this && effect.showInEffectsUI) { EffectOnEntityUI effectUI = EffectsOnPlayerUIPoolManager.pool.GetPooledObject(); effectUI.gameObject.SetActive(true); effectUI.Init(effect, true); } } else MaxHealth += effect.magnitude; } public void FortifyStamina(EffectOnEntity effect, bool _overtime = false) { if (_overtime) { StartCoroutine(FortifyStaminaUpdate(effect)); if (PlayerAttributes == this && effect.showInEffectsUI) { EffectOnEntityUI effectUI = EffectsOnPlayerUIPoolManager.pool.GetPooledObject(); effectUI.gameObject.SetActive(true); effectUI.Init(effect, true); } } else MaxStamina += effect.magnitude; } public void FortifyMana(EffectOnEntity effect, bool _overtime = false) { if (_overtime) { StartCoroutine(FortifyManaUpdate(effect)); if (PlayerAttributes == this && effect.showInEffectsUI) { EffectOnEntityUI effectUI = EffectsOnPlayerUIPoolManager.pool.GetPooledObject(); effectUI.gameObject.SetActive(true); effectUI.Init(effect, true); } } else MaxMana += effect.magnitude; } void AlterAttribute(EffectOnEntity _effect, bool _add) { switch (_effect.onAttribute) { case EntityBaseAttributes.Strength: attributes.Strength = (_add) ? (attributes.Strength + (int)_effect.magnitude) : (attributes.Strength - (int)_effect.magnitude); break; case EntityBaseAttributes.Dexterity: attributes.Dexterity = (_add) ? (attributes.Dexterity + (int)_effect.magnitude) : (attributes.Dexterity - (int)_effect.magnitude); break; case EntityBaseAttributes.Agility: attributes.Agility = (_add) ? (attributes.Agility + (int)_effect.magnitude) : (attributes.Agility - (int)_effect.magnitude); break; case EntityBaseAttributes.Constitution: attributes.Constitution = (_add) ? (attributes.Constitution + (int)_effect.magnitude) : (attributes.Constitution - (int)_effect.magnitude); break; case EntityBaseAttributes.Speed: attributes.Speed = (_add) ? (attributes.Speed + (int)_effect.magnitude) : (attributes.Speed - (int)_effect.magnitude); break; case EntityBaseAttributes.Endurance: attributes.Endurance = (_add) ? (attributes.Speed + (int)_effect.magnitude) : (attributes.Endurance - (int)_effect.magnitude); break; case EntityBaseAttributes.Charisma: attributes.Charisma = (_add) ? (attributes.Charisma + (int)_effect.magnitude) : (attributes.Charisma - (int)_effect.magnitude); break; case EntityBaseAttributes.Intelligence: attributes.Intelligence = (_add) ? (attributes.Intelligence + (int)_effect.magnitude) : (attributes.Intelligence - (int)_effect.magnitude); break; case EntityBaseAttributes.Willpower: attributes.Willpower = (_add) ? (attributes.Willpower + (int)_effect.magnitude) : (attributes.Willpower - (int)_effect.magnitude); break; } } IEnumerator FortifyHealthUpdate(EffectOnEntity effect) { MaxHealth += effect.magnitude; while (effect.duration >= effect.magnitudeAlreadyApplied) { while (GameStatus.instance.IsPaused) yield return null; effect.magnitudeAlreadyApplied += 1 * Time.deltaTime; yield return null; } MaxHealth -= effect.magnitude; yield return null; } IEnumerator FortifyAttributeUpdate(EffectOnEntity effect) { AlterAttribute(effect, true); while (effect.duration >= effect.magnitudeAlreadyApplied) { while (GameStatus.instance.IsPaused) yield return null; effect.magnitudeAlreadyApplied += 1 * Time.deltaTime; yield return null; } AlterAttribute(effect, false); yield return null; } IEnumerator DamageAttributeUpdate(EffectOnEntity effect) { AlterAttribute(effect, false); while (effect.duration >= effect.magnitudeAlreadyApplied) { while (GameStatus.instance.IsPaused) yield return null; effect.magnitudeAlreadyApplied += 1 * Time.deltaTime; yield return null; } AlterAttribute(effect, true); yield return null; } IEnumerator FortifyStaminaUpdate(EffectOnEntity effect) { MaxStamina += effect.magnitude; while (effect.duration >= effect.magnitudeAlreadyApplied) { while (GameStatus.instance.IsPaused) yield return null; effect.magnitudeAlreadyApplied += 1 * Time.deltaTime; //Debug.Log(effect.duration + " | " + effect.magnitudeAlreadyApplied); yield return null; } MaxStamina -= effect.magnitude; yield return null; } IEnumerator FortifyManaUpdate(EffectOnEntity effect) { MaxMana += effect.magnitude; while (effect.duration >= effect.magnitudeAlreadyApplied) { while (GameStatus.instance.IsPaused) yield return null; effect.magnitudeAlreadyApplied += 1 * Time.deltaTime; //Debug.Log(effect.duration + " | " + effect.magnitudeAlreadyApplied); yield return null; } MaxMana -= effect.magnitude; yield return null; } // ----------------------------------------------------------------------------- // To gradually decrease a value - Health // ----------------------------------------------------------------------------- IEnumerator DecreaseHealth(EffectOnEntity effect) { float decreased = effect.magnitudeAlreadyApplied; float delta = effect.magnitude / effect.duration; while (true) { float maxDecrease = effect.magnitude - decreased; float decreaseRate = Time.deltaTime * delta; if (decreaseRate > maxDecrease) // Reached max damage { CurHealth -= maxDecrease; effect.magnitudeAlreadyApplied += maxDecrease; yield break; } else { CurHealth -= decreaseRate; decreased += decreaseRate; effect.magnitudeAlreadyApplied += decreaseRate; yield return null; } CurHealth = Mathf.Clamp(CurHealth, 0, MaxHealth); } } IEnumerator DecreaseHealth(float _amount, float rate = 1) { float decreased = 0f; while (true) { float maxDecrease = _amount - decreased; float decreaseRate = Time.deltaTime * rate; if (decreaseRate > maxDecrease) // Reached max damage { CurHealth -= maxDecrease; yield break; } else { CurHealth -= decreaseRate; decreased += decreaseRate; yield return null; } CurHealth = Mathf.Clamp(CurHealth, 0, MaxHealth); } } // ----------------------------------------------------------------------------- // To gradually increase a value - Health // ----------------------------------------------------------------------------- IEnumerator IncreaseHealth(EffectOnEntity effect) { float increased = effect.magnitudeAlreadyApplied; float delta = effect.magnitude / effect.duration; while (true) { float maxIncrease = effect.magnitude - increased; float increaseRate = Time.deltaTime * delta; if (increaseRate > maxIncrease) // Reached max damage { CurHealth += maxIncrease; effect.magnitudeAlreadyApplied += maxIncrease; yield break; } else { CurHealth += increaseRate; increased += increaseRate; effect.magnitudeAlreadyApplied += increaseRate; yield return null; } CurHealth = Mathf.Clamp(CurHealth, 0, MaxHealth); } } // ----------------------------------------------------------------------------- // To gradually decrease a value - Stamina // ----------------------------------------------------------------------------- IEnumerator DecreaseStamina(EffectOnEntity effect) { float decreased = effect.magnitudeAlreadyApplied; float delta = effect.magnitude / effect.duration; while (true) { float maxDecrease = effect.magnitude - decreased; float decreaseRate = Time.deltaTime * delta; if (decreaseRate > maxDecrease) // Reached max damage { CurStamina -= maxDecrease; effect.magnitudeAlreadyApplied += maxDecrease; yield break; } else { CurStamina -= decreaseRate; decreased += decreaseRate; effect.magnitudeAlreadyApplied += decreaseRate; yield return null; } CurStamina = Mathf.Clamp(CurStamina, 0, MaxStamina); } } // ----------------------------------------------------------------------------- // To gradually decrease a value - Stamina // ----------------------------------------------------------------------------- IEnumerator DecreaseMana(EffectOnEntity effect) { float decreased = effect.magnitudeAlreadyApplied; float delta = effect.magnitude / effect.duration; while (true) { float maxDecrease = effect.magnitude - decreased; float decreaseRate = Time.deltaTime * delta; if (decreaseRate > maxDecrease) // Reached max damage { CurMana -= maxDecrease; effect.magnitudeAlreadyApplied += maxDecrease; yield break; } else { CurMana -= decreaseRate; decreased += decreaseRate; effect.magnitudeAlreadyApplied += decreaseRate; yield return null; } CurMana = Mathf.Clamp(CurMana, 0, MaxMana); } } IEnumerator DecreaseStamina(float _amount, float rate = 1) { float decreased = 0f; while (true) { float maxDecrease = _amount - decreased; float decreaseRate = Time.deltaTime * rate; if (decreaseRate > maxDecrease) // Reached max damage { CurStamina -= maxDecrease; yield break; } else { CurStamina -= decreaseRate; decreased += decreaseRate; yield return null; } CurStamina = Mathf.Clamp(CurStamina, 0, MaxStamina); } } IEnumerator DecreaseMana(float _amount, float rate = 1) { float decreased = 0f; while (true) { float maxDecrease = _amount - decreased; float decreaseRate = Time.deltaTime * rate; if (decreaseRate > maxDecrease) // Reached max damage { CurMana -= maxDecrease; yield break; } else { CurMana -= decreaseRate; decreased += decreaseRate; yield return null; } CurMana = Mathf.Clamp(CurMana, 0, MaxMana); } } // ----------------------------------------------------------------------------- // To gradually increase a value - Stamina // ----------------------------------------------------------------------------- IEnumerator IncreaseStamina(EffectOnEntity effect) { float increased = effect.magnitudeAlreadyApplied; float delta = effect.magnitude / effect.duration; while (true) { float maxIncrease = effect.magnitude - increased; float increaseRate = Time.deltaTime * delta; if (increaseRate > maxIncrease) // Reached max damage { CurStamina += maxIncrease; effect.magnitudeAlreadyApplied += maxIncrease; yield break; } else { CurStamina += increaseRate; increased += increaseRate; effect.magnitudeAlreadyApplied += increaseRate; yield return null; } CurStamina = Mathf.Clamp(CurStamina, 0, MaxStamina); } } // ----------------------------------------------------------------------------- // To gradually increase a value - Mana // ----------------------------------------------------------------------------- IEnumerator IncreaseMana(EffectOnEntity effect) { float increased = effect.magnitudeAlreadyApplied; float delta = effect.magnitude / effect.duration; while (true) { float maxIncrease = effect.magnitude - increased; float increaseRate = Time.deltaTime * delta; if (increaseRate > maxIncrease) // Reached max damage { CurMana += maxIncrease; effect.magnitudeAlreadyApplied += maxIncrease; yield break; } else { CurMana += increaseRate; increased += increaseRate; effect.magnitudeAlreadyApplied += increaseRate; yield return null; } CurMana = Mathf.Clamp(CurMana, 0, MaxMana); } } private void Start() { InvokeRepeating("CheckActiveEffects", 0, 0.5f); } /// /// Checks which effects are active on the character and removes them from the list if they're expired. /// public void CheckActiveEffects() { for (int i = 0; i < activeEffects.Count; i++) { if (!activeEffects[i].isOnDuration) { // Check if effect has expired/done what it had to if (activeEffects[i].magnitudeAlreadyApplied >= activeEffects[i].magnitude) { activeEffects[i].isFinished = true; activeEffects.RemoveAt(i); } } else { // Check if effect has expired/done what it had to if (activeEffects[i].magnitudeAlreadyApplied >= activeEffects[i].duration) { activeEffects[i].isFinished = true; activeEffects.RemoveAt(i); } } } } /// /// Returns whenever an attribute is currently buffed, debuffed or not /// /// The attribute to check /// public EntityBaseAttributesState GetAttributeState(EntityBaseAttributes _attribute) { for (int i = 0; i < activeEffects.Count; i++) { if (activeEffects[i].effectType == ConsumableEffectType.DamageAttribute && activeEffects[i].onAttribute == _attribute) return EntityBaseAttributesState.Debuffed; if (activeEffects[i].effectType == ConsumableEffectType.FortifyAttribute && activeEffects[i].onAttribute == _attribute) return EntityBaseAttributesState.Buffed; } return EntityBaseAttributesState.Normal; } public EntityAttributesSaveData ToSaveData() { EntityAttributesSaveData newAttData = new EntityAttributesSaveData(attributes, derivedAttributes, activeEffects); return newAttData; } } }