Ability Runtime instances, modifiers and behaviours (WIP)
This commit is contained in:
parent
d7eb479da7
commit
c4d084acb2
@ -236,7 +236,7 @@ AnimatorStateTransition:
|
|||||||
m_HasFixedDuration: 1
|
m_HasFixedDuration: 1
|
||||||
m_InterruptionSource: 0
|
m_InterruptionSource: 0
|
||||||
m_OrderedInterruption: 1
|
m_OrderedInterruption: 1
|
||||||
m_CanTransitionToSelf: 1
|
m_CanTransitionToSelf: 0
|
||||||
--- !u!1101 &-3316037427580542980
|
--- !u!1101 &-3316037427580542980
|
||||||
AnimatorStateTransition:
|
AnimatorStateTransition:
|
||||||
m_ObjectHideFlags: 1
|
m_ObjectHideFlags: 1
|
||||||
@ -564,9 +564,9 @@ AnimatorStateTransition:
|
|||||||
m_Mute: 0
|
m_Mute: 0
|
||||||
m_IsExit: 0
|
m_IsExit: 0
|
||||||
serializedVersion: 3
|
serializedVersion: 3
|
||||||
m_TransitionDuration: 0.2
|
m_TransitionDuration: 0.15
|
||||||
m_TransitionOffset: 0
|
m_TransitionOffset: 0
|
||||||
m_ExitTime: 0.8
|
m_ExitTime: 0.5
|
||||||
m_HasExitTime: 1
|
m_HasExitTime: 1
|
||||||
m_HasFixedDuration: 1
|
m_HasFixedDuration: 1
|
||||||
m_InterruptionSource: 0
|
m_InterruptionSource: 0
|
||||||
|
@ -78,7 +78,7 @@ Material:
|
|||||||
- _Mode: 0
|
- _Mode: 0
|
||||||
- _OcclusionStrength: 1
|
- _OcclusionStrength: 1
|
||||||
- _Parallax: 0.02
|
- _Parallax: 0.02
|
||||||
- _Rotation: 7.162766
|
- _Rotation: 6.1873918
|
||||||
- _SmoothnessTextureChannel: 0
|
- _SmoothnessTextureChannel: 0
|
||||||
- _SpecularHighlights: 1
|
- _SpecularHighlights: 1
|
||||||
- _SrcBlend: 1
|
- _SrcBlend: 1
|
||||||
|
@ -2301,6 +2301,26 @@ PrefabInstance:
|
|||||||
serializedVersion: 3
|
serializedVersion: 3
|
||||||
m_TransformParent: {fileID: 0}
|
m_TransformParent: {fileID: 0}
|
||||||
m_Modifications:
|
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}
|
- target: {fileID: 952476992021474036, guid: 7cf303e1116e7fb46ba92e7d73321eeb, type: 3}
|
||||||
propertyPath: m_AnchorMax.y
|
propertyPath: m_AnchorMax.y
|
||||||
value: 0
|
value: 0
|
||||||
@ -2429,6 +2449,26 @@ PrefabInstance:
|
|||||||
propertyPath: m_AnchoredPosition.y
|
propertyPath: m_AnchoredPosition.y
|
||||||
value: -600
|
value: -600
|
||||||
objectReference: {fileID: 0}
|
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}
|
- target: {fileID: 3044532144327822992, guid: 7cf303e1116e7fb46ba92e7d73321eeb, type: 3}
|
||||||
propertyPath: m_AnchorMax.y
|
propertyPath: m_AnchorMax.y
|
||||||
value: 0
|
value: 0
|
||||||
@ -2513,6 +2553,26 @@ PrefabInstance:
|
|||||||
propertyPath: m_AnchoredPosition.y
|
propertyPath: m_AnchoredPosition.y
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 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}
|
- target: {fileID: 6069245676466788546, guid: 7cf303e1116e7fb46ba92e7d73321eeb, type: 3}
|
||||||
propertyPath: m_AnchorMax.y
|
propertyPath: m_AnchorMax.y
|
||||||
value: 0
|
value: 0
|
||||||
|
@ -29,7 +29,7 @@ MonoBehaviour:
|
|||||||
- {fileID: 11400000, guid: 7b7a9c9ae4b8ece4eb680f621937c58a, type: 2}
|
- {fileID: 11400000, guid: 7b7a9c9ae4b8ece4eb680f621937c58a, type: 2}
|
||||||
- {fileID: 11400000, guid: 127f92fd14a21174695a692c0cf18746, type: 2}
|
- {fileID: 11400000, guid: 127f92fd14a21174695a692c0cf18746, type: 2}
|
||||||
castTime: 0.5
|
castTime: 0.5
|
||||||
manaCost: 3
|
manaCost: 30
|
||||||
healthCost: 0
|
healthCost: 0
|
||||||
classResourceCost: 0
|
classResourceCost: 0
|
||||||
spiritPowerReserveCost: 0
|
spiritPowerReserveCost: 0
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ebbaf77cf9aa1bf4686e2835b46e8e66
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,59 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// COST CALCULATION CONTEXT - Holds user stats for cost calculations
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Context containing user stats needed for cost calculations
|
||||||
|
/// Allows ability cost calculation without direct user reference
|
||||||
|
/// </summary>
|
||||||
|
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<Mana>();
|
||||||
|
if (mana != null)
|
||||||
|
{
|
||||||
|
context.maxMana = mana.GetMaxValue();
|
||||||
|
context.currentMana = mana.GetCurrentValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
var health = user.GetComponent<Health>();
|
||||||
|
if (health != null)
|
||||||
|
{
|
||||||
|
context.maxHealth = health.GetMaxValue();
|
||||||
|
context.currentHealth = health.GetCurrentValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
var classResource = user.GetComponent<ClassResource>();
|
||||||
|
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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5050e09038372134fbe8fa068698e68a
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -1,25 +1,20 @@
|
|||||||
// ============================================================================
|
|
||||||
// RUNTIME ABILITY WRAPPER - DROP-IN REPLACEMENT FOR BaseAbility
|
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
using Kryz.CharacterStats.Examples;
|
using Kryz.CharacterStats.Examples;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// 1. RUNTIME ABILITY INSTANCE - Wraps Your Existing BaseAbility
|
// RUNTIME ABILITY INSTANCE - Context-Aware Version
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Runtime wrapper for BaseAbility that adds modifiers and behaviors
|
/// Runtime wrapper for BaseAbility with context-aware cost calculations
|
||||||
/// Can be used anywhere you currently use BaseAbility references
|
/// Modifiers now properly affect total costs (flat + percentage combined)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class RuntimeAbilityInstance
|
public class RuntimeAbilityInstance
|
||||||
{
|
{
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
// CORE DATA - Wraps your existing ScriptableObject
|
// CORE DATA
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
|
||||||
[SerializeField] private BaseAbility sourceAbility;
|
[SerializeField] private BaseAbility sourceAbility;
|
||||||
@ -37,15 +32,13 @@ public class RuntimeAbilityInstance
|
|||||||
public RuntimeAbilityInstance(BaseAbility source)
|
public RuntimeAbilityInstance(BaseAbility source)
|
||||||
{
|
{
|
||||||
sourceAbility = source;
|
sourceAbility = source;
|
||||||
currentCharges = GetMaxCharges(); // In case you add charges later
|
currentCharges = GetMaxCharges();
|
||||||
RecalculateModifiedValues();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
// PROPERTIES - Direct access to original + modified values
|
// PROPERTIES - Direct access to original values
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
|
||||||
// Original values (unchanged)
|
|
||||||
public BaseAbility SourceAbility => sourceAbility;
|
public BaseAbility SourceAbility => sourceAbility;
|
||||||
public string displayName => sourceAbility.displayName;
|
public string displayName => sourceAbility.displayName;
|
||||||
public Sprite Icon => sourceAbility.Icon;
|
public Sprite Icon => sourceAbility.Icon;
|
||||||
@ -55,15 +48,18 @@ public class RuntimeAbilityInstance
|
|||||||
public bool castableWhileMoving => sourceAbility.castableWhileMoving;
|
public bool castableWhileMoving => sourceAbility.castableWhileMoving;
|
||||||
public AbilityAnimationType animationType => sourceAbility.animationType;
|
public AbilityAnimationType animationType => sourceAbility.animationType;
|
||||||
|
|
||||||
// Modified values (affected by modifiers)
|
// Base costs (for display when no context available)
|
||||||
public float manaCost { get; private set; }
|
public float baseManaFlat => sourceAbility.manaCost;
|
||||||
public float healthCost { get; private set; }
|
public float baseHealthFlat => sourceAbility.healthCost;
|
||||||
public float classResourceCost { get; private set; }
|
public float baseClassResourceFlat => sourceAbility.classResourceCost;
|
||||||
public float spiritPowerReserveCost { get; private set; }
|
public float baseManaPercent => sourceAbility.percentMaxManaCost;
|
||||||
public float percentMaxManaCost { get; private set; }
|
public float baseHealthPercent => sourceAbility.percentMaxHealthCost;
|
||||||
public float percentMaxHealthCost { get; private set; }
|
public float baseCastTime => sourceAbility.castTime;
|
||||||
public float castTime { get; private set; }
|
public float baseCooldown => sourceAbility.cooldown;
|
||||||
public float cooldown { get; private set; }
|
|
||||||
|
// Modified timing values (these don't need user context)
|
||||||
|
public float castTime => GetModifiedCastTime();
|
||||||
|
public float cooldown => GetModifiedCooldown();
|
||||||
|
|
||||||
// Runtime state properties
|
// Runtime state properties
|
||||||
public float LastUsedTime => lastUsedTime;
|
public float LastUsedTime => lastUsedTime;
|
||||||
@ -73,23 +69,143 @@ public class RuntimeAbilityInstance
|
|||||||
public List<RuntimeBehavior> RuntimeBehaviors => new List<RuntimeBehavior>(runtimeBehaviors);
|
public List<RuntimeBehavior> RuntimeBehaviors => new List<RuntimeBehavior>(runtimeBehaviors);
|
||||||
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
// EXECUTION METHODS - Same signature as your BaseAbility
|
// CONTEXT-AWARE COST CALCULATIONS
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculate final mana cost including modifiers (affects flat + percentage total)
|
||||||
|
/// </summary>
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculate final health cost including modifiers (affects flat + percentage total)
|
||||||
|
/// </summary>
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculate final class resource cost (flat only, no percentage version)
|
||||||
|
/// </summary>
|
||||||
|
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
|
||||||
|
// ========================================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get display-friendly mana cost text
|
||||||
|
/// </summary>
|
||||||
|
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";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get display-friendly health cost text
|
||||||
|
/// </summary>
|
||||||
|
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";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all cost information as formatted string
|
||||||
|
/// </summary>
|
||||||
|
public string GetAllCostsDisplayText(CostCalculationContext? context = null)
|
||||||
|
{
|
||||||
|
var costs = new List<string>();
|
||||||
|
|
||||||
|
// 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<ClassResource>()?.ChangeValue(-GetFinalClassResourceCost());
|
||||||
|
}
|
||||||
|
|
||||||
public virtual void Execute(Taggable user)
|
public virtual void Execute(Taggable user)
|
||||||
{
|
{
|
||||||
if (!CanExecute(user)) return;
|
if (!CanExecute(user)) return;
|
||||||
|
|
||||||
// Execute pre-cast behaviors
|
|
||||||
ExecuteBehaviors(BehaviorTrigger.PreCast, user, null, Vector3.zero);
|
ExecuteBehaviors(BehaviorTrigger.PreCast, user, null, Vector3.zero);
|
||||||
|
SpendResourcesNecessary(user);
|
||||||
// Execute original ability
|
|
||||||
sourceAbility.Execute(user);
|
sourceAbility.Execute(user);
|
||||||
|
|
||||||
// Execute post-cast behaviors
|
|
||||||
ExecuteBehaviors(BehaviorTrigger.PostCast, user, null, Vector3.zero);
|
ExecuteBehaviors(BehaviorTrigger.PostCast, user, null, Vector3.zero);
|
||||||
|
|
||||||
// Update runtime state
|
|
||||||
lastUsedTime = Time.time;
|
lastUsedTime = Time.time;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,6 +214,7 @@ public class RuntimeAbilityInstance
|
|||||||
if (!CanExecute(user)) return;
|
if (!CanExecute(user)) return;
|
||||||
|
|
||||||
ExecuteBehaviors(BehaviorTrigger.PreCast, user, null, point);
|
ExecuteBehaviors(BehaviorTrigger.PreCast, user, null, point);
|
||||||
|
SpendResourcesNecessary(user);
|
||||||
sourceAbility.Execute(user, point);
|
sourceAbility.Execute(user, point);
|
||||||
ExecuteBehaviors(BehaviorTrigger.PostCast, user, null, point);
|
ExecuteBehaviors(BehaviorTrigger.PostCast, user, null, point);
|
||||||
|
|
||||||
@ -109,6 +226,7 @@ public class RuntimeAbilityInstance
|
|||||||
if (!CanExecute(user)) return;
|
if (!CanExecute(user)) return;
|
||||||
|
|
||||||
ExecuteBehaviors(BehaviorTrigger.PreCast, user, target, target.position);
|
ExecuteBehaviors(BehaviorTrigger.PreCast, user, target, target.position);
|
||||||
|
SpendResourcesNecessary(user);
|
||||||
sourceAbility.Execute(user, target);
|
sourceAbility.Execute(user, target);
|
||||||
ExecuteBehaviors(BehaviorTrigger.PostCast, user, target, target.position);
|
ExecuteBehaviors(BehaviorTrigger.PostCast, user, target, target.position);
|
||||||
|
|
||||||
@ -121,83 +239,131 @@ public class RuntimeAbilityInstance
|
|||||||
|
|
||||||
public bool CanExecute(Taggable user)
|
public bool CanExecute(Taggable user)
|
||||||
{
|
{
|
||||||
// Check cooldown
|
|
||||||
if (IsOnCooldown) return false;
|
if (IsOnCooldown) return false;
|
||||||
|
return CanAffordResources(CostCalculationContext.FromUser(user));
|
||||||
// Check resources using modified costs
|
|
||||||
return CanAffordResources(user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool CanAffordResources(Taggable user)
|
public bool CanAffordResources(CostCalculationContext context)
|
||||||
{
|
{
|
||||||
// Use the modified costs, not original
|
// Check mana cost
|
||||||
var userMana = user.GetComponent<Mana>();
|
if (context.maxMana > 0)
|
||||||
if (userMana != null)
|
|
||||||
{
|
{
|
||||||
float finalManaCost = manaCost + userMana.GetMaxValue() * percentMaxManaCost;
|
float finalManaCost = GetFinalManaCost(context);
|
||||||
if (!userMana.EnoughMana(finalManaCost)) return false;
|
if (context.currentMana < finalManaCost) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var userHealth = user.GetComponent<Health>();
|
// Check health cost
|
||||||
if (userHealth != null)
|
if (context.maxHealth > 0)
|
||||||
{
|
{
|
||||||
float finalHealthCost = healthCost + userHealth.GetMaxValue() * percentMaxHealthCost;
|
float finalHealthCost = GetFinalHealthCost(context);
|
||||||
if (userHealth.GetCurrentValue() <= finalHealthCost) return false;
|
if (context.currentHealth <= finalHealthCost) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var userClassResource = user.GetComponent<ClassResource>();
|
// Check class resource cost
|
||||||
if (userClassResource != null && classResourceCost > 0)
|
if (context.currentClassResource > 0)
|
||||||
{
|
{
|
||||||
if (userClassResource.GetCurrentValue() < classResourceCost) return false;
|
float finalClassResourceCost = GetFinalClassResourceCost();
|
||||||
|
if (context.currentClassResource < finalClassResourceCost) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
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)
|
public void AddModifier(AbilityModifier modifier)
|
||||||
{
|
{
|
||||||
activeModifiers.Add(modifier);
|
activeModifiers.Add(modifier);
|
||||||
RecalculateModifiedValues();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddModifier(AbilityModifier modifier, object source)
|
public void AddModifier(AbilityModifier modifier, object source)
|
||||||
{
|
{
|
||||||
// Create a copy with the specified source
|
|
||||||
var modifierWithSource = new AbilityModifier(modifier, source);
|
var modifierWithSource = new AbilityModifier(modifier, source);
|
||||||
activeModifiers.Add(modifierWithSource);
|
activeModifiers.Add(modifierWithSource);
|
||||||
RecalculateModifiedValues();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveModifier(AbilityModifier modifier)
|
public void RemoveModifier(AbilityModifier modifier)
|
||||||
{
|
{
|
||||||
activeModifiers.Remove(modifier);
|
activeModifiers.Remove(modifier);
|
||||||
RecalculateModifiedValues();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool RemoveAllModifiersFromSource(object source)
|
public bool RemoveAllModifiersFromSource(object source)
|
||||||
{
|
{
|
||||||
int numRemovals = activeModifiers.RemoveAll(mod => mod.Source != null && mod.Source.Equals(source));
|
int numRemovals = activeModifiers.RemoveAll(mod => mod.Source != null && mod.Source.Equals(source));
|
||||||
|
return numRemovals > 0;
|
||||||
if (numRemovals > 0)
|
|
||||||
{
|
|
||||||
RecalculateModifiedValues();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasModifiersFromSource(object source)
|
public bool HasModifiersFromSource(object source)
|
||||||
@ -213,87 +379,39 @@ public class RuntimeAbilityInstance
|
|||||||
public void RemoveAllModifiers()
|
public void RemoveAllModifiers()
|
||||||
{
|
{
|
||||||
activeModifiers.Clear();
|
activeModifiers.Clear();
|
||||||
RecalculateModifiedValues();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
// CONVENIENCE METHODS - Common source-based operations
|
// CONVENIENCE METHODS
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
|
||||||
// Add modifier from equipment
|
|
||||||
public void AddEquipmentModifier(AbilityModifier modifier, EquippableItem equipment)
|
public void AddEquipmentModifier(AbilityModifier modifier, EquippableItem equipment)
|
||||||
{
|
{
|
||||||
AddModifier(modifier, equipment);
|
AddModifier(modifier, equipment);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add modifier from buff/effect
|
|
||||||
public void AddEffectModifier(AbilityModifier modifier, BaseEffect effect)
|
public void AddEffectModifier(AbilityModifier modifier, BaseEffect effect)
|
||||||
{
|
{
|
||||||
AddModifier(modifier, effect);
|
AddModifier(modifier, effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add modifier from skill/talent
|
|
||||||
public void AddSkillModifier(AbilityModifier modifier, string skillSource)
|
public void AddSkillModifier(AbilityModifier modifier, string skillSource)
|
||||||
{
|
{
|
||||||
AddModifier(modifier, skillSource);
|
AddModifier(modifier, skillSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove equipment modifiers when unequipping
|
|
||||||
public void RemoveEquipmentModifiers(EquippableItem equipment)
|
public void RemoveEquipmentModifiers(EquippableItem equipment)
|
||||||
{
|
{
|
||||||
RemoveAllModifiersFromSource(equipment);
|
RemoveAllModifiersFromSource(equipment);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove effect modifiers when effect expires
|
|
||||||
public void RemoveEffectModifiers(BaseEffect effect)
|
public void RemoveEffectModifiers(BaseEffect effect)
|
||||||
{
|
{
|
||||||
RemoveAllModifiersFromSource(effect);
|
RemoveAllModifiersFromSource(effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
// MODIFIER CALCULATION
|
// RUNTIME BEHAVIOR SYSTEM (same as before)
|
||||||
// ========================================================================
|
|
||||||
|
|
||||||
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
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
|
||||||
public void AddBehavior(RuntimeBehavior behavior)
|
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<object, int> GetModifierCountBySource()
|
|
||||||
{
|
|
||||||
var counts = new Dictionary<object, int>();
|
|
||||||
foreach (var modifier in activeModifiers)
|
|
||||||
{
|
|
||||||
var source = modifier.Source ?? "No Source";
|
|
||||||
counts[source] = counts.ContainsKey(source) ? counts[source] + 1 : 1;
|
|
||||||
}
|
|
||||||
return counts;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
// UTILITY METHODS
|
// UTILITY METHODS
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
@ -366,29 +459,48 @@ public class RuntimeAbilityInstance
|
|||||||
{
|
{
|
||||||
var clone = new RuntimeAbilityInstance(sourceAbility);
|
var clone = new RuntimeAbilityInstance(sourceAbility);
|
||||||
|
|
||||||
// Copy modifiers
|
|
||||||
foreach (var modifier in activeModifiers)
|
foreach (var modifier in activeModifiers)
|
||||||
{
|
|
||||||
clone.AddModifier(modifier);
|
clone.AddModifier(modifier);
|
||||||
}
|
|
||||||
|
|
||||||
// Copy behaviors
|
|
||||||
foreach (var behavior in runtimeBehaviors)
|
foreach (var behavior in runtimeBehaviors)
|
||||||
{
|
|
||||||
clone.AddBehavior(behavior.Clone());
|
clone.AddBehavior(behavior.Clone());
|
||||||
}
|
|
||||||
|
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetMaxCharges()
|
private int GetMaxCharges()
|
||||||
{
|
{
|
||||||
// Future: add charge system
|
return 1; // Future: add charge system
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
// IMPLICIT CONVERSION - Makes it work seamlessly
|
// DEBUG METHODS
|
||||||
|
// ========================================================================
|
||||||
|
|
||||||
|
public void PrintCostAnalysis(CostCalculationContext? context = null)
|
||||||
|
{
|
||||||
|
Debug.Log($"=== Cost Analysis for {displayName} ===");
|
||||||
|
|
||||||
|
if (context.HasValue)
|
||||||
|
{
|
||||||
|
var ctx = context.Value;
|
||||||
|
Debug.Log($"With Context (Max Mana: {ctx.maxMana}, Max Health: {ctx.maxHealth}):");
|
||||||
|
Debug.Log($" Final Mana Cost: {GetFinalManaCost(ctx):F1}");
|
||||||
|
Debug.Log($" Final Health Cost: {GetFinalHealthCost(ctx):F1}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Log("Without Context:");
|
||||||
|
Debug.Log($" Base Flat Mana: {baseManaFlat} + {baseManaPercent:P0} Max");
|
||||||
|
Debug.Log($" Base Flat Health: {baseHealthFlat} + {baseHealthPercent:P0} Max");
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.Log($" Final Class Resource Cost: {GetFinalClassResourceCost():F1}");
|
||||||
|
Debug.Log($" Active Modifiers: {activeModifiers.Count}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================================================
|
||||||
|
// IMPLICIT CONVERSION
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
|
||||||
public static implicit operator BaseAbility(RuntimeAbilityInstance instance)
|
public static implicit operator BaseAbility(RuntimeAbilityInstance instance)
|
||||||
|
@ -3,6 +3,7 @@ using UnityEngine;
|
|||||||
public enum BehaviorTrigger
|
public enum BehaviorTrigger
|
||||||
{
|
{
|
||||||
PreCast, // Before ability executes
|
PreCast, // Before ability executes
|
||||||
|
Execute, // MAIN EXECUTION - replaces your override Execute()
|
||||||
PostCast, // After ability executes
|
PostCast, // After ability executes
|
||||||
OnHit, // When ability hits target
|
OnHit, // When ability hits target
|
||||||
OnKill, // When ability kills target
|
OnKill, // When ability kills target
|
||||||
|
@ -39,6 +39,9 @@ public class AbilityKeyBinder : MonoBehaviour
|
|||||||
float finalHealthCost;
|
float finalHealthCost;
|
||||||
float finalManaCost;
|
float finalManaCost;
|
||||||
|
|
||||||
|
RuntimeAbilityInstance abilityInstance;
|
||||||
|
public RuntimeAbilityInstance AbilityInstance => abilityInstance;
|
||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
userTag = GetComponentInParent<Taggable>();
|
userTag = GetComponentInParent<Taggable>();
|
||||||
@ -86,6 +89,17 @@ public class AbilityKeyBinder : MonoBehaviour
|
|||||||
if (abilityBindInstance != null)
|
if (abilityBindInstance != null)
|
||||||
abilityBindInstance.pressed.SetActive(true);
|
abilityBindInstance.pressed.SetActive(true);
|
||||||
|
|
||||||
|
if(abilityInstance != null)
|
||||||
|
{
|
||||||
|
if(abilityInstance.CanExecute(userTag))
|
||||||
|
{
|
||||||
|
castingStateController.RequestAbilityCast(abilityInstance, () =>
|
||||||
|
{
|
||||||
|
abilityInstance.Execute(userTag);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
if (IsAbilityOffCooldown() && mana.EnoughMana(ability.GetFinalManaCost(mana)) && health.EnoughHealth(ability.GetFinalHealthCost(health)))
|
if (IsAbilityOffCooldown() && mana.EnoughMana(ability.GetFinalManaCost(mana)) && health.EnoughHealth(ability.GetFinalHealthCost(health)))
|
||||||
{
|
{
|
||||||
if (ability is ChanneledAbility)
|
if (ability is ChanneledAbility)
|
||||||
@ -159,6 +173,7 @@ public class AbilityKeyBinder : MonoBehaviour
|
|||||||
|
|
||||||
public void SetupAbilityBindInstance(AbilityBindInstance abilityBindInstance)
|
public void SetupAbilityBindInstance(AbilityBindInstance abilityBindInstance)
|
||||||
{
|
{
|
||||||
|
Debug.Log("#RACE: SETUP BIND INSTANCE");
|
||||||
this.abilityBindInstance = abilityBindInstance;
|
this.abilityBindInstance = abilityBindInstance;
|
||||||
mana.onResourceChanged.AddListener(OnManaChanged);
|
mana.onResourceChanged.AddListener(OnManaChanged);
|
||||||
health.onResourceChanged.AddListener(OnHealthChanged);
|
health.onResourceChanged.AddListener(OnHealthChanged);
|
||||||
@ -167,15 +182,23 @@ public class AbilityKeyBinder : MonoBehaviour
|
|||||||
abilityBindInstance.ForceUpdateOnComboAbility(GetCurrentAbility());
|
abilityBindInstance.ForceUpdateOnComboAbility(GetCurrentAbility());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[ContextMenu("debug Add manacost reduction")]
|
||||||
|
public void AddManaCostModifierDebug()
|
||||||
|
{
|
||||||
|
abilityInstance.AddModifier(AbilityModifier.CreateManaCostReduction(100f));
|
||||||
|
}
|
||||||
|
|
||||||
public void OnManaChanged(float currentMana)
|
public void OnManaChanged(float currentMana)
|
||||||
{
|
{
|
||||||
|
if (ability == null || abilityInstance == null) return;
|
||||||
|
|
||||||
if (isComboAbility)
|
if (isComboAbility)
|
||||||
{
|
{
|
||||||
finalManaCost = GetCurrentAbility().GetFinalManaCost(mana);
|
finalManaCost = GetCurrentAbility().GetFinalManaCost(mana);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
finalManaCost = ability.GetFinalManaCost(mana);
|
finalManaCost = abilityInstance.GetFinalManaCost(CostCalculationContext.FromUser(userTag));
|
||||||
}
|
}
|
||||||
abilityBindInstance.manaCost.text = finalManaCost.ToString("F0");
|
abilityBindInstance.manaCost.text = finalManaCost.ToString("F0");
|
||||||
abilityBindInstance.noMana.SetActive(!mana.EnoughMana(finalManaCost));
|
abilityBindInstance.noMana.SetActive(!mana.EnoughMana(finalManaCost));
|
||||||
@ -183,13 +206,15 @@ public class AbilityKeyBinder : MonoBehaviour
|
|||||||
|
|
||||||
public void OnHealthChanged(float currentHealth)
|
public void OnHealthChanged(float currentHealth)
|
||||||
{
|
{
|
||||||
|
if (ability == null || abilityInstance == null) return;
|
||||||
|
|
||||||
if (isComboAbility)
|
if (isComboAbility)
|
||||||
{
|
{
|
||||||
finalHealthCost = GetCurrentAbility().GetFinalHealthCost(health);
|
finalHealthCost = GetCurrentAbility().GetFinalHealthCost(health);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
finalHealthCost = ability.GetFinalHealthCost(health);
|
finalHealthCost = abilityInstance.GetFinalHealthCost(CostCalculationContext.FromUser(userTag));
|
||||||
}
|
}
|
||||||
|
|
||||||
abilityBindInstance.healthCost.text = finalHealthCost.ToString("F0");
|
abilityBindInstance.healthCost.text = finalHealthCost.ToString("F0");
|
||||||
@ -199,11 +224,15 @@ public class AbilityKeyBinder : MonoBehaviour
|
|||||||
|
|
||||||
public bool IsAbilityOffCooldown()
|
public bool IsAbilityOffCooldown()
|
||||||
{
|
{
|
||||||
|
if (abilityBindInstance != null)
|
||||||
|
return !abilityInstance.IsOnCooldown;
|
||||||
|
|
||||||
return ability.cooldown <= 0 || !cooldownTracker.OnCooldown(ability);
|
return ability.cooldown <= 0 || !cooldownTracker.OnCooldown(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BindAbility(BaseAbility ability)
|
public void BindAbility(BaseAbility ability)
|
||||||
{
|
{
|
||||||
|
Debug.Log("#RACE: BIND ABILITY");
|
||||||
this.ability = ability;
|
this.ability = ability;
|
||||||
if (ability is ComboAbility comboAbility)
|
if (ability is ComboAbility comboAbility)
|
||||||
{
|
{
|
||||||
@ -213,6 +242,7 @@ public class AbilityKeyBinder : MonoBehaviour
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
abilityInstance = new RuntimeAbilityInstance(ability);
|
||||||
isComboAbility = false;
|
isComboAbility = false;
|
||||||
combo = null;
|
combo = null;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user