JisolGame/JEX_GAS/Assets/GAS/Runtime/Effects/GameplayEffectStacking.cs

239 lines
9.4 KiB
C#
Raw Normal View History

using System;
using GAS.General;
using Sirenix.OdinInspector;
using UnityEngine;
namespace GAS.Runtime
{
public enum StackingType
{
[LabelText("独立", SdfIconType.XCircleFill)]
None, //不会叠加如果多次释放则每个Effect相当于单个Effect
[LabelText("来源", SdfIconType.Magic)]
AggregateBySource, //目标(Target)上的每个源(Source)ASC都有一个单独的堆栈实例, 每个源(Source)可以应用堆栈中的X个GameplayEffect.
[LabelText("目标", SdfIconType.Person)]
AggregateByTarget //目标(Target)上只有一个堆栈实例而不管源(Source)如何, 每个源(Source)都可以在共享堆栈限制(Shared Stack Limit)内应用堆栈.
}
public enum DurationRefreshPolicy
{
[LabelText("NeverRefresh - 不刷新Effect的持续时间", SdfIconType.XCircleFill)]
NeverRefresh, //不刷新Effect的持续时间
[LabelText(
"RefreshOnSuccessfulApplication - 每次apply成功后刷新持续时间",
SdfIconType.HourglassTop)]
RefreshOnSuccessfulApplication //每次apply成功后刷新Effect的持续时间, denyOverflowApplication如果为True则多余的Apply不会刷新Duration
}
public enum PeriodResetPolicy
{
[LabelText("NeverReset - 不重置Effect的周期计时", SdfIconType.XCircleFill)]
NeverRefresh, //不重置Effect的周期计时
[LabelText("ResetOnSuccessfulApplication - 每次apply成功后重置Effect的周期计时", SdfIconType.HourglassTop)]
ResetOnSuccessfulApplication //每次apply成功后重置Effect的周期计时
}
public enum ExpirationPolicy
{
[LabelText("ClearEntireStack - 持续时间结束时, 清除所有层数", SdfIconType.TrashFill)]
ClearEntireStack, //持续时间结束时,清除所有层数
[LabelText("RemoveSingleStackAndRefreshDuration - 持续时间结束时减少一层然后重新经历一个Duration", SdfIconType.EraserFill)]
RemoveSingleStackAndRefreshDuration, //持续时间结束时减少一层然后重新经历一个Duration一直持续到层数减为0
[LabelText("RefreshDuration - 持续时间结束时,再次刷新Duration", SdfIconType.HourglassTop)]
RefreshDuration //持续时间结束时,再次刷新Duration这相当于无限Duration
//TODO :可以通过调用GameplayEffectsContainer的OnStackCountChange(GameplayEffect ActiveEffect, int OldStackCount, int NewStackCount)来处理层数,
//TODO :可以达到Duration结束时减少两层并刷新Duration这样复杂的效果。
}
// GE堆栈数据结构
public struct GameplayEffectStacking
{
public string stackingCodeName; // 实际允许不会使用而是使用stackingCodeName的hash值, 即stackingHashCode
public int stackingHashCode;
public StackingType stackingType;
public int limitCount;
public DurationRefreshPolicy durationRefreshPolicy;
public PeriodResetPolicy periodResetPolicy;
public ExpirationPolicy expirationPolicy;
// Overflow 溢出逻辑处理
public bool denyOverflowApplication; //对应于StackDurationRefreshPolicy如果为True则多余的Apply不会刷新Duration
public bool clearStackOnOverflow; //当DenyOverflowApplication为True是才有效当Overflow时是否直接删除所有层数
public GameplayEffect[] overflowEffects; // 超过StackLimitCount数量的Effect被Apply时将会调用该OverflowEffects
public void SetStackingCodeName(string stackingCodeName)
{
this.stackingCodeName = stackingCodeName;
this.stackingHashCode = stackingCodeName?.GetHashCode() ?? 0; // 兼容旧的SO数据
}
public void SetStackingHashCode(int stackingHashCode)
{
this.stackingHashCode = stackingHashCode;
}
public void SetStackingType(StackingType stackingType)
{
this.stackingType = stackingType;
}
public void SetLimitCount(int limitCount)
{
this.limitCount = limitCount;
}
public void SetDurationRefreshPolicy(DurationRefreshPolicy durationRefreshPolicy)
{
this.durationRefreshPolicy = durationRefreshPolicy;
}
public void SetPeriodResetPolicy(PeriodResetPolicy periodResetPolicy)
{
this.periodResetPolicy = periodResetPolicy;
}
public void SetExpirationPolicy(ExpirationPolicy expirationPolicy)
{
this.expirationPolicy = expirationPolicy;
}
public void SetOverflowEffects(GameplayEffect[] overflowEffects)
{
this.overflowEffects = overflowEffects;
}
public void SetOverflowEffects(GameplayEffectAsset[] overflowEffectAssets)
{
overflowEffects = new GameplayEffect[overflowEffectAssets.Length];
for (var i = 0; i < overflowEffectAssets.Length; ++i)
{
overflowEffects[i] = overflowEffectAssets[i].SharedInstance;
}
}
public void SetDenyOverflowApplication(bool denyOverflowApplication)
{
this.denyOverflowApplication = denyOverflowApplication;
}
public void SetClearStackOnOverflow(bool clearStackOnOverflow)
{
this.clearStackOnOverflow = clearStackOnOverflow;
}
public static GameplayEffectStacking None
{
get
{
var stack = new GameplayEffectStacking();
stack.SetStackingType(StackingType.None);
return stack;
}
}
}
[Serializable]
public sealed class GameplayEffectStackingConfig
{
private const int LABEL_WIDTH = 100;
[LabelWidth(LABEL_WIDTH)]
[VerticalGroup]
[LabelText(GASTextDefine.LABEL_GE_STACKING_TYPE)]
[EnumToggleButtons]
public StackingType stackingType;
[LabelWidth(LABEL_WIDTH)]
[VerticalGroup]
[HideIf("IsNoStacking")]
[LabelText(GASTextDefine.LABEL_GE_STACKING_CODENAME)]
[CustomContextMenu("清除","@stackingCodeName = \"\"")]
public string stackingCodeName;
[LabelWidth(LABEL_WIDTH)]
[VerticalGroup]
[LabelText(GASTextDefine.LABEL_GE_STACKING_COUNT)]
[HideIf("IsNoStacking")]
[CustomContextMenu("设为0","@limitCount = 0")]
[CustomContextMenu("设为1","@limitCount = 1")]
[CustomContextMenu("设为最大值","@limitCount = int.MaxValue")]
[MinValue(0),MaxValue(int.MaxValue)]
public int limitCount;
[LabelWidth(LABEL_WIDTH)]
[VerticalGroup]
[LabelText(GASTextDefine.LABEL_GE_STACKING_DURATION_REFRESH_POLICY)]
[HideIf("IsNoStacking")]
[InfoBox(GASTextDefine.LABEL_GE_STACKING_DENY_OVERFLOW_APPLICATION+"为True时多余的Apply不会刷新Duration", InfoMessageType.None,
VisibleIf =
"@durationRefreshPolicy == DurationRefreshPolicy.RefreshOnSuccessfulApplication && denyOverflowApplication")]
public DurationRefreshPolicy durationRefreshPolicy;
[LabelWidth(LABEL_WIDTH)]
[VerticalGroup]
[LabelText(GASTextDefine.LABEL_GE_STACKING_PERIOD_RESET_POLICY)]
[HideIf("IsNoStacking")]
public PeriodResetPolicy periodResetPolicy;
[LabelWidth(LABEL_WIDTH)]
[VerticalGroup]
[LabelText(GASTextDefine.LABEL_GE_STACKING_EXPIRATION_POLICY)]
[HideIf("IsNoStacking")]
public ExpirationPolicy expirationPolicy;
// Overflow 溢出逻辑处理
[LabelWidth(LABEL_WIDTH)]
[VerticalGroup]
[LabelText(GASTextDefine.LABEL_GE_STACKING_DENY_OVERFLOW_APPLICATION)]
[HideIf("@IsNoStacking() || IsNeverRefreshDuration()")]
public bool denyOverflowApplication;
[VerticalGroup]
[LabelWidth(LABEL_WIDTH)]
[LabelText(GASTextDefine.LABEL_GE_STACKING_CLEAR_STACK_ON_OVERFLOW)]
[ShowIf("IsDenyOverflowApplication")]
public bool clearStackOnOverflow;
[VerticalGroup]
[LabelWidth(LABEL_WIDTH)]
[LabelText(GASTextDefine.LABEL_GE_STACKING_CLEAR_OVERFLOW_EFFECTS)]
[HideIf("IsNoStacking")]
public GameplayEffectAsset[] overflowEffects;
/// <summary>
/// 转换为运行时数据
/// </summary>
/// <returns></returns>
public GameplayEffectStacking ToRuntimeData()
{
var stack = new GameplayEffectStacking();
stack.SetStackingCodeName(stackingCodeName);
stack.SetStackingType(stackingType);
stack.SetLimitCount(limitCount);
stack.SetDurationRefreshPolicy(durationRefreshPolicy);
stack.SetPeriodResetPolicy(periodResetPolicy);
stack.SetExpirationPolicy(expirationPolicy);
stack.SetOverflowEffects(overflowEffects);
stack.SetDenyOverflowApplication(denyOverflowApplication);
stack.SetClearStackOnOverflow(clearStackOnOverflow);
return stack;
}
#region UTIL FUNCTION FOR ODIN INSPECTOR
public bool IsNoStacking() => stackingType == StackingType.None;
public bool IsNeverRefreshDuration() =>
IsNoStacking() || durationRefreshPolicy == DurationRefreshPolicy.NeverRefresh;
public bool IsDenyOverflowApplication() => !IsNoStacking() && denyOverflowApplication;
#endregion
}
}