diff --git a/Assets/1-Packs/3D/CharactersPack/KayKit_Adventurers_1.0_FREE/Characters/Skeleton_Enemy.controller b/Assets/1-Packs/3D/CharactersPack/KayKit_Adventurers_1.0_FREE/Characters/Skeleton_Enemy.controller
index fcf9d85c..7f712a11 100644
--- a/Assets/1-Packs/3D/CharactersPack/KayKit_Adventurers_1.0_FREE/Characters/Skeleton_Enemy.controller
+++ b/Assets/1-Packs/3D/CharactersPack/KayKit_Adventurers_1.0_FREE/Characters/Skeleton_Enemy.controller
@@ -236,7 +236,7 @@ AnimatorStateTransition:
m_HasFixedDuration: 1
m_InterruptionSource: 0
m_OrderedInterruption: 1
- m_CanTransitionToSelf: 1
+ m_CanTransitionToSelf: 0
--- !u!1101 &-3316037427580542980
AnimatorStateTransition:
m_ObjectHideFlags: 1
@@ -564,9 +564,9 @@ AnimatorStateTransition:
m_Mute: 0
m_IsExit: 0
serializedVersion: 3
- m_TransitionDuration: 0.2
+ m_TransitionDuration: 0.15
m_TransitionOffset: 0
- m_ExitTime: 0.8
+ m_ExitTime: 0.5
m_HasExitTime: 1
m_HasFixedDuration: 1
m_InterruptionSource: 0
diff --git a/Assets/Fantasy Skybox FREE/Panoramics/FS002/FS002_Night.mat b/Assets/Fantasy Skybox FREE/Panoramics/FS002/FS002_Night.mat
index 3dde5691..e12f787b 100644
--- a/Assets/Fantasy Skybox FREE/Panoramics/FS002/FS002_Night.mat
+++ b/Assets/Fantasy Skybox FREE/Panoramics/FS002/FS002_Night.mat
@@ -78,7 +78,7 @@ Material:
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- - _Rotation: 7.162766
+ - _Rotation: 6.1873918
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
diff --git a/Assets/Scenes/0-Splash.unity b/Assets/Scenes/0-Splash.unity
index 811428fd..2a521f14 100644
--- a/Assets/Scenes/0-Splash.unity
+++ b/Assets/Scenes/0-Splash.unity
@@ -2301,6 +2301,26 @@ PrefabInstance:
serializedVersion: 3
m_TransformParent: {fileID: 0}
m_Modifications:
+ - target: {fileID: 559795999353192350, guid: 7cf303e1116e7fb46ba92e7d73321eeb, type: 3}
+ propertyPath: m_AnchorMax.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 559795999353192350, guid: 7cf303e1116e7fb46ba92e7d73321eeb, type: 3}
+ propertyPath: m_AnchorMin.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 559795999353192350, guid: 7cf303e1116e7fb46ba92e7d73321eeb, type: 3}
+ propertyPath: m_SizeDelta.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 559795999353192350, guid: 7cf303e1116e7fb46ba92e7d73321eeb, type: 3}
+ propertyPath: m_AnchoredPosition.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 559795999353192350, guid: 7cf303e1116e7fb46ba92e7d73321eeb, type: 3}
+ propertyPath: m_AnchoredPosition.y
+ value: 0
+ objectReference: {fileID: 0}
- target: {fileID: 952476992021474036, guid: 7cf303e1116e7fb46ba92e7d73321eeb, type: 3}
propertyPath: m_AnchorMax.y
value: 0
@@ -2429,6 +2449,26 @@ PrefabInstance:
propertyPath: m_AnchoredPosition.y
value: -600
objectReference: {fileID: 0}
+ - target: {fileID: 3015579015349867821, guid: 7cf303e1116e7fb46ba92e7d73321eeb, type: 3}
+ propertyPath: m_AnchorMax.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 3015579015349867821, guid: 7cf303e1116e7fb46ba92e7d73321eeb, type: 3}
+ propertyPath: m_AnchorMin.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 3015579015349867821, guid: 7cf303e1116e7fb46ba92e7d73321eeb, type: 3}
+ propertyPath: m_SizeDelta.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 3015579015349867821, guid: 7cf303e1116e7fb46ba92e7d73321eeb, type: 3}
+ propertyPath: m_AnchoredPosition.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 3015579015349867821, guid: 7cf303e1116e7fb46ba92e7d73321eeb, type: 3}
+ propertyPath: m_AnchoredPosition.y
+ value: 0
+ objectReference: {fileID: 0}
- target: {fileID: 3044532144327822992, guid: 7cf303e1116e7fb46ba92e7d73321eeb, type: 3}
propertyPath: m_AnchorMax.y
value: 0
@@ -2513,6 +2553,26 @@ PrefabInstance:
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
+ - target: {fileID: 5126747884924751304, guid: 7cf303e1116e7fb46ba92e7d73321eeb, type: 3}
+ propertyPath: m_AnchorMax.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 5126747884924751304, guid: 7cf303e1116e7fb46ba92e7d73321eeb, type: 3}
+ propertyPath: m_AnchorMin.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 5126747884924751304, guid: 7cf303e1116e7fb46ba92e7d73321eeb, type: 3}
+ propertyPath: m_SizeDelta.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 5126747884924751304, guid: 7cf303e1116e7fb46ba92e7d73321eeb, type: 3}
+ propertyPath: m_AnchoredPosition.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 5126747884924751304, guid: 7cf303e1116e7fb46ba92e7d73321eeb, type: 3}
+ propertyPath: m_AnchoredPosition.y
+ value: 0
+ objectReference: {fileID: 0}
- target: {fileID: 6069245676466788546, guid: 7cf303e1116e7fb46ba92e7d73321eeb, type: 3}
propertyPath: m_AnchorMax.y
value: 0
diff --git a/Assets/Scriptables/Data/Resources/Abilities/Debug/Player/Mage/0-IceShard_ProjectileAbility.asset b/Assets/Scriptables/Data/Resources/Abilities/Debug/Player/Mage/0-IceShard_ProjectileAbility.asset
index 9de6557c..01c49208 100644
--- a/Assets/Scriptables/Data/Resources/Abilities/Debug/Player/Mage/0-IceShard_ProjectileAbility.asset
+++ b/Assets/Scriptables/Data/Resources/Abilities/Debug/Player/Mage/0-IceShard_ProjectileAbility.asset
@@ -29,7 +29,7 @@ MonoBehaviour:
- {fileID: 11400000, guid: 7b7a9c9ae4b8ece4eb680f621937c58a, type: 2}
- {fileID: 11400000, guid: 127f92fd14a21174695a692c0cf18746, type: 2}
castTime: 0.5
- manaCost: 3
+ manaCost: 30
healthCost: 0
classResourceCost: 0
spiritPowerReserveCost: 0
diff --git a/Assets/Scripts/AbilitySystem/AbilityInstance/Refactor.meta b/Assets/Scripts/AbilitySystem/AbilityInstance/Refactor.meta
new file mode 100644
index 00000000..279af8b7
--- /dev/null
+++ b/Assets/Scripts/AbilitySystem/AbilityInstance/Refactor.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: ebbaf77cf9aa1bf4686e2835b46e8e66
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/AbilitySystem/AbilityInstance/Refactor/CostCalculationContext.cs b/Assets/Scripts/AbilitySystem/AbilityInstance/Refactor/CostCalculationContext.cs
new file mode 100644
index 00000000..d82431c1
--- /dev/null
+++ b/Assets/Scripts/AbilitySystem/AbilityInstance/Refactor/CostCalculationContext.cs
@@ -0,0 +1,59 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+// ============================================================================
+// COST CALCULATION CONTEXT - Holds user stats for cost calculations
+// ============================================================================
+
+///
+/// Context containing user stats needed for cost calculations
+/// Allows ability cost calculation without direct user reference
+///
+public struct CostCalculationContext
+{
+ public float maxMana;
+ public float maxHealth;
+ public float currentMana;
+ public float currentHealth;
+ public float currentClassResource;
+
+ public static CostCalculationContext FromUser(Taggable user)
+ {
+ var context = new CostCalculationContext();
+
+ var mana = user.GetComponent();
+ if (mana != null)
+ {
+ context.maxMana = mana.GetMaxValue();
+ context.currentMana = mana.GetCurrentValue();
+ }
+
+ var health = user.GetComponent();
+ if (health != null)
+ {
+ context.maxHealth = health.GetMaxValue();
+ context.currentHealth = health.GetCurrentValue();
+ }
+
+ var classResource = user.GetComponent();
+ if (classResource != null)
+ {
+ context.currentClassResource = classResource.GetCurrentValue();
+ }
+
+ return context;
+ }
+
+ public static CostCalculationContext CreateMockContext(float maxMana = 100f, float maxHealth = 100f)
+ {
+ return new CostCalculationContext
+ {
+ maxMana = maxMana,
+ maxHealth = maxHealth,
+ currentMana = maxMana,
+ currentHealth = maxHealth,
+ currentClassResource = 100f
+ };
+ }
+}
diff --git a/Assets/Scripts/AbilitySystem/AbilityInstance/Refactor/CostCalculationContext.cs.meta b/Assets/Scripts/AbilitySystem/AbilityInstance/Refactor/CostCalculationContext.cs.meta
new file mode 100644
index 00000000..814fa7e9
--- /dev/null
+++ b/Assets/Scripts/AbilitySystem/AbilityInstance/Refactor/CostCalculationContext.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 5050e09038372134fbe8fa068698e68a
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/AbilitySystem/AbilityInstance/RuntimeAbilityInstance.cs b/Assets/Scripts/AbilitySystem/AbilityInstance/RuntimeAbilityInstance.cs
index e75b0127..5a9f5cb9 100644
--- a/Assets/Scripts/AbilitySystem/AbilityInstance/RuntimeAbilityInstance.cs
+++ b/Assets/Scripts/AbilitySystem/AbilityInstance/RuntimeAbilityInstance.cs
@@ -1,25 +1,20 @@
-// ============================================================================
-// RUNTIME ABILITY WRAPPER - DROP-IN REPLACEMENT FOR BaseAbility
-// ============================================================================
-
using Kryz.CharacterStats.Examples;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
-
// ============================================================================
-// 1. RUNTIME ABILITY INSTANCE - Wraps Your Existing BaseAbility
+// RUNTIME ABILITY INSTANCE - Context-Aware Version
// ============================================================================
///
-/// Runtime wrapper for BaseAbility that adds modifiers and behaviors
-/// Can be used anywhere you currently use BaseAbility references
+/// Runtime wrapper for BaseAbility with context-aware cost calculations
+/// Modifiers now properly affect total costs (flat + percentage combined)
///
public class RuntimeAbilityInstance
{
// ========================================================================
- // CORE DATA - Wraps your existing ScriptableObject
+ // CORE DATA
// ========================================================================
[SerializeField] private BaseAbility sourceAbility;
@@ -37,15 +32,13 @@ public class RuntimeAbilityInstance
public RuntimeAbilityInstance(BaseAbility source)
{
sourceAbility = source;
- currentCharges = GetMaxCharges(); // In case you add charges later
- RecalculateModifiedValues();
+ currentCharges = GetMaxCharges();
}
// ========================================================================
- // PROPERTIES - Direct access to original + modified values
+ // PROPERTIES - Direct access to original values
// ========================================================================
- // Original values (unchanged)
public BaseAbility SourceAbility => sourceAbility;
public string displayName => sourceAbility.displayName;
public Sprite Icon => sourceAbility.Icon;
@@ -55,15 +48,18 @@ public class RuntimeAbilityInstance
public bool castableWhileMoving => sourceAbility.castableWhileMoving;
public AbilityAnimationType animationType => sourceAbility.animationType;
- // Modified values (affected by modifiers)
- public float manaCost { get; private set; }
- public float healthCost { get; private set; }
- public float classResourceCost { get; private set; }
- public float spiritPowerReserveCost { get; private set; }
- public float percentMaxManaCost { get; private set; }
- public float percentMaxHealthCost { get; private set; }
- public float castTime { get; private set; }
- public float cooldown { get; private set; }
+ // Base costs (for display when no context available)
+ public float baseManaFlat => sourceAbility.manaCost;
+ public float baseHealthFlat => sourceAbility.healthCost;
+ public float baseClassResourceFlat => sourceAbility.classResourceCost;
+ public float baseManaPercent => sourceAbility.percentMaxManaCost;
+ public float baseHealthPercent => sourceAbility.percentMaxHealthCost;
+ public float baseCastTime => sourceAbility.castTime;
+ public float baseCooldown => sourceAbility.cooldown;
+
+ // Modified timing values (these don't need user context)
+ public float castTime => GetModifiedCastTime();
+ public float cooldown => GetModifiedCooldown();
// Runtime state properties
public float LastUsedTime => lastUsedTime;
@@ -73,23 +69,143 @@ public class RuntimeAbilityInstance
public List RuntimeBehaviors => new List(runtimeBehaviors);
// ========================================================================
- // EXECUTION METHODS - Same signature as your BaseAbility
+ // CONTEXT-AWARE COST CALCULATIONS
// ========================================================================
+ ///
+ /// Calculate final mana cost including modifiers (affects flat + percentage total)
+ ///
+ public float GetFinalManaCost(CostCalculationContext context)
+ {
+ // Calculate total base cost (flat + percentage)
+ float totalBaseCost = sourceAbility.manaCost + (context.maxMana * sourceAbility.percentMaxManaCost);
+
+ // Apply modifiers to the total cost
+ float modifiedCost = (totalBaseCost + GetTotalManaCostFlat()) * GetTotalManaCostMultiplier();
+
+ return Mathf.Max(0f, modifiedCost);
+ }
+
+ ///
+ /// Calculate final health cost including modifiers (affects flat + percentage total)
+ ///
+ public float GetFinalHealthCost(CostCalculationContext context)
+ {
+ // Calculate total base cost (flat + percentage)
+ float totalBaseCost = sourceAbility.healthCost + (context.maxHealth * sourceAbility.percentMaxHealthCost);
+
+ // Apply modifiers to the total cost
+ float modifiedCost = (totalBaseCost + GetTotalHealthCostFlat()) * GetTotalHealthCostMultiplier();
+
+ return Mathf.Max(0f, modifiedCost);
+ }
+
+ ///
+ /// Calculate final class resource cost (flat only, no percentage version)
+ ///
+ public float GetFinalClassResourceCost()
+ {
+ float modifiedCost = (sourceAbility.classResourceCost + GetTotalClassResourceFlat()) * GetTotalClassResourceMultiplier();
+ return Mathf.Max(0f, modifiedCost);
+ }
+
+ // Convenience overloads for when you have a user reference
+ public float GetFinalManaCost(Taggable user) => GetFinalManaCost(CostCalculationContext.FromUser(user));
+ public float GetFinalHealthCost(Taggable user) => GetFinalHealthCost(CostCalculationContext.FromUser(user));
+
+ // ========================================================================
+ // DISPLAY METHODS - For UI when no user context available
+ // ========================================================================
+
+ ///
+ /// Get display-friendly mana cost text
+ ///
+ public string GetManaCostDisplayText(CostCalculationContext? context = null)
+ {
+ if (context.HasValue)
+ {
+ return $"{GetFinalManaCost(context.Value):F0} Mana";
+ }
+ else
+ {
+ // Show base cost + modifiers when no context
+ float flatCost = baseManaFlat * GetTotalManaCostMultiplier() + GetTotalManaCostFlat();
+ string text = $"{Mathf.Max(0f, flatCost):F0}";
+
+ if (baseManaPercent > 0)
+ text += $" + {baseManaPercent:P0} Max";
+
+ return text + " Mana";
+ }
+ }
+
+ ///
+ /// Get display-friendly health cost text
+ ///
+ public string GetHealthCostDisplayText(CostCalculationContext? context = null)
+ {
+ if (context.HasValue)
+ {
+ return $"{GetFinalHealthCost(context.Value):F0} Health";
+ }
+ else
+ {
+ float flatCost = baseHealthFlat * GetTotalHealthCostMultiplier() + GetTotalHealthCostFlat();
+ string text = $"{Mathf.Max(0f, flatCost):F0}";
+
+ if (baseHealthPercent > 0)
+ text += $" + {baseHealthPercent:P0} Max";
+
+ return text + " Health";
+ }
+ }
+
+ ///
+ /// Get all cost information as formatted string
+ ///
+ public string GetAllCostsDisplayText(CostCalculationContext? context = null)
+ {
+ var costs = new List();
+
+ // Mana cost
+ if (baseManaFlat > 0 || baseManaPercent > 0)
+ costs.Add(GetManaCostDisplayText(context));
+
+ // Health cost
+ if (baseHealthFlat > 0 || baseHealthPercent > 0)
+ costs.Add(GetHealthCostDisplayText(context));
+
+ // Class resource cost
+ float classResourceCost = GetFinalClassResourceCost();
+ if (classResourceCost > 0)
+ costs.Add($"{classResourceCost:F0} Energy");
+
+ return costs.Count > 0 ? string.Join(", ", costs) : "No Cost";
+ }
+
+ // ========================================================================
+ // EXECUTION METHODS
+ // ========================================================================
+
+ Mana userMana;
+ Health userHealth;
+ public virtual void SpendResourcesNecessary(Taggable user)
+ {
+
+ userMana.ChangeValue(-GetFinalManaCost(user));
+ userHealth.ChangeValue(-GetFinalHealthCost(user));
+ //user.GetComponent()?.ChangeValue(-GetFinalClassResourceCost());
+ }
+
public virtual void Execute(Taggable user)
{
if (!CanExecute(user)) return;
- // Execute pre-cast behaviors
ExecuteBehaviors(BehaviorTrigger.PreCast, user, null, Vector3.zero);
-
- // Execute original ability
+ SpendResourcesNecessary(user);
sourceAbility.Execute(user);
-
- // Execute post-cast behaviors
ExecuteBehaviors(BehaviorTrigger.PostCast, user, null, Vector3.zero);
- // Update runtime state
lastUsedTime = Time.time;
}
@@ -98,6 +214,7 @@ public class RuntimeAbilityInstance
if (!CanExecute(user)) return;
ExecuteBehaviors(BehaviorTrigger.PreCast, user, null, point);
+ SpendResourcesNecessary(user);
sourceAbility.Execute(user, point);
ExecuteBehaviors(BehaviorTrigger.PostCast, user, null, point);
@@ -109,6 +226,7 @@ public class RuntimeAbilityInstance
if (!CanExecute(user)) return;
ExecuteBehaviors(BehaviorTrigger.PreCast, user, target, target.position);
+ SpendResourcesNecessary(user);
sourceAbility.Execute(user, target);
ExecuteBehaviors(BehaviorTrigger.PostCast, user, target, target.position);
@@ -121,83 +239,131 @@ public class RuntimeAbilityInstance
public bool CanExecute(Taggable user)
{
- // Check cooldown
if (IsOnCooldown) return false;
-
- // Check resources using modified costs
- return CanAffordResources(user);
+ return CanAffordResources(CostCalculationContext.FromUser(user));
}
- private bool CanAffordResources(Taggable user)
+ public bool CanAffordResources(CostCalculationContext context)
{
- // Use the modified costs, not original
- var userMana = user.GetComponent();
- if (userMana != null)
+ // Check mana cost
+ if (context.maxMana > 0)
{
- float finalManaCost = manaCost + userMana.GetMaxValue() * percentMaxManaCost;
- if (!userMana.EnoughMana(finalManaCost)) return false;
+ float finalManaCost = GetFinalManaCost(context);
+ if (context.currentMana < finalManaCost) return false;
}
- var userHealth = user.GetComponent();
- if (userHealth != null)
+ // Check health cost
+ if (context.maxHealth > 0)
{
- float finalHealthCost = healthCost + userHealth.GetMaxValue() * percentMaxHealthCost;
- if (userHealth.GetCurrentValue() <= finalHealthCost) return false;
+ float finalHealthCost = GetFinalHealthCost(context);
+ if (context.currentHealth <= finalHealthCost) return false;
}
- var userClassResource = user.GetComponent();
- if (userClassResource != null && classResourceCost > 0)
+ // Check class resource cost
+ if (context.currentClassResource > 0)
{
- if (userClassResource.GetCurrentValue() < classResourceCost) return false;
+ float finalClassResourceCost = GetFinalClassResourceCost();
+ if (context.currentClassResource < finalClassResourceCost) return false;
}
return true;
}
- public float GetFinalManaCost(Mana userMana)
+ // Convenience overload
+ public bool CanAffordResources(Taggable user) => CanAffordResources(CostCalculationContext.FromUser(user));
+
+ // ========================================================================
+ // MODIFIER CALCULATION HELPERS
+ // ========================================================================
+
+ private float GetTotalManaCostMultiplier()
{
- return manaCost + userMana.GetMaxValue() * percentMaxManaCost;
+ float multiplier = 1f;
+ foreach (var modifier in activeModifiers)
+ multiplier *= modifier.manaCostMultiplier;
+ return multiplier;
}
- public float GetFinalHealthCost(Health userHealth)
+ private float GetTotalManaCostFlat()
{
- return healthCost + userHealth.GetMaxValue() * percentMaxHealthCost;
+ float flat = 0f;
+ foreach (var modifier in activeModifiers)
+ flat += modifier.manaCostFlat;
+ return flat;
+ }
+
+ private float GetTotalHealthCostMultiplier()
+ {
+ float multiplier = 1f;
+ foreach (var modifier in activeModifiers)
+ multiplier *= modifier.healthCostMultiplier;
+ return multiplier;
+ }
+
+ private float GetTotalHealthCostFlat()
+ {
+ float flat = 0f;
+ foreach (var modifier in activeModifiers)
+ flat += modifier.healthCostFlat;
+ return flat;
+ }
+
+ private float GetTotalClassResourceMultiplier()
+ {
+ float multiplier = 1f;
+ foreach (var modifier in activeModifiers)
+ multiplier *= modifier.classResourceCostMultiplier;
+ return multiplier;
+ }
+
+ private float GetTotalClassResourceFlat()
+ {
+ float flat = 0f;
+ foreach (var modifier in activeModifiers)
+ flat += modifier.classResourceCostFlat;
+ return flat;
+ }
+
+ private float GetModifiedCastTime()
+ {
+ float time = sourceAbility.castTime;
+ foreach (var modifier in activeModifiers)
+ time *= modifier.castTimeMultiplier;
+ return Mathf.Max(0f, time);
+ }
+
+ private float GetModifiedCooldown()
+ {
+ float cd = sourceAbility.cooldown;
+ foreach (var modifier in activeModifiers)
+ cd *= modifier.cooldownMultiplier;
+ return Mathf.Max(0f, cd);
}
// ========================================================================
- // ENHANCED MODIFIER SYSTEM - Source-Aware Management
+ // MODIFIER MANAGEMENT (same as before)
// ========================================================================
public void AddModifier(AbilityModifier modifier)
{
activeModifiers.Add(modifier);
- 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;
+ return numRemovals > 0;
}
public bool HasModifiersFromSource(object source)
@@ -213,87 +379,39 @@ public class RuntimeAbilityInstance
public void RemoveAllModifiers()
{
activeModifiers.Clear();
- RecalculateModifiedValues();
}
// ========================================================================
- // CONVENIENCE METHODS - Common source-based operations
+ // CONVENIENCE METHODS
// ========================================================================
- // 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
- manaCost = sourceAbility.manaCost;
- healthCost = sourceAbility.healthCost;
- classResourceCost = sourceAbility.classResourceCost;
- spiritPowerReserveCost = sourceAbility.spiritPowerReserveCost;
- percentMaxManaCost = sourceAbility.percentMaxManaCost;
- percentMaxHealthCost = sourceAbility.percentMaxHealthCost;
- castTime = sourceAbility.castTime;
- cooldown = sourceAbility.cooldown;
-
- // Apply all modifiers
- foreach (var modifier in activeModifiers)
- {
- ApplyModifier(modifier);
- }
- }
-
- private void ApplyModifier(AbilityModifier modifier)
- {
- // Resource cost modifiers
- manaCost = manaCost * modifier.manaCostMultiplier + modifier.manaCostFlat;
- healthCost = healthCost * modifier.healthCostMultiplier + modifier.healthCostFlat;
- classResourceCost = classResourceCost * modifier.classResourceCostMultiplier + modifier.classResourceCostFlat;
-
- // Timing modifiers
- castTime *= modifier.castTimeMultiplier;
- cooldown *= modifier.cooldownMultiplier;
-
- // Ensure values don't go negative
- manaCost = Mathf.Max(0f, manaCost);
- healthCost = Mathf.Max(0f, healthCost);
- classResourceCost = Mathf.Max(0f, classResourceCost);
- castTime = Mathf.Max(0f, castTime);
- cooldown = Mathf.Max(0f, cooldown);
- }
-
- // ========================================================================
- // RUNTIME BEHAVIOR SYSTEM
+ // RUNTIME BEHAVIOR SYSTEM (same as before)
// ========================================================================
public void AddBehavior(RuntimeBehavior behavior)
@@ -333,31 +451,6 @@ 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