diff --git a/Assets/Scripts/AbilitySystem/AbilityInstance/AbilityModifier.cs b/Assets/Scripts/AbilitySystem/AbilityInstance/AbilityModifier.cs index 9e87ae2f..7b27afd4 100644 --- a/Assets/Scripts/AbilitySystem/AbilityInstance/AbilityModifier.cs +++ b/Assets/Scripts/AbilitySystem/AbilityInstance/AbilityModifier.cs @@ -1,5 +1,5 @@ // ============================================================================ -// 2. ABILITY MODIFIER SYSTEM +// 2. ABILITY MODIFIER SYSTEM - Enhanced with Source Tracking // ============================================================================ using UnityEngine; @@ -30,31 +30,118 @@ public class AbilityModifier public string description = ""; public float duration = -1f; // -1 = permanent - // Factory methods for common modifiers - public static AbilityModifier CreateDamageBoost(float multiplier, string name = "Damage Boost") + // Source tracking - matches StatModifier pattern + public readonly object Source; + + // ======================================================================== + // CONSTRUCTORS - Multiple overloads like StatModifier + // ======================================================================== + + // Default constructor (for serialization) + public AbilityModifier() { - return new AbilityModifier + Source = null; + } + + // Constructor with source + public AbilityModifier(object source) + { + Source = source; + } + + // Copy constructor with new source + public AbilityModifier(AbilityModifier original, object newSource) + { + // Copy all values + manaCostMultiplier = original.manaCostMultiplier; + manaCostFlat = original.manaCostFlat; + healthCostMultiplier = original.healthCostMultiplier; + healthCostFlat = original.healthCostFlat; + classResourceCostMultiplier = original.classResourceCostMultiplier; + classResourceCostFlat = original.classResourceCostFlat; + + castTimeMultiplier = original.castTimeMultiplier; + cooldownMultiplier = original.cooldownMultiplier; + + damageMultiplier = original.damageMultiplier; + healingMultiplier = original.healingMultiplier; + durationMultiplier = original.durationMultiplier; + rangeMultiplier = original.rangeMultiplier; + + modifierName = original.modifierName; + description = original.description; + duration = original.duration; + + // Set new source + Source = newSource; + } + + // ======================================================================== + // FACTORY METHODS - Enhanced with source support + // ======================================================================== + + public static AbilityModifier CreateDamageBoost(float multiplier, string name = "Damage Boost", object source = null) + { + var modifier = new AbilityModifier(source) { damageMultiplier = multiplier, modifierName = name }; + return modifier; } - public static AbilityModifier CreateCooldownReduction(float reductionPercent, string name = "Cooldown Reduction") + public static AbilityModifier CreateCooldownReduction(float reductionPercent, string name = "Cooldown Reduction", object source = null) { - return new AbilityModifier + var modifier = new AbilityModifier(source) { cooldownMultiplier = 1f - (reductionPercent / 100f), modifierName = name }; + return modifier; } - public static AbilityModifier CreateManaCostReduction(float reductionPercent, string name = "Mana Cost Reduction") + public static AbilityModifier CreateManaCostReduction(float reductionPercent, string name = "Mana Cost Reduction", object source = null) { - return new AbilityModifier + var modifier = new AbilityModifier(source) { manaCostMultiplier = 1f - (reductionPercent / 100f), modifierName = name }; + return modifier; + } + + public static AbilityModifier CreateCastTimeReduction(float reductionPercent, string name = "Cast Time Reduction", object source = null) + { + var modifier = new AbilityModifier(source) + { + castTimeMultiplier = 1f - (reductionPercent / 100f), + modifierName = name + }; + return modifier; + } + + public static AbilityModifier CreateHealingBoost(float multiplier, string name = "Healing Boost", object source = null) + { + var modifier = new AbilityModifier(source) + { + healingMultiplier = multiplier, + modifierName = name + }; + return modifier; + } + + // ======================================================================== + // UTILITY METHODS + // ======================================================================== + + public bool HasSource(object source) + { + return Source != null && Source.Equals(source); + } + + public override string ToString() + { + string sourceStr = Source?.ToString() ?? "No Source"; + return $"{modifierName} (Source: {sourceStr})"; } } \ No newline at end of file diff --git a/Assets/Scripts/AbilitySystem/AbilityInstance/RuntimeAbilityInstance.cs b/Assets/Scripts/AbilitySystem/AbilityInstance/RuntimeAbilityInstance.cs index d1586ed2..e75b0127 100644 --- a/Assets/Scripts/AbilitySystem/AbilityInstance/RuntimeAbilityInstance.cs +++ b/Assets/Scripts/AbilitySystem/AbilityInstance/RuntimeAbilityInstance.cs @@ -2,8 +2,10 @@ // RUNTIME ABILITY WRAPPER - DROP-IN REPLACEMENT FOR BaseAbility // ============================================================================ +using Kryz.CharacterStats.Examples; using System; using System.Collections.Generic; +using System.Linq; using UnityEngine; // ============================================================================ @@ -163,7 +165,7 @@ public class RuntimeAbilityInstance } // ======================================================================== - // MODIFIER SYSTEM + // ENHANCED MODIFIER SYSTEM - Source-Aware Management // ======================================================================== public void AddModifier(AbilityModifier modifier) @@ -172,18 +174,86 @@ public class RuntimeAbilityInstance RecalculateModifiedValues(); } + public void AddModifier(AbilityModifier modifier, object source) + { + // Create a copy with the specified source + var modifierWithSource = new AbilityModifier(modifier, source); + activeModifiers.Add(modifierWithSource); + RecalculateModifiedValues(); + } + public void RemoveModifier(AbilityModifier modifier) { activeModifiers.Remove(modifier); RecalculateModifiedValues(); } + public bool RemoveAllModifiersFromSource(object source) + { + int numRemovals = activeModifiers.RemoveAll(mod => mod.Source != null && mod.Source.Equals(source)); + + if (numRemovals > 0) + { + RecalculateModifiedValues(); + return true; + } + return false; + } + + public bool HasModifiersFromSource(object source) + { + return activeModifiers.Any(mod => mod.Source != null && mod.Source.Equals(source)); + } + + public List GetModifiersFromSource(object source) + { + return activeModifiers.Where(mod => mod.Source != null && mod.Source.Equals(source)).ToList(); + } + public void RemoveAllModifiers() { activeModifiers.Clear(); RecalculateModifiedValues(); } + // ======================================================================== + // CONVENIENCE METHODS - Common source-based operations + // ======================================================================== + + // Add modifier from equipment + public void AddEquipmentModifier(AbilityModifier modifier, EquippableItem equipment) + { + AddModifier(modifier, equipment); + } + + // Add modifier from buff/effect + public void AddEffectModifier(AbilityModifier modifier, BaseEffect effect) + { + AddModifier(modifier, effect); + } + + // Add modifier from skill/talent + public void AddSkillModifier(AbilityModifier modifier, string skillSource) + { + AddModifier(modifier, skillSource); + } + + // Remove equipment modifiers when unequipping + public void RemoveEquipmentModifiers(EquippableItem equipment) + { + RemoveAllModifiersFromSource(equipment); + } + + // Remove effect modifiers when effect expires + public void RemoveEffectModifiers(BaseEffect effect) + { + RemoveAllModifiersFromSource(effect); + } + + // ======================================================================== + // MODIFIER CALCULATION + // ======================================================================== + private void RecalculateModifiedValues() { // Start with original values @@ -263,6 +333,31 @@ public class RuntimeAbilityInstance } } + // ======================================================================== + // DEBUG/UTILITY METHODS + // ======================================================================== + + public void PrintActiveModifiers() + { + Debug.Log($"=== Active Modifiers for {displayName} ==="); + foreach (var modifier in activeModifiers) + { + string sourceStr = modifier.Source?.ToString() ?? "No Source"; + Debug.Log($"- {modifier.modifierName} (Source: {sourceStr})"); + } + } + + public Dictionary GetModifierCountBySource() + { + var counts = new Dictionary(); + foreach (var modifier in activeModifiers) + { + var source = modifier.Source ?? "No Source"; + counts[source] = counts.ContainsKey(source) ? counts[source] + 1 : 1; + } + return counts; + } + // ======================================================================== // UTILITY METHODS // ========================================================================