mirror of
https://gitee.com/jisol/jisol-game/
synced 2025-06-26 03:14:47 +00:00
702 lines
24 KiB
C#
702 lines
24 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using GAS.General;
|
||
using UnityEngine;
|
||
|
||
namespace GAS.Runtime
|
||
{
|
||
/// <summary>
|
||
/// 注意: 永远不要直接持有对GameplayEffectSpec的引用, 用EntityRef代替, 否则当它回收入池再次使用时会出现问题
|
||
/// </summary>
|
||
public sealed class GameplayEffectSpec : IEntity, IPool
|
||
{
|
||
private Dictionary<GameplayTag, float> _valueMapWithTag;
|
||
private Dictionary<string, float> _valueMapWithName;
|
||
private List<GameplayCueDurationalSpec> _cueDurationalSpecs;
|
||
|
||
public object UserData { get; set; }
|
||
|
||
private event Action<AbilitySystemComponent, GameplayEffectSpec> OnImmunityBlock;
|
||
|
||
private event Action<int, int> OnStackChanged;
|
||
|
||
public ulong InstanceId { get; private set; }
|
||
|
||
public bool IsFromPool { get; set; }
|
||
|
||
public void Awake(GameplayEffect gameplayEffect, object userData = null)
|
||
{
|
||
InstanceId = IdGenerator.Next;
|
||
|
||
GameplayEffect = gameplayEffect;
|
||
UserData = userData;
|
||
Duration = GameplayEffect.Duration;
|
||
DurationPolicy = GameplayEffect.DurationPolicy;
|
||
Stacking = GameplayEffect.Stacking;
|
||
Modifiers = GameplayEffect.Modifiers;
|
||
if (gameplayEffect.DurationPolicy != EffectsDurationPolicy.Instant)
|
||
{
|
||
var periodTicker = JexGasObjectPool.Instance.Fetch<GameplayEffectPeriodTicker>();
|
||
periodTicker.Awake(this);
|
||
// EntityRef之前必须确定InstanceId的值
|
||
PeriodTicker = periodTicker;
|
||
}
|
||
}
|
||
|
||
public void Recycle()
|
||
{
|
||
if (InstanceId != 0)
|
||
{
|
||
InstanceId = 0;
|
||
|
||
GameplayEffect = default;
|
||
ActivationTime = default;
|
||
Level = default;
|
||
Source = default;
|
||
Owner = default;
|
||
IsApplied = default;
|
||
IsActive = default;
|
||
|
||
var gameplayEffectPeriodTicker = PeriodTicker.Value;
|
||
if (gameplayEffectPeriodTicker != null)
|
||
{
|
||
gameplayEffectPeriodTicker.Release();
|
||
JexGasObjectPool.Instance.Recycle(gameplayEffectPeriodTicker);
|
||
}
|
||
|
||
PeriodTicker = default;
|
||
|
||
Duration = default;
|
||
DurationPolicy = default;
|
||
PeriodExecution.Value?.Recycle();
|
||
PeriodExecution = default;
|
||
Modifiers = default;
|
||
|
||
if (GrantedAbilitiesSpecFromEffect != null)
|
||
{
|
||
foreach (GrantedAbilitySpecFromEffect grantedAbilitySpecFromEffect in GrantedAbilitiesSpecFromEffect)
|
||
{
|
||
if (grantedAbilitySpecFromEffect != null)
|
||
{
|
||
grantedAbilitySpecFromEffect.Release();
|
||
JexGasObjectPool.Instance.Recycle(grantedAbilitySpecFromEffect);
|
||
}
|
||
}
|
||
|
||
GrantedAbilitiesSpecFromEffect.Clear();
|
||
JexGasObjectPool.Instance.Recycle(GrantedAbilitiesSpecFromEffect);
|
||
GrantedAbilitiesSpecFromEffect = default;
|
||
}
|
||
|
||
Stacking = default;
|
||
|
||
// 注意: SnapshotSourceAttributes 和 SnapshotTargetAttributes 可能是同一个对象
|
||
if (SnapshotSourceAttributes != null)
|
||
{
|
||
SnapshotSourceAttributes.Clear();
|
||
JexGasObjectPool.Instance.Recycle(SnapshotSourceAttributes);
|
||
}
|
||
|
||
if (SnapshotTargetAttributes != null && SnapshotSourceAttributes != SnapshotTargetAttributes)
|
||
{
|
||
SnapshotTargetAttributes.Clear();
|
||
JexGasObjectPool.Instance.Recycle(SnapshotTargetAttributes);
|
||
}
|
||
|
||
SnapshotSourceAttributes = null;
|
||
SnapshotTargetAttributes = null;
|
||
|
||
StackCount = 1;
|
||
|
||
if (_valueMapWithTag != null)
|
||
{
|
||
_valueMapWithTag.Clear();
|
||
JexGasObjectPool.Instance.Recycle(_valueMapWithTag);
|
||
_valueMapWithTag = null;
|
||
}
|
||
|
||
if (_valueMapWithName != null)
|
||
{
|
||
_valueMapWithName.Clear();
|
||
JexGasObjectPool.Instance.Recycle(_valueMapWithName);
|
||
_valueMapWithName = null;
|
||
}
|
||
|
||
ReleaseCueDurationalSpecs();
|
||
|
||
OnImmunityBlock = default;
|
||
OnStackChanged = default;
|
||
}
|
||
|
||
JexGasObjectPool.Instance.Recycle(this);
|
||
}
|
||
|
||
public void Init(AbilitySystemComponent source, AbilitySystemComponent owner, float level = 1)
|
||
{
|
||
Source = source;
|
||
Owner = owner;
|
||
Level = level;
|
||
if (GameplayEffect.DurationPolicy != EffectsDurationPolicy.Instant)
|
||
{
|
||
if (GameplayEffect.PeriodExecution is not null)
|
||
{
|
||
PeriodExecution = GameplayEffect.PeriodExecution.CreateSpec(source, owner);
|
||
}
|
||
|
||
SetGrantedAbility(GameplayEffect.GrantedAbilities);
|
||
}
|
||
|
||
CaptureAttributesSnapshot();
|
||
}
|
||
|
||
public GameplayEffect GameplayEffect { get; private set; }
|
||
public float ActivationTime { get; private set; }
|
||
public float Level { get; private set; }
|
||
public AbilitySystemComponent Source { get; private set; }
|
||
public AbilitySystemComponent Owner { get; private set; }
|
||
public bool IsApplied { get; private set; }
|
||
public bool IsActive { get; private set; }
|
||
internal EntityRef<GameplayEffectPeriodTicker> PeriodTicker { get; private set; }
|
||
public float Duration { get; private set; }
|
||
public EffectsDurationPolicy DurationPolicy { get; private set; }
|
||
public EntityRef<GameplayEffectSpec> PeriodExecution { get; private set; }
|
||
public GameplayEffectModifier[] Modifiers { get; private set; }
|
||
public List<EntityRef<GrantedAbilitySpecFromEffect>> GrantedAbilitiesSpecFromEffect { get; private set; }
|
||
public GameplayEffectStacking Stacking { get; private set; }
|
||
|
||
public GameplayEffectSnapshotPolicy SnapshotPolicy => GameplayEffect.SnapshotPolicy;
|
||
public Dictionary<string, float> SnapshotSourceAttributes { get; private set; }
|
||
public Dictionary<string, float> SnapshotTargetAttributes { get; private set; }
|
||
|
||
/// <summary>
|
||
/// 堆叠数
|
||
/// </summary>
|
||
public int StackCount { get; private set; } = 1;
|
||
|
||
|
||
public float DurationRemaining()
|
||
{
|
||
if (DurationPolicy == EffectsDurationPolicy.Infinite)
|
||
return -1;
|
||
|
||
return Mathf.Max(0, Duration - (Time.time - ActivationTime));
|
||
}
|
||
|
||
public void SetLevel(float level)
|
||
{
|
||
Level = level;
|
||
}
|
||
|
||
public void SetActivationTime(float activationTime)
|
||
{
|
||
ActivationTime = activationTime;
|
||
}
|
||
|
||
public void SetDuration(float duration)
|
||
{
|
||
Duration = duration;
|
||
}
|
||
|
||
public void SetDurationPolicy(EffectsDurationPolicy durationPolicy)
|
||
{
|
||
DurationPolicy = durationPolicy;
|
||
}
|
||
|
||
public void SetPeriodExecution(GameplayEffectSpec periodExecution)
|
||
{
|
||
PeriodExecution.Value?.Recycle();
|
||
PeriodExecution = periodExecution;
|
||
}
|
||
|
||
public void SetModifiers(GameplayEffectModifier[] modifiers)
|
||
{
|
||
Modifiers = modifiers;
|
||
}
|
||
|
||
public void SetGrantedAbility(GrantedAbilityFromEffect[] grantedAbilityFromEffects)
|
||
{
|
||
ReleaseGrantedAbilitiesSpecFromEffect();
|
||
|
||
if (grantedAbilityFromEffects is null) return;
|
||
if (grantedAbilityFromEffects.Length == 0) return;
|
||
|
||
GrantedAbilitiesSpecFromEffect = JexGasObjectPool.Instance.Fetch<List<EntityRef<GrantedAbilitySpecFromEffect>>>();
|
||
foreach (var grantedAbilityFromEffect in grantedAbilityFromEffects)
|
||
{
|
||
GrantedAbilitiesSpecFromEffect.Add(grantedAbilityFromEffect.CreateSpec(this));
|
||
}
|
||
}
|
||
|
||
private void ReleaseGrantedAbilitiesSpecFromEffect()
|
||
{
|
||
if (GrantedAbilitiesSpecFromEffect == null) return;
|
||
foreach (var grantedAbilitySpecFromEffectRef in GrantedAbilitiesSpecFromEffect)
|
||
{
|
||
var grantedAbilitySpecFromEffect = grantedAbilitySpecFromEffectRef.Value;
|
||
if (grantedAbilitySpecFromEffect != null)
|
||
{
|
||
grantedAbilitySpecFromEffect.Release();
|
||
JexGasObjectPool.Instance.Recycle(grantedAbilitySpecFromEffect);
|
||
}
|
||
}
|
||
|
||
GrantedAbilitiesSpecFromEffect.Clear();
|
||
JexGasObjectPool.Instance.Recycle(GrantedAbilitiesSpecFromEffect);
|
||
}
|
||
|
||
public void SetStacking(GameplayEffectStacking stacking)
|
||
{
|
||
Stacking = stacking;
|
||
}
|
||
|
||
public void Apply()
|
||
{
|
||
if (IsApplied) return;
|
||
IsApplied = true;
|
||
|
||
if (GameplayEffect.CanRunning(Owner))
|
||
{
|
||
Activate();
|
||
}
|
||
}
|
||
|
||
public void DisApply()
|
||
{
|
||
if (!IsApplied) return;
|
||
IsApplied = false;
|
||
Deactivate();
|
||
}
|
||
|
||
public void Activate()
|
||
{
|
||
if (IsActive) return;
|
||
IsActive = true;
|
||
ActivationTime = Time.time;
|
||
TriggerOnActivation();
|
||
}
|
||
|
||
public void Deactivate()
|
||
{
|
||
if (!IsActive) return;
|
||
IsActive = false;
|
||
TriggerOnDeactivation();
|
||
}
|
||
|
||
public void Tick()
|
||
{
|
||
PeriodTicker.Value?.Tick();
|
||
}
|
||
|
||
void TriggerInstantCues(GameplayCueInstant[] cues)
|
||
{
|
||
try
|
||
{
|
||
foreach (var cue in cues) cue.ApplyFrom(this);
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError(e);
|
||
}
|
||
}
|
||
|
||
private void TriggerCueOnExecute()
|
||
{
|
||
if (GameplayEffect.CueOnExecute == null || GameplayEffect.CueOnExecute.Length <= 0) return;
|
||
TriggerInstantCues(GameplayEffect.CueOnExecute);
|
||
}
|
||
|
||
private void TriggerCueOnAdd()
|
||
{
|
||
if (GameplayEffect.CueOnAdd is { Length: > 0 })
|
||
TriggerInstantCues(GameplayEffect.CueOnAdd);
|
||
|
||
try
|
||
{
|
||
ReleaseCueDurationalSpecs();
|
||
if (GameplayEffect.CueDurational is { Length: > 0 })
|
||
{
|
||
_cueDurationalSpecs = JexGasObjectPool.Instance.Fetch<List<GameplayCueDurationalSpec>>();
|
||
foreach (var cueDurational in GameplayEffect.CueDurational)
|
||
{
|
||
var cueSpec = cueDurational.ApplyFrom(this);
|
||
if (cueSpec != null) _cueDurationalSpecs.Add(cueSpec);
|
||
}
|
||
|
||
foreach (var cue in _cueDurationalSpecs)
|
||
cue.OnAdd(-1,-1,-1);
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError(e);
|
||
}
|
||
}
|
||
|
||
private void TriggerCueOnRemove()
|
||
{
|
||
if (GameplayEffect.CueOnRemove is { Length: > 0 })
|
||
TriggerInstantCues(GameplayEffect.CueOnRemove);
|
||
|
||
try
|
||
{
|
||
if (_cueDurationalSpecs != null)
|
||
{
|
||
foreach (var cue in _cueDurationalSpecs)
|
||
cue.OnRemove(-1,-1,-1);
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError(e);
|
||
}
|
||
finally
|
||
{
|
||
ReleaseCueDurationalSpecs();
|
||
}
|
||
}
|
||
|
||
|
||
private void TriggerCueOnActivation()
|
||
{
|
||
if (GameplayEffect.CueOnActivate is { Length: > 0 })
|
||
TriggerInstantCues(GameplayEffect.CueOnActivate);
|
||
|
||
try
|
||
{
|
||
if (_cueDurationalSpecs != null)
|
||
{
|
||
foreach (var cue in _cueDurationalSpecs)
|
||
cue.OnGameplayEffectActivate();
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError(e);
|
||
}
|
||
}
|
||
|
||
private void TriggerCueOnDeactivation()
|
||
{
|
||
if (GameplayEffect.CueOnDeactivate is { Length: > 0 })
|
||
TriggerInstantCues(GameplayEffect.CueOnDeactivate);
|
||
|
||
try
|
||
{
|
||
if (_cueDurationalSpecs != null)
|
||
{
|
||
foreach (var cue in _cueDurationalSpecs)
|
||
cue.OnGameplayEffectDeactivate();
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError(e);
|
||
}
|
||
}
|
||
|
||
private void CueOnTick()
|
||
{
|
||
try
|
||
{
|
||
if (_cueDurationalSpecs != null)
|
||
{
|
||
foreach (var cue in _cueDurationalSpecs)
|
||
cue.OnTick(-1,-1,-1);
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError(e);
|
||
}
|
||
}
|
||
|
||
public void TriggerOnExecute()
|
||
{
|
||
Owner.GameplayEffectContainer.RemoveGameplayEffectWithAnyTags(GameplayEffect.TagContainer
|
||
.RemoveGameplayEffectsWithTags);
|
||
Owner.ApplyModFromInstantGameplayEffect(this);
|
||
|
||
TriggerCueOnExecute();
|
||
}
|
||
|
||
public void TriggerOnAdd()
|
||
{
|
||
TriggerCueOnAdd();
|
||
}
|
||
|
||
public void TriggerOnRemove()
|
||
{
|
||
TryRemoveGrantedAbilities();
|
||
TriggerCueOnRemove();
|
||
}
|
||
|
||
private void TriggerOnActivation()
|
||
{
|
||
Owner.GameplayTagAggregator.ApplyGameplayEffectDynamicTag(this);
|
||
Owner.GameplayEffectContainer.RemoveGameplayEffectWithAnyTags(GameplayEffect.TagContainer.RemoveGameplayEffectsWithTags);
|
||
|
||
TryActivateGrantedAbilities();
|
||
TriggerCueOnActivation();
|
||
}
|
||
|
||
private void TriggerOnDeactivation()
|
||
{
|
||
Owner.GameplayTagAggregator.RestoreGameplayEffectDynamicTags(this);
|
||
|
||
TryDeactivateGrantedAbilities();
|
||
TriggerCueOnDeactivation();
|
||
}
|
||
|
||
public void TriggerOnTick()
|
||
{
|
||
if (DurationPolicy is EffectsDurationPolicy.Duration or EffectsDurationPolicy.Infinite)
|
||
CueOnTick();
|
||
}
|
||
|
||
public void TriggerOnImmunity()
|
||
{
|
||
OnImmunityBlock?.Invoke(Owner, this);
|
||
OnImmunityBlock = null;
|
||
}
|
||
|
||
public void RegisterOnImmunityBlock(Action<AbilitySystemComponent, GameplayEffectSpec> callback)
|
||
{
|
||
OnImmunityBlock += callback;
|
||
}
|
||
|
||
public void UnregisterOnImmunityBlock(Action<AbilitySystemComponent, GameplayEffectSpec> callback)
|
||
{
|
||
OnImmunityBlock -= callback;
|
||
}
|
||
|
||
public void RemoveSelf()
|
||
{
|
||
Owner.GameplayEffectContainer.RemoveGameplayEffectSpec(this);
|
||
}
|
||
|
||
private void CaptureAttributesSnapshot()
|
||
{
|
||
switch (SnapshotPolicy)
|
||
{
|
||
case GameplayEffectSnapshotPolicy.Specified:
|
||
if (GameplayEffect.SpecifiedSnapshotConfigs != null)
|
||
{
|
||
foreach (var config in GameplayEffect.SpecifiedSnapshotConfigs)
|
||
{
|
||
switch (config.SnapshotTarget)
|
||
{
|
||
case GameplayEffectSpecifiedSnapshotConfig.ESnapshotTarget.Source:
|
||
{
|
||
SnapshotSourceAttributes ??= JexGasObjectPool.Instance.Fetch<Dictionary<string, float>>();
|
||
var attribute = Source.AttributeSetContainer.GetAttributeAttributeValue(config.AttributeSetName, config.AttributeShortName);
|
||
if (attribute != null)
|
||
{
|
||
SnapshotSourceAttributes[config.AttributeName] = attribute.Value.CurrentValue;
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError($"Snapshot Source Attribute \"{config.AttributeName}\" not found in AttributeSet \"{config.AttributeSetName}\"");
|
||
}
|
||
|
||
break;
|
||
}
|
||
case GameplayEffectSpecifiedSnapshotConfig.ESnapshotTarget.Target:
|
||
{
|
||
SnapshotTargetAttributes ??= JexGasObjectPool.Instance.Fetch<Dictionary<string, float>>();
|
||
var attribute = Owner.AttributeSetContainer.GetAttributeAttributeValue(config.AttributeSetName, config.AttributeShortName);
|
||
if (attribute != null)
|
||
{
|
||
SnapshotTargetAttributes[config.AttributeName] = attribute.Value.CurrentValue;
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError($"Snapshot Target Attribute {config.AttributeName} not found in AttributeSet {config.AttributeSetName}");
|
||
}
|
||
|
||
break;
|
||
}
|
||
default:
|
||
throw new ArgumentOutOfRangeException();
|
||
}
|
||
}
|
||
}
|
||
|
||
break;
|
||
case GameplayEffectSnapshotPolicy.AllOfSource:
|
||
SnapshotSourceAttributes = Source.DataSnapshot();
|
||
break;
|
||
case GameplayEffectSnapshotPolicy.AllOfTarget:
|
||
SnapshotTargetAttributes = Owner.DataSnapshot();
|
||
break;
|
||
case GameplayEffectSnapshotPolicy.AllOfBoth:
|
||
SnapshotSourceAttributes = Source.DataSnapshot();
|
||
SnapshotTargetAttributes = Source == Owner ? SnapshotSourceAttributes : Owner.DataSnapshot();
|
||
break;
|
||
default:
|
||
Debug.LogError($"Unsupported SnapshotPolicy: {SnapshotPolicy}, GameplayEffect: {GameplayEffect.GameplayEffectName}");
|
||
break;
|
||
}
|
||
}
|
||
|
||
public void RegisterValue(in GameplayTag tag, float value)
|
||
{
|
||
_valueMapWithTag ??= JexGasObjectPool.Instance.Fetch<Dictionary<GameplayTag, float>>();
|
||
_valueMapWithTag[tag] = value;
|
||
}
|
||
|
||
public void RegisterValue(string name, float value)
|
||
{
|
||
_valueMapWithName ??= JexGasObjectPool.Instance.Fetch<Dictionary<string, float>>();
|
||
_valueMapWithName[name] = value;
|
||
}
|
||
|
||
public bool UnregisterValue(in GameplayTag tag)
|
||
{
|
||
if (_valueMapWithTag == null) return false;
|
||
return _valueMapWithTag.Remove(tag);
|
||
}
|
||
|
||
public bool UnregisterValue(string name)
|
||
{
|
||
if (_valueMapWithName == null) return false;
|
||
return _valueMapWithName.Remove(name);
|
||
}
|
||
|
||
public float? GetMapValue(in GameplayTag tag)
|
||
{
|
||
if (_valueMapWithTag == null) return null;
|
||
return _valueMapWithTag.TryGetValue(tag, out var value) ? value : (float?)null;
|
||
}
|
||
|
||
public float? GetMapValue(string name)
|
||
{
|
||
if (_valueMapWithName == null) return null;
|
||
return _valueMapWithName.TryGetValue(name, out var value) ? value : (float?)null;
|
||
}
|
||
|
||
private void TryActivateGrantedAbilities()
|
||
{
|
||
if (GrantedAbilitiesSpecFromEffect == null) return;
|
||
foreach (GrantedAbilitySpecFromEffect grantedAbilitySpec in GrantedAbilitiesSpecFromEffect)
|
||
{
|
||
if (grantedAbilitySpec is { ActivationPolicy: GrantedAbilityActivationPolicy.SyncWithEffect })
|
||
{
|
||
Owner.TryActivateAbility(grantedAbilitySpec.AbilityName);
|
||
}
|
||
}
|
||
}
|
||
|
||
private void TryDeactivateGrantedAbilities()
|
||
{
|
||
if (GrantedAbilitiesSpecFromEffect == null) return;
|
||
foreach (GrantedAbilitySpecFromEffect grantedAbilitySpec in GrantedAbilitiesSpecFromEffect)
|
||
{
|
||
if (grantedAbilitySpec is { DeactivationPolicy: GrantedAbilityDeactivationPolicy.SyncWithEffect })
|
||
{
|
||
Owner.TryEndAbility(grantedAbilitySpec.AbilityName);
|
||
}
|
||
}
|
||
}
|
||
|
||
private void TryRemoveGrantedAbilities()
|
||
{
|
||
if (GrantedAbilitiesSpecFromEffect == null) return;
|
||
foreach (GrantedAbilitySpecFromEffect grantedAbilitySpec in GrantedAbilitiesSpecFromEffect)
|
||
{
|
||
if (grantedAbilitySpec is { RemovePolicy: GrantedAbilityRemovePolicy.SyncWithEffect })
|
||
{
|
||
Owner.TryCancelAbility(grantedAbilitySpec.AbilityName);
|
||
Owner.RemoveAbility(grantedAbilitySpec.AbilityName);
|
||
}
|
||
}
|
||
}
|
||
|
||
private void ReleaseCueDurationalSpecs()
|
||
{
|
||
if (_cueDurationalSpecs != null)
|
||
{
|
||
_cueDurationalSpecs.Clear();
|
||
JexGasObjectPool.Instance.Recycle(_cueDurationalSpecs);
|
||
_cueDurationalSpecs = null;
|
||
}
|
||
}
|
||
|
||
#region ABOUT STACKING
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <returns>Stack Count是否变化</returns>
|
||
public bool RefreshStack()
|
||
{
|
||
var oldStackCount = StackCount;
|
||
RefreshStack(StackCount + 1);
|
||
OnStackCountChange(oldStackCount, StackCount);
|
||
return oldStackCount != StackCount;
|
||
}
|
||
|
||
public void RefreshStack(int stackCount)
|
||
{
|
||
if (stackCount <= Stacking.limitCount)
|
||
{
|
||
// 更新栈数
|
||
StackCount = Mathf.Max(1, stackCount); // 最小层数为1
|
||
// 是否刷新Duration
|
||
if (Stacking.durationRefreshPolicy == DurationRefreshPolicy.RefreshOnSuccessfulApplication)
|
||
{
|
||
RefreshDuration();
|
||
}
|
||
|
||
// 是否重置Period
|
||
if (Stacking.periodResetPolicy == PeriodResetPolicy.ResetOnSuccessfulApplication)
|
||
{
|
||
PeriodTicker.Value.ResetPeriod();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 溢出GE生效
|
||
foreach (var overflowEffect in Stacking.overflowEffects)
|
||
Owner.ApplyGameplayEffectToSelf(overflowEffect);
|
||
|
||
if (Stacking.durationRefreshPolicy == DurationRefreshPolicy.RefreshOnSuccessfulApplication)
|
||
{
|
||
if (Stacking.denyOverflowApplication)
|
||
{
|
||
//当DenyOverflowApplication为True是才有效,当Overflow时是否直接删除所有层数
|
||
if (Stacking.clearStackOnOverflow)
|
||
{
|
||
RemoveSelf();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
RefreshDuration();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
public void RefreshDuration()
|
||
{
|
||
ActivationTime = Time.time;
|
||
}
|
||
|
||
private void OnStackCountChange(int oldStackCount, int newStackCount)
|
||
{
|
||
OnStackChanged?.Invoke(oldStackCount, newStackCount);
|
||
}
|
||
|
||
public void RegisterOnStackCountChanged(Action<int, int> callback)
|
||
{
|
||
OnStackChanged += callback;
|
||
}
|
||
|
||
public void UnregisterOnStackCountChanged(Action<int, int> callback)
|
||
{
|
||
OnStackChanged -= callback;
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
} |