diff --git a/Assets/Prefabs/Enemies/Basic Enemy.prefab b/Assets/Prefabs/Enemies/Basic Enemy.prefab index f8aa615..d67a721 100644 --- a/Assets/Prefabs/Enemies/Basic Enemy.prefab +++ b/Assets/Prefabs/Enemies/Basic Enemy.prefab @@ -130,19 +130,20 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: attributes: - health: 10 - maxHealth: 10 - moveSpeed: 2 - luck: 0 - armor: 0 - level: 1 - experience: 0 - baseExperienceToLevelUp: 100 - damage: 1 - rangedDamage: 1 - meleeDamage: 1 - attackRange: 1 - attackSpeed: 1 + serializedAttributes: + - key: 0 + - key: 1 + - key: 2 + - key: 3 + - key: 4 + - key: 5 + - key: 6 + - key: 7 + - key: 8 + - key: 9 + - key: 10 + - key: 11 + - key: 12 --- !u!114 &9093693903318130491 MonoBehaviour: m_ObjectHideFlags: 0 diff --git a/Assets/Scenes/main.unity b/Assets/Scenes/main.unity index c030e02..e2ea7dd 100644 --- a/Assets/Scenes/main.unity +++ b/Assets/Scenes/main.unity @@ -7087,20 +7087,281 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 44b572240c4243c9954bd19967bfeb64, type: 3} m_Name: m_EditorClassIdentifier: - attributes: - health: 100 - maxHealth: 100 - moveSpeed: 5 - luck: 0 - armor: 0 - level: 1 - experience: 0 - baseExperienceToLevelUp: 5 - damage: 1 - rangedDamage: 1 - meleeDamage: 1 - attackRange: 1 - attackSpeed: 1 + serializationData: + SerializedFormat: 2 + SerializedBytes: + ReferencedUnityObjects: [] + SerializedBytesString: + Prefab: {fileID: 0} + PrefabModificationsReferencedUnityObjects: [] + PrefabModifications: [] + SerializationNodes: + - Name: attributes + Entry: 7 + Data: 0|Data.CharacterAttributes, Assembly-CSharp + - Name: attributes + Entry: 7 + Data: 1|System.Collections.Generic.Dictionary`2[[Data.Attribute, Assembly-CSharp],[Data.AttributeData`1[[System.Single, + mscorlib]], Assembly-CSharp]], mscorlib + - Name: comparer + Entry: 7 + Data: 2|System.Collections.Generic.EnumEqualityComparer`1[[Data.Attribute, + Assembly-CSharp]], mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 12 + Data: 13 + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 3 + Data: 0 + - Name: $v + Entry: 7 + Data: 3|Data.AttributeData`1[[System.Single, mscorlib]], Assembly-CSharp + - Name: Value + Entry: 4 + Data: 100 + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 3 + Data: 1 + - Name: $v + Entry: 7 + Data: 4|Data.AttributeData`1[[System.Single, mscorlib]], Assembly-CSharp + - Name: Value + Entry: 4 + Data: 100 + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 3 + Data: 2 + - Name: $v + Entry: 7 + Data: 5|Data.AttributeData`1[[System.Single, mscorlib]], Assembly-CSharp + - Name: Value + Entry: 4 + Data: 1 + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 3 + Data: 3 + - Name: $v + Entry: 7 + Data: 6|Data.AttributeData`1[[System.Single, mscorlib]], Assembly-CSharp + - Name: Value + Entry: 4 + Data: 0 + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 3 + Data: 4 + - Name: $v + Entry: 7 + Data: 7|Data.AttributeData`1[[System.Single, mscorlib]], Assembly-CSharp + - Name: Value + Entry: 4 + Data: 1 + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 3 + Data: 5 + - Name: $v + Entry: 7 + Data: 8|Data.AttributeData`1[[System.Single, mscorlib]], Assembly-CSharp + - Name: Value + Entry: 4 + Data: 5 + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 3 + Data: 6 + - Name: $v + Entry: 7 + Data: 9|Data.AttributeData`1[[System.Single, mscorlib]], Assembly-CSharp + - Name: Value + Entry: 4 + Data: 1 + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 3 + Data: 7 + - Name: $v + Entry: 7 + Data: 10|Data.AttributeData`1[[System.Single, mscorlib]], Assembly-CSharp + - Name: Value + Entry: 4 + Data: 1 + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 3 + Data: 8 + - Name: $v + Entry: 7 + Data: 11|Data.AttributeData`1[[System.Single, mscorlib]], Assembly-CSharp + - Name: Value + Entry: 4 + Data: 1 + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 3 + Data: 9 + - Name: $v + Entry: 7 + Data: 12|Data.AttributeData`1[[System.Single, mscorlib]], Assembly-CSharp + - Name: Value + Entry: 4 + Data: 1 + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 3 + Data: 10 + - Name: $v + Entry: 7 + Data: 13|Data.AttributeData`1[[System.Single, mscorlib]], Assembly-CSharp + - Name: Value + Entry: 4 + Data: 1 + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 3 + Data: 11 + - Name: $v + Entry: 7 + Data: 14|Data.AttributeData`1[[System.Single, mscorlib]], Assembly-CSharp + - Name: Value + Entry: 4 + Data: 0 + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 3 + Data: 12 + - Name: $v + Entry: 7 + Data: 15|Data.AttributeData`1[[System.Single, mscorlib]], Assembly-CSharp + - Name: Value + Entry: 4 + Data: 100 + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: --- !u!4 &1261447604 Transform: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/AI/Chaser.cs b/Assets/Scripts/AI/Chaser.cs index 86af3c9..cf3edad 100644 --- a/Assets/Scripts/AI/Chaser.cs +++ b/Assets/Scripts/AI/Chaser.cs @@ -4,6 +4,7 @@ using KBCore.Refs; using Pathfinding; using Systems; using UnityEngine; +using Attribute = Data.Attribute; namespace AI { @@ -27,7 +28,7 @@ namespace AI { if (!target || !aiPath) return; - aiPath.maxSpeed = character.attributes.MoveSpeed; + aiPath.maxSpeed = character.attributes.Get(Attribute.MoveSpeed); aiPath.destination = target.position; } diff --git a/Assets/Scripts/Data/Attribute.cs b/Assets/Scripts/Data/Attribute.cs new file mode 100644 index 0000000..422a3e9 --- /dev/null +++ b/Assets/Scripts/Data/Attribute.cs @@ -0,0 +1,19 @@ +namespace Data +{ + public enum Attribute + { + Health, + MaxHealth, + MoveSpeed, + Luck, + Armor, + Damage, + RangedDamage, + MeleeDamage, + AttackRange, + AttackSpeed, + Level, + Experience, + BaseExperienceToNextLevel, + } +} \ No newline at end of file diff --git a/Assets/Scripts/Data/Attribute.cs.meta b/Assets/Scripts/Data/Attribute.cs.meta new file mode 100644 index 0000000..2b6f213 --- /dev/null +++ b/Assets/Scripts/Data/Attribute.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9587f73172674bd1ad04d9e2327ad882 +timeCreated: 1754103975 \ No newline at end of file diff --git a/Assets/Scripts/Data/AttributeData.cs b/Assets/Scripts/Data/AttributeData.cs new file mode 100644 index 0000000..07c3792 --- /dev/null +++ b/Assets/Scripts/Data/AttributeData.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using Sirenix.OdinInspector; +using Sirenix.Serialization; + +namespace Data +{ + [Serializable] + public class AttributeData + { + [OdinSerialize] + public T Value { get; private set; } + public event Action OnChanged; + + public void Set(T value) + { + if (!EqualityComparer.Default.Equals(Value, value)) + { + Value = value; + OnChanged?.Invoke(Value); + } + } + + public void Modify(Func modifier) + { + Set(modifier(Value)); + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Data/AttributeData.cs.meta b/Assets/Scripts/Data/AttributeData.cs.meta new file mode 100644 index 0000000..61f975d --- /dev/null +++ b/Assets/Scripts/Data/AttributeData.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: dd15401c68cc46338799a2718a5e6960 +timeCreated: 1754104026 \ No newline at end of file diff --git a/Assets/Scripts/Data/AttributeEntry.cs b/Assets/Scripts/Data/AttributeEntry.cs new file mode 100644 index 0000000..69784cf --- /dev/null +++ b/Assets/Scripts/Data/AttributeEntry.cs @@ -0,0 +1,18 @@ +using System; +using Sirenix.OdinInspector; + +namespace Data +{ + [Serializable] + public class AttributeEntry + { + [HorizontalGroup("Split", 0.4f)] + [LabelWidth(100)] + public Attribute key; + + [HorizontalGroup("Split", 0.6f)] + [LabelWidth(50)] + [InlineProperty] + public AttributeData value; + } +} \ No newline at end of file diff --git a/Assets/Scripts/Data/AttributeEntry.cs.meta b/Assets/Scripts/Data/AttributeEntry.cs.meta new file mode 100644 index 0000000..b043020 --- /dev/null +++ b/Assets/Scripts/Data/AttributeEntry.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 056d8fc09bcc477fba9ff895cde4bb6e +timeCreated: 1754105855 \ No newline at end of file diff --git a/Assets/Scripts/Data/Character.cs b/Assets/Scripts/Data/Character.cs index 2788692..2faffdb 100644 --- a/Assets/Scripts/Data/Character.cs +++ b/Assets/Scripts/Data/Character.cs @@ -1,11 +1,17 @@ +using System; using Sirenix.OdinInspector; using Sirenix.Serialization; using UnityEngine; namespace Data { - public class Character : MonoBehaviour + public class Character : SerializedMonoBehaviour { - [OdinSerialize, InlineProperty] public CharacterAttributes attributes = new(); + [OdinSerialize] public CharacterAttributes attributes = new(); + + private void Start() + { + attributes.Init(); + } } } \ No newline at end of file diff --git a/Assets/Scripts/Data/CharacterAttributes.cs b/Assets/Scripts/Data/CharacterAttributes.cs index 859630b..de01819 100644 --- a/Assets/Scripts/Data/CharacterAttributes.cs +++ b/Assets/Scripts/Data/CharacterAttributes.cs @@ -1,348 +1,113 @@ using System; +using System.Collections.Generic; +using System.Runtime.Serialization; using Sirenix.OdinInspector; using Sirenix.Serialization; +using UnityEngine; namespace Data { - public enum Stat - { - Health, - MaxHealth, - MoveSpeed, - Luck, - Armor, - Damage, - RangedDamage, - MeleeDamage, - AttackRange, - AttackSpeed - } - [Serializable] public class CharacterAttributes { - [OdinSerialize] public float health = 100f; - [OdinSerialize] public float maxHealth = 100f; - [OdinSerialize] public float moveSpeed = 5f; - [OdinSerialize] public float luck = 0f; - [OdinSerialize] public float armor = 0f; - [OdinSerialize] public int level = 1; - [OdinSerialize] public int experience = 0; - [OdinSerialize] public int baseExperienceToLevelUp = 100; + private float lastLevel = 1f; - [OdinSerialize, PropertyTooltip("This is damage multiplier")] - public float damage = 1f; - - [OdinSerialize, PropertyTooltip("This is damage multiplier for ranged attacks")] - public float rangedDamage = 1f; - - [OdinSerialize, PropertyTooltip("This is damage multiplier for melee attacks")] - public float meleeDamage = 1f; - - [OdinSerialize] public float attackRange = 16f; - [OdinSerialize] public float attackSpeed = 1f; - - public event Action OnHealthChanged; - public event Action OnMaxHealthChanged; - public event Action OnMoveSpeedChanged; - public event Action OnLuckChanged; - public event Action OnArmorChanged; - public event Action OnDamageChanged; - public event Action OnRangedDamageChanged; - public event Action OnMeleeDamageChanged; - public event Action OnAttackRangeChanged; - public event Action OnAttackSpeedChanged; + [OdinSerialize, DictionaryDrawerSettings(KeyLabel = "Stat", ValueLabel = "Value", DisplayMode = DictionaryDisplayOptions.OneLine)] + private Dictionary> attributes = new(); - public event Action OnExperienceChanged; - public event Action OnLevelChanged; public event Action OnLevelUp; - public float Health + public CharacterAttributes() { - get => health; - private set + foreach (Attribute attr in Enum.GetValues(typeof(Attribute))) { - if (Math.Abs(health - value) < float.Epsilon) return; - health = value; - OnHealthChanged?.Invoke(health); - } - } - - public float MaxHealth - { - get => maxHealth; - private set - { - if (Math.Abs(maxHealth - value) < float.Epsilon) return; - maxHealth = value; - OnMaxHealthChanged?.Invoke(maxHealth); - } - } - - public float MoveSpeed - { - get => moveSpeed; - private set - { - if (Math.Abs(moveSpeed - value) < float.Epsilon) return; - moveSpeed = value; - OnMoveSpeedChanged?.Invoke(moveSpeed); - } - } - - public float Luck - { - get => luck; - private set - { - if (Math.Abs(luck - value) < float.Epsilon) return; - luck = value; - OnLuckChanged?.Invoke(luck); - } - } - - public float Armor - { - get => armor; - private set - { - if (Math.Abs(armor - value) < float.Epsilon) return; - armor = value; - OnArmorChanged?.Invoke(armor); - } - } - - public float Damage - { - get => damage; - private set - { - if (Math.Abs(damage - value) < float.Epsilon) return; - damage = value; - OnDamageChanged?.Invoke(damage); - } - } - - public float RangedDamage - { - get => rangedDamage; - private set - { - if (Math.Abs(rangedDamage - value) < float.Epsilon) return; - rangedDamage = value; - OnRangedDamageChanged?.Invoke(rangedDamage); - } - } - - public float MeleeDamage - { - get => meleeDamage; - private set - { - if (Math.Abs(meleeDamage - value) < float.Epsilon) return; - meleeDamage = value; - OnMeleeDamageChanged?.Invoke(meleeDamage); - } - } - - public float AttackRange - { - get => attackRange; - private set - { - if (Math.Abs(attackRange - value) < float.Epsilon) return; - attackRange = value; - OnAttackRangeChanged?.Invoke(attackRange); - } - } - - public float AttackSpeed - { - get => attackSpeed; - private set - { - if (Math.Abs(attackSpeed - value) < float.Epsilon) return; - attackSpeed = value; - OnAttackSpeedChanged?.Invoke(attackSpeed); + if (!attributes.ContainsKey(attr)) + attributes[attr] = new AttributeData(); } } - public int Experience - { - get => experience; - private set - { - if (experience == value) return; - experience = value; - OnExperienceChanged?.Invoke(experience); - - if (experience >= ExperienceToNextLevel()) - { - Level++; - experience -= ExperienceToNextLevel(); - experience = Math.Min(0, experience); - } - else if (experience < 0) - { - experience = 0; - } - } - } + public float Get(Attribute attr) => attributes[attr].Value; - public int Level - { - get => level; - private set - { - if (level == value) return; - level = value; - OnLevelChanged?.Invoke(level); - OnLevelUp?.Invoke(); - } - } - - public void SetHealth(float value) - { - Health = Math.Clamp(value, 0, MaxHealth); - } - - public void SetMaxHealth(float value) - { - MaxHealth = Math.Max(value, 0); - if (Health > MaxHealth) - { - Health = MaxHealth; - } - } - - public void SetMoveSpeed(float value) - { - MoveSpeed = Math.Max(value, 0); - } - - public void SetLuck(float value) - { - Luck = Math.Max(value, 0); - } - - public void SetArmor(float value) - { - Armor = Math.Max(value, 0); - } - - public void SetDamage(float value) - { - Damage = Math.Max(value, 0); - } - - public void SetRangedDamage(float value) - { - RangedDamage = Math.Max(value, 0); - } - - public void SetMeleeDamage(float value) - { - MeleeDamage = Math.Max(value, 0); - } - - public void SetAttackRange(float value) - { - AttackRange = Math.Max(value, 0); - } - - public void SetAttackSpeed(float value) - { - AttackSpeed = Math.Max(value, 0); - } - - public void SetExperience(int value) - { - Experience = Math.Max(value, 0); - } + public void Set(Attribute attr, float value) => attributes[attr].Set(value); - public void SetLevel(int value) - { - Level = Math.Max(value, 1); - } + public void Modify(Attribute attr, float delta) => attributes[attr].Set(attributes[attr].Value + delta); - public void ModifyHealth(float delta) - { - SetHealth(Health + delta); - } - - public void ModifyMaxHealth(float delta) - { - SetMaxHealth(MaxHealth + delta); - } - - public void ModifyMoveSpeed(float delta) - { - SetMoveSpeed(MoveSpeed + delta); - } - - public void ModifyLuck(float delta) - { - SetLuck(Luck + delta); - } - - public void ModifyArmor(float delta) - { - SetArmor(Armor + delta); - } - - public void ModifyDamage(float delta) - { - SetDamage(Damage + delta); - } - - public void ModifyRangedDamage(float delta) - { - SetRangedDamage(RangedDamage + delta); - } - - public void ModifyMeleeDamage(float delta) - { - SetMeleeDamage(MeleeDamage + delta); - } - - public void ModifyAttackRange(float delta) - { - SetAttackRange(AttackRange + delta); - } - - public void ModifyAttackSpeed(float delta) - { - SetAttackSpeed(AttackSpeed + delta); - } + public void Subscribe(Attribute attr, Action listener) => attributes[attr].OnChanged += listener; - public void ModifyExperience(int delta) - { - SetExperience(Experience + delta); - } - - public void ModifyLevel(int delta) - { - SetLevel(Level + delta); - } + public void Unsubscribe(Attribute attr, Action listener) => attributes[attr].OnChanged -= listener; public void Reset() { - Health = MaxHealth = 100f; - MoveSpeed = 5f; - Luck = 0f; - Armor = 0f; - Damage = 1f; - RangedDamage = 1f; - MeleeDamage = 1f; - AttackRange = 16f; - AttackSpeed = 1f; - Level = 1; - Experience = 0; + Set(Attribute.Health, Get(Attribute.MaxHealth)); + Set(Attribute.MoveSpeed, 5f); + Set(Attribute.Luck, 0f); + Set(Attribute.Armor, 0f); + Set(Attribute.Damage, 1f); + Set(Attribute.RangedDamage, 1f); + Set(Attribute.MeleeDamage, 1f); + Set(Attribute.AttackRange, 1f); + Set(Attribute.AttackSpeed, 1f); + Set(Attribute.Level, 1f); + Set(Attribute.Experience, 0f); + Set(Attribute.BaseExperienceToNextLevel, 100f); + } + + /* + * health: 10 + maxHealth: 10 + moveSpeed: 2 + luck: 0 + armor: 0 + level: 1 + experience: 0 + baseExperienceToLevelUp: 100 + damage: 1 + rangedDamage: 1 + meleeDamage: 1 + attackRange: 1 + attackSpeed: 1 + + basic enemy btw + */ + + public void Init() + { + foreach (Attribute attr in Enum.GetValues(typeof(Attribute))) + { + if (!attributes.ContainsKey(attr)) + attributes[attr] = new AttributeData(); + } + + lastLevel = Get(Attribute.Level); + + Subscribe(Attribute.Experience, OnExperienceChanged); } private int ExperienceToNextLevel() { - return (int)(baseExperienceToLevelUp * Math.Pow(Level, 2)); + return (int)(Get(Attribute.BaseExperienceToNextLevel) * Math.Pow(Get(Attribute.Level), 2)); + } + + private void OnExperienceChanged(float newExp) + { + var xpToNext = ExperienceToNextLevel(); + + if (newExp >= xpToNext) + { + Modify(Attribute.Level, 1f); + Set(Attribute.Experience, newExp - xpToNext); + } + else if (newExp < 0) + { + Set(Attribute.Experience, 0f); + } + + var currentLevel = Get(Attribute.Level); + if (currentLevel > lastLevel) + { + lastLevel = currentLevel; + OnLevelUp?.Invoke(); + } } } } \ No newline at end of file diff --git a/Assets/Scripts/Modifiers/FlatStatModifier.cs b/Assets/Scripts/Modifiers/FlatStatModifier.cs index 822df16..fa7dcae 100644 --- a/Assets/Scripts/Modifiers/FlatStatModifier.cs +++ b/Assets/Scripts/Modifiers/FlatStatModifier.cs @@ -1,13 +1,14 @@ using System; using Data; using Interfaces; +using Attribute = Data.Attribute; namespace Modifiers { [Serializable] public class FlatStatModifier : IStatModifier { - public Stat stat; + public Attribute stat; public float value; public string Description => BuildDescription(); @@ -30,35 +31,35 @@ namespace Modifiers { switch (stat) { - case Stat.Health: - attributes.ModifyHealth(value); + case Attribute.Health: + attributes.Modify(Attribute.Health, value); break; - case Stat.MaxHealth: - attributes.ModifyMaxHealth(value); + case Attribute.MaxHealth: + attributes.Modify(Attribute.MaxHealth, value); break; - case Stat.MoveSpeed: - attributes.ModifyMoveSpeed(value); + case Attribute.MoveSpeed: + attributes.Modify(Attribute.MoveSpeed, value); break; - case Stat.Luck: - attributes.ModifyLuck(value); + case Attribute.Luck: + attributes.Modify(Attribute.Luck, value); break; - case Stat.Armor: - attributes.ModifyArmor(value); + case Attribute.Armor: + attributes.Modify(Attribute.Armor, value); break; - case Stat.Damage: - attributes.ModifyDamage(value); + case Attribute.Damage: + attributes.Modify(Attribute.Damage, value); break; - case Stat.RangedDamage: - attributes.ModifyRangedDamage(value); + case Attribute.RangedDamage: + attributes.Modify(Attribute.RangedDamage, value); break; - case Stat.MeleeDamage: - attributes.ModifyMeleeDamage(value); + case Attribute.MeleeDamage: + attributes.Modify(Attribute.MeleeDamage, value); break; - case Stat.AttackRange: - attributes.ModifyAttackRange(value); + case Attribute.AttackRange: + attributes.Modify(Attribute.AttackRange, value); break; - case Stat.AttackSpeed: - attributes.ModifyAttackSpeed(value); + case Attribute.AttackSpeed: + attributes.Modify(Attribute.AttackSpeed, value); break; default: throw new ArgumentOutOfRangeException(); diff --git a/Assets/Scripts/Modifiers/HealOnKillModifier.cs b/Assets/Scripts/Modifiers/HealOnKillModifier.cs index 39d5c2f..7bb2155 100644 --- a/Assets/Scripts/Modifiers/HealOnKillModifier.cs +++ b/Assets/Scripts/Modifiers/HealOnKillModifier.cs @@ -3,6 +3,7 @@ using Data; using Interfaces; using Systems; using UnityEngine; +using Attribute = Data.Attribute; namespace Modifiers { @@ -19,7 +20,7 @@ namespace Modifiers public void OnKill(GameObject killer, GameObject victim) { killer.TryGetComponent(out Character character); - character?.attributes.ModifyHealth(value); + character?.attributes.Modify(Attribute.Health, value); } } } \ No newline at end of file diff --git a/Assets/Scripts/Modifiers/PercentStatModifier.cs b/Assets/Scripts/Modifiers/PercentStatModifier.cs index 37d1fc1..3a80601 100644 --- a/Assets/Scripts/Modifiers/PercentStatModifier.cs +++ b/Assets/Scripts/Modifiers/PercentStatModifier.cs @@ -1,6 +1,7 @@ using System; using Data; using Interfaces; +using Attribute = Data.Attribute; namespace Modifiers { @@ -9,51 +10,20 @@ namespace Modifiers { private float lastAppliedAmount; - public Stat stat; + public Attribute stat; public float percent; public string Description => GetDescription(); public void Apply(CharacterAttributes attributes) { - var baseValue = GetBaseValue(attributes); + var baseValue = attributes.Get(stat); lastAppliedAmount = baseValue * percent; - - var flatModifier = new FlatStatModifier - { - value = lastAppliedAmount, - stat = stat - }; - - flatModifier.Apply(attributes); + attributes.Modify(stat, lastAppliedAmount); } public void Remove(CharacterAttributes attributes) { - var flatModifier = new FlatStatModifier - { - value = -lastAppliedAmount, - stat = stat - }; - - flatModifier.Apply(attributes); - } - - private T GetBaseValue(CharacterAttributes attributes) - { - return stat switch - { - Stat.Health => (T)(object)attributes.Health, - Stat.MaxHealth => (T)(object)attributes.MaxHealth, - Stat.MoveSpeed => (T)(object)attributes.MoveSpeed, - Stat.Luck => (T)(object)attributes.Luck, - Stat.Armor => (T)(object)attributes.Armor, - Stat.Damage => (T)(object)attributes.Damage, - Stat.RangedDamage => (T)(object)attributes.RangedDamage, - Stat.MeleeDamage => (T)(object)attributes.MeleeDamage, - Stat.AttackRange => (T)(object)attributes.AttackRange, - Stat.AttackSpeed => (T)(object)attributes.AttackSpeed, - _ => throw new System.ArgumentOutOfRangeException() - }; + attributes.Modify(stat, -lastAppliedAmount); } private string GetDescription() diff --git a/Assets/Scripts/Systems/DeathHandler.cs b/Assets/Scripts/Systems/DeathHandler.cs index 4abfb8e..a9906f0 100644 --- a/Assets/Scripts/Systems/DeathHandler.cs +++ b/Assets/Scripts/Systems/DeathHandler.cs @@ -13,12 +13,12 @@ namespace Systems private void OnEnable() { - character.attributes.OnHealthChanged += OnHealthChanged; + character.attributes.Subscribe(Attribute.Health, OnHealthChanged); } private void OnDisable() { - character.attributes.OnHealthChanged -= OnHealthChanged; + character.attributes.Unsubscribe(Attribute.Health, OnHealthChanged); } private void OnHealthChanged(float newHealth) diff --git a/Assets/Scripts/Systems/EnemyDeathBehavior.cs b/Assets/Scripts/Systems/EnemyDeathBehavior.cs index 409764c..6e93b11 100644 --- a/Assets/Scripts/Systems/EnemyDeathBehavior.cs +++ b/Assets/Scripts/Systems/EnemyDeathBehavior.cs @@ -2,6 +2,7 @@ using System; using Interfaces; using Sirenix.Serialization; using UnityEngine; +using Attribute = Data.Attribute; namespace Systems { @@ -14,7 +15,7 @@ namespace Systems public void Die(GameObject killer = null) { - GameManager.Instance.Player.attributes.ModifyExperience(expReward); + GameManager.Instance.Player.attributes.Modify(Attribute.Experience, expReward); GameManager.Instance.AddCoins(coinReward); OnAnyEnemyKilled?.Invoke(killer ?? GameManager.Instance.Player.gameObject, gameObject); diff --git a/Assets/Scripts/Systems/Health.cs b/Assets/Scripts/Systems/Health.cs index f404f8d..303c0cb 100644 --- a/Assets/Scripts/Systems/Health.cs +++ b/Assets/Scripts/Systems/Health.cs @@ -2,6 +2,7 @@ using System; using Data; using KBCore.Refs; using UnityEngine; +using Attribute = Data.Attribute; namespace Systems { @@ -19,15 +20,15 @@ namespace Systems private void Start() { - character.attributes.SetHealth(initialHealth); + character.attributes.Set(Attribute.Health, initialHealth); } public void TakeDamage(float damage, GameObject attacker = null) { lastAttacker = attacker; - var effectiveDamage = Math.Max(damage - character.attributes.Armor, 1); - character.attributes.ModifyHealth(-effectiveDamage); + var effectiveDamage = Math.Max(damage - character.attributes.Get(Attribute.Armor), 1); + character.attributes.Modify(Attribute.Health, -effectiveDamage); if (damageSound) { diff --git a/Assets/Scripts/Systems/Movement.cs b/Assets/Scripts/Systems/Movement.cs index 7007d6b..391489a 100644 --- a/Assets/Scripts/Systems/Movement.cs +++ b/Assets/Scripts/Systems/Movement.cs @@ -3,6 +3,7 @@ using Data; using KBCore.Refs; using UnityEngine; using UnityEngine.InputSystem; +using Attribute = Data.Attribute; namespace Systems { @@ -43,7 +44,7 @@ namespace Systems { if (!rb) return; - var velocity = new Vector2(movementInput.x, movementInput.y).normalized * character.attributes.MoveSpeed; + var velocity = new Vector2(movementInput.x, movementInput.y).normalized * character.attributes.Get(Attribute.MoveSpeed); rb.linearVelocity = velocity; } } diff --git a/Assets/Scripts/UI/GameHud.cs b/Assets/Scripts/UI/GameHud.cs index 0f2e6ed..1234482 100644 --- a/Assets/Scripts/UI/GameHud.cs +++ b/Assets/Scripts/UI/GameHud.cs @@ -3,6 +3,7 @@ using Systems; using TMPro; using UnityEngine; using UnityEngine.UI; +using Attribute = Data.Attribute; namespace UI { @@ -18,11 +19,11 @@ namespace UI var player = GameManager.Instance.Player; if (!player) return; - expText.text = $"EXP: {player.attributes.Experience}"; + expText.text = $"EXP: {player.attributes.Get(Attribute.Experience)}"; coinsText.text = $"Coins: {GameManager.Instance.Coins}"; roundTimeLeftText.text = $"{GameManager.Instance.RoundTimeLeft:F1}s"; - healthSlider.maxValue = player.attributes.MaxHealth; - healthSlider.value = player.attributes.Health; + healthSlider.maxValue = player.attributes.Get(Attribute.MaxHealth); + healthSlider.value = player.attributes.Get(Attribute.Health); } } } \ No newline at end of file diff --git a/Assets/Scripts/UI/LevelUpHud.cs b/Assets/Scripts/UI/LevelUpHud.cs index a254d47..05d3831 100644 --- a/Assets/Scripts/UI/LevelUpHud.cs +++ b/Assets/Scripts/UI/LevelUpHud.cs @@ -5,11 +5,13 @@ using KBCore.Refs; using Shop; using Systems; using UnityEngine; +using Attribute = Data.Attribute; namespace UI { public class LevelUpHud : MonoBehaviour { + private float previousLevel = 1f; private List currentSlots = new(); private List currentItemChoices = new(); private List currentWeaponChoices = new(); diff --git a/Assets/Scripts/Weapons/Weapon.cs b/Assets/Scripts/Weapons/Weapon.cs index 6d9798c..0a4ee5b 100644 --- a/Assets/Scripts/Weapons/Weapon.cs +++ b/Assets/Scripts/Weapons/Weapon.cs @@ -4,6 +4,7 @@ using Interfaces; using Sirenix.OdinInspector; using Sirenix.Serialization; using UnityEngine; +using Attribute = Data.Attribute; namespace Weapons { @@ -27,18 +28,18 @@ namespace Weapons private float GetFinalAttackSpeed() { - return character.attributes.AttackSpeed * weaponStats.attackSpeed; + return character.attributes.Get(Attribute.AttackSpeed) * weaponStats.attackSpeed; } protected float GetFinalDamage() { - return weaponStats.damage + character.attributes.Damage * - (weaponStats.damageType == DamageType.Melee ? character.attributes.MeleeDamage : character.attributes.RangedDamage); + return weaponStats.damage + character.attributes.Get(Attribute.Damage) * + (weaponStats.damageType == DamageType.Melee ? character.attributes.Get(Attribute.MeleeDamage) : character.attributes.Get(Attribute.RangedDamage)); } protected float GetFinalRange() { - return weaponStats.range * character.attributes.AttackRange; + return weaponStats.range * character.attributes.Get(Attribute.AttackRange); } protected void PlayShotSound()