using System; using System.Collections.Generic; using System.Linq; using SoftCircuits.Collections; using SLSUtilities.General; using UnityEngine; using UnityEngine.Events; namespace Cielonos.MainGame { public partial class BuffBase { public abstract class BuffSubmodule : SubmoduleBase> { public BuffBase buff; protected BuffSubmodule(BuffBase buff) : base(buff) { this.buff = buff; } } public class ContentSubmodule : BuffSubmodule { public string displayName; public string originalFunctionText; public string interpretedFunctionText; public Dictionary> parameterGetters; public ContentSubmodule(BuffBase buff) : base(buff) { string displayNameKey = buff.GetType().Name + "_DisplayName"; string originalFunctionTextKey = buff.GetType().Name + "_FunctionText"; this.displayName = displayNameKey.Localize(); this.originalFunctionText = originalFunctionTextKey.Localize(); this.interpretedFunctionText = this.originalFunctionText; parameterGetters = new Dictionary>(); } public ContentSubmodule(BuffBase buff, string displayNameKey, string originalFunctionTextKey) : base(buff) { this.displayName = displayNameKey.Localize(); this.originalFunctionText = originalFunctionTextKey.Localize(); this.interpretedFunctionText = this.originalFunctionText; parameterGetters = new Dictionary>(); } public ContentSubmodule SetParameterGetter(Dictionary> getters) { parameterGetters = getters; return this; } public ContentSubmodule AddParameterGetter(string parameterName, Func getter) { parameterGetters[parameterName] = getter; return this; } } public class IconSubmodule : BuffSubmodule { public string iconID; public Sprite icon; public List synchronizedParameters; //public HUD_CharacterBuffIcon buffIcon; public IconSubmodule(BuffBase buff, string iconID = "") : base(buff) { if (buff.contentSubmodule != null) { this.synchronizedParameters = buff.contentSubmodule.parameterGetters.Keys.ToList(); } } public IconSubmodule SetTextFunctions(params string[] syncParameters) { synchronizedParameters = syncParameters.ToList(); return this; } public void Update() { } public void Remove() { } } public class EventSubmodule : BuffSubmodule { public OrderedDictionary>> onOtherBuffApplied; //Buff被添加时,参数为被添加的Buff实例 public OrderedDictionary>> onOtherBuffFirstApplied; //Buff被新添加时,参数为被添加的Buff实例 public OrderedDictionary>> onOtherBuffRemoved; //Buff被移除后,参数为被移除的Buff实例 public OrderedDictionary> onDealAttack; //造成伤害后,参数为伤害结果 public OrderedDictionary> onBeforeGetAttacked; //被攻击后,参数为伤害结果 public OrderedDictionary> onAfterGetAttacked; //被攻击后,参数为伤害结果 public EventSubmodule(BuffBase buff) : base(buff) { onOtherBuffApplied = new OrderedDictionary>>(); onOtherBuffFirstApplied = new OrderedDictionary>>(); onOtherBuffRemoved = new OrderedDictionary>>(); onDealAttack = new OrderedDictionary>(); onBeforeGetAttacked = new OrderedDictionary>(); onAfterGetAttacked = new OrderedDictionary>(); } } public class TimeSubmodule : BuffSubmodule { public bool isInfinite; public float duration; public float timeLeft; public float TimeLeftPercentage => timeLeft / duration; public List intervalActions; public TimeSubmodule(BuffBase buff, bool isInfinite): base(buff) { this.buff = buff; this.isInfinite = isInfinite; this.duration = -1; this.timeLeft = -1; this.intervalActions = new List(); } public TimeSubmodule(BuffBase buff, float duration): base(buff) { this.buff = buff; this.isInfinite = false; this.duration = duration; this.timeLeft = duration; this.intervalActions = new List(); } public void Update(float deltaTime) { foreach (var action in intervalActions) { action.Update(deltaTime); } if (isInfinite) { return; } timeLeft -= deltaTime; if (timeLeft <= 0) { buff.Remove(); } } public void AddIntervalAction(Action action, float interval) { intervalActions.Add(new IntervalAction(action, interval)); } public void RefreshDuration() { timeLeft = duration; } public void PickHigherDuration(TimeSubmodule other) { duration = Mathf.Max(duration, other.duration); timeLeft = duration; } public void StackDuration(TimeSubmodule other) { duration += other.duration; timeLeft += other.duration; } public class IntervalAction { public float timer; float interval; Action action; public IntervalAction(Action action, float interval) { this.action = action; this.interval = interval; this.timer = 0f; } public void Update(float deltaTime) { timer += deltaTime; if (timer >= interval) { action.Invoke(); timer -= interval; } } public void SetInterval(float interval) { this.interval = interval; if (timer > interval) { timer = interval; } } } } public class CountSubmodule : BuffSubmodule { public int maximumCount; public int remainingCount; public bool isInfinite => maximumCount < 0; public float remainingPercentage => (float)remainingCount / maximumCount; public UnityAction onCountChanged; /// /// maximumCount为负数表示无限持续时间。 /// public CountSubmodule(BuffBase buff, int maximumCount = -1) : base(buff) { this.maximumCount = maximumCount; this.remainingCount = maximumCount; } public void Update() { if (isInfinite) { return; } remainingCount--; onCountChanged?.Invoke(remainingCount); if (remainingCount <= 0) { buff.Remove(); } } /// /// 刷新剩余时间至初始值。 /// public void Refresh() { if (isInfinite) { return; } remainingCount = maximumCount; onCountChanged?.Invoke(remainingCount); } /// /// 覆盖(可选保留更大的duration)并刷新剩余时间。 /// public void Refresh(int overrideDuration, bool keepMaximal = true) { if (isInfinite) { return; } maximumCount = keepMaximal ? Mathf.Max(maximumCount, overrideDuration) : overrideDuration; remainingCount = maximumCount; onCountChanged?.Invoke(remainingCount); } /// /// 增加持续时间和剩余时间。 /// public void AddCount(int maxCount) { if (isInfinite) { return; } maximumCount += maxCount; remainingCount += maxCount; onCountChanged?.Invoke(remainingCount); } /// /// 仅增加剩余时间,不改变总持续时间。 /// 如果增加后剩余时间超过总持续时间,则剩余时间等于总持续时间。 /// public void AddRemainingCount(int count) { if (isInfinite) { return; } remainingCount += count; remainingCount = Mathf.Min(remainingCount, maximumCount); onCountChanged?.Invoke(remainingCount); } /// /// 选择更高的持续时间和剩余时间。 /// public void PickHigherCount(CountSubmodule other) { if (isInfinite) { return; } maximumCount = Mathf.Max(maximumCount, other.maximumCount); remainingCount = Mathf.Max(remainingCount, other.remainingCount); } } /// /// Buff叠加模块,叠加层数统一。 /// public class UnitedStackSubmodule : BuffSubmodule { public bool willRemoveOnZero; //是否在层数为0时移除Buff public bool isIntegerRange; //是否为整数范围型Buff(可为0或负数) public int stackAmount; //当前层数 public int stackUpperLimit; //层数上限,-1表示无限制 public IBuffExtension_IntegerRange IntegerRange => buff as IBuffExtension_IntegerRange; public UnitedStackSubmodule(BuffBase buff, int initialStackAmount = 1, bool isIntegerRange = false) : base(buff) { this.willRemoveOnZero = true; this.isIntegerRange = isIntegerRange; this.stackAmount = initialStackAmount; this.stackUpperLimit = -1; } public UnitedStackSubmodule(BuffBase buff, bool willRemoveOnZero, int stackUpperLimit = -1, int initialStackAmount = 1, bool isIntegerRange = false) : base(buff) { this.willRemoveOnZero = willRemoveOnZero; this.isIntegerRange = isIntegerRange; this.stackAmount = initialStackAmount; this.stackUpperLimit = stackUpperLimit; } public void RefreshStackUpperLimit(int upperLimit, bool keepMaximal = true) { stackUpperLimit = keepMaximal ? Mathf.Max(stackUpperLimit, upperLimit) : upperLimit; } public void PickHigherStack(UnitedStackSubmodule other) { stackAmount = Mathf.Max(stackAmount, other.stackAmount); if (stackUpperLimit > 0) { stackAmount = Mathf.Min(stackAmount, stackUpperLimit); } } public void AddStack(int amount) => ModifyStack(amount); public void ReduceStack(int amount) => ModifyStack(-amount); public void ModifyStack(int amount) { int lastStack = stackAmount; stackAmount += amount; if (stackUpperLimit > 0) { stackAmount = Mathf.Min(stackAmount, stackUpperLimit); } if (willRemoveOnZero) { if (!isIntegerRange && stackAmount <= 0) { buff.Remove(); return; } if (isIntegerRange && stackAmount == 0) { buff.Remove(); return; } } if (isIntegerRange) { if (lastStack < 0 && stackAmount > 0) { IntegerRange.OnBecomePositive(); } else if (lastStack > 0 && stackAmount < 0) { IntegerRange.OnBecomeNegative(); } else if (lastStack != 0 && stackAmount == 0) { IntegerRange.OnBecomeZero(); } } } public bool ReachedUpperLimit() { if (stackUpperLimit < 0) { return false; } return stackAmount >= stackUpperLimit; } public void ClearAllStacks() { stackAmount = 0; if (willRemoveOnZero) { buff.Remove(); } } } /// /// Buff独立叠加模块,每一层的持续时间和层数可以不同。 /// public class IndependentStackSubmodule : BuffSubmodule { public bool willRemoveOnZero; public List independentStacks; public int totalStackAmount; public IndependentStackSubmodule(BuffBase buff, bool willRemoveOnZero = true) : base(buff) { independentStacks = new List(); totalStackAmount = 0; this.willRemoveOnZero = willRemoveOnZero; } public IndependentStackSubmodule(BuffBase buff, int stack, float duration, bool willRemoveOnZero = true) : base(buff) { independentStacks = new List(); AddStack(stack, duration); totalStackAmount = stack; this.willRemoveOnZero = willRemoveOnZero; } public IndependentStackSubmodule(BuffBase buff, int stack, float duration, bool willRemoveOnZero, out IndependentStackUnit unit) : base(buff) { independentStacks = new List(); unit = AddStack(stack, duration); totalStackAmount = stack; this.willRemoveOnZero = willRemoveOnZero; } public void Update(float deltaTime) { independentStacks.ForEach(x => x.remainingTime -= deltaTime); independentStacks.RemoveAll(x => !x.IsInfinite && x.remainingTime <= 0); totalStackAmount = independentStacks.Sum(x => x.stackAmount); if (willRemoveOnZero && totalStackAmount <= 0) { buff.Remove(); } } public IndependentStackUnit LongestUnit => independentStacks.Count > 0 ? independentStacks[^1] : null; public void Merge(IndependentStackSubmodule other) { foreach (IndependentStackUnit stack in other.independentStacks) { independentStacks.Add(stack.Clone()); } independentStacks.Sort(); } public IndependentStackUnit AddStack(int stackAmount, float duration) { IndependentStackUnit addition = new IndependentStackUnit(stackAmount, duration); independentStacks.Add(addition); independentStacks.Sort(); return addition; } public void ReduceStack(int stackAmount) { for (int i = 0; i < independentStacks.Count; i++) { if (stackAmount <= independentStacks[i].stackAmount) { independentStacks[i].stackAmount -= stackAmount; if (independentStacks[i].stackAmount <= 0) { independentStacks.RemoveAt(i); } return; } stackAmount -= independentStacks[i].stackAmount; independentStacks.RemoveAt(i); i--; } totalStackAmount = independentStacks.Sum(x => x.stackAmount); if (willRemoveOnZero && totalStackAmount <= 0) { buff.Remove(); } } public class IndependentStackUnit : IComparable, ICloneable { public int stackAmount; public float duration; public float remainingTime; public Dictionary parameters; public bool IsInfinite => duration < 0; public float RemainingPercentage => IsInfinite ? 1f : remainingTime / duration; public IndependentStackUnit(int stackAmount, float duration) { this.stackAmount = stackAmount; this.duration = duration; this.remainingTime = duration; this.parameters = new Dictionary(); } public int CompareTo(IndependentStackUnit other) { return remainingTime.CompareTo(other.remainingTime); } public IndependentStackUnit Clone() { IndependentStackUnit clone = new IndependentStackUnit(stackAmount, duration); clone.remainingTime = remainingTime; foreach (var param in parameters) { clone.parameters[param.Key] = param.Value; } return clone; } } } } }