using System; using System.Collections.Generic; using Lean.Pool; using UnityEngine; namespace Cielonos.MainGame { public partial class TimeSubmodule : AttackAreaSubmoduleBase { public float lifeTime; public float delayTime; public float enablingTimer; public float remainingEnableTime; public float remainingLifeTime; public Action enableAction; public Action timeOutAction; public List scheduledActions; private List toBeExecutedScheduledActions = new List(); /// /// enable 阶段开始前允许反应的提前量(秒),默认 0 表示无提前 grace window。 /// public float reactionGraceBefore; public TimeSubmodule(AttackAreaBase attackArea, float lifeTime, Action timeOutAction = null) : base(attackArea) { this.isEnabling = true; this.lifeTime = lifeTime; this.remainingLifeTime = lifeTime; this.enablingTimer = 0; this.scheduledActions = new List(); if (attackArea is NormalArea) { this.remainingEnableTime = lifeTime * 0.25f; } else if (attackArea is Projectile) { this.remainingEnableTime = lifeTime; } else { this.remainingEnableTime = lifeTime; } this.timeOutAction = timeOutAction ?? (() => { if (attackArea is Projectile projectile) { projectile.Explode(projectile.transform.position); } else { LeanPool.Despawn(attackArea.topParent); } }); } public TimeSubmodule(AttackAreaBase attackArea, float lifeTime, float delayTime, float enableTime, Action enableAction, Action timeOutAction) : this(attackArea, lifeTime, delayTime, enableTime, enableAction, timeOutAction, 0f) { } public TimeSubmodule(AttackAreaBase attackArea, float lifeTime, float delayTime, float enableTime, Action enableAction, Action timeOutAction, float graceBefore) : base(attackArea) { this.isEnabling = true; this.lifeTime = lifeTime; this.delayTime = delayTime; this.attackArea.isEnabling = delayTime <= 0; this.scheduledActions = new List(); this.timeOutAction = timeOutAction ?? (() => { if (attackArea is Projectile projectile) { projectile.Explode(projectile.transform.position); } else { LeanPool.Despawn(attackArea.topParent); } }); if (this.attackArea.isEnabling) { enableAction?.Invoke(); } this.remainingLifeTime = lifeTime; this.enablingTimer = 0; this.remainingEnableTime = enableTime; this.enableAction = enableAction; this.reactionGraceBefore = graceBefore; } public TimeSubmodule AddScheduleAction(Action action, float delay) { scheduledActions.Add(new ScheduledAction(action, delay)); return this; } /// /// 判断当前时刻是否处于反应窗口内(包含 grace 区间和 enable 阶段本身)。 /// before grace: delay 阶段末尾的 reactionGraceBefore 秒内。 /// after grace: enable 结束后的 reactionGraceAfter 秒内。 /// public bool IsReactionActive() { // 在 enable 阶段本身,反应始终可用 if (attackArea.isEnabling) { return true; } // before grace: delay 尚未结束,但已进入 grace 窗口 if (delayTime > 0f && reactionGraceBefore > 0f && delayTime <= reactionGraceBefore) { return true; } return false; } } public partial class TimeSubmodule { public void Update() { if (!isEnabling) return; if (delayTime > 0) { delayTime -= attackArea.creator.selfTimeSm.DeltaTime; return; } if (!attackArea.isEnabling) { attackArea.isEnabling = true; enableAction?.Invoke(); } toBeExecutedScheduledActions.Clear(); foreach (var scheduledAction in scheduledActions) { scheduledAction.delay -= attackArea.creator.selfTimeSm.DeltaTime; if (scheduledAction.delay <= 0) { toBeExecutedScheduledActions.Add(scheduledAction); } } foreach (var scheduledAction in toBeExecutedScheduledActions) { scheduledAction.action.Invoke(); scheduledActions.Remove(scheduledAction); } if (remainingLifeTime <= 0) { this.isEnabling = false; timeOutAction?.Invoke(); } if (remainingEnableTime <= 0) { attackArea.isEnabling = false; } enablingTimer += attackArea.creator.selfTimeSm.DeltaTime; remainingLifeTime -= attackArea.creator.selfTimeSm.DeltaTime; remainingEnableTime -= attackArea.creator.selfTimeSm.DeltaTime; } public void ModifyLifeTime(float modifyValue) { lifeTime += modifyValue; remainingLifeTime += modifyValue; } } public partial class TimeSubmodule { public class ScheduledAction { public Action action; public float delay; public ScheduledAction(Action action, float delay) { this.action = action; this.delay = delay; } } } }