using System; using System.Collections.Generic; using CoreGame.Render; using Framw.AudioFramework; using GAS.Runtime; using Sog; using UnityEngine; namespace CoreGame.Render { public sealed class GARush : GameplayAbility { public GARush(IAbilityData abilityAsset) : base(abilityAsset) { } public override AbilitySpec CreateSpec(AbilitySystemComponent owner, GameAbilityContext ctx) { var rushAbilitySpec = SptPool.Malloc(); rushAbilitySpec.Awake(this, ctx); return rushAbilitySpec; } public override void FreeSpec(ref AbilitySpec spec) { if (spec is not GARushSpec rushAbilitySpec) { BattleLogger.LogInfo("RushAbilitySpec.FreeSpec: spec is not RushAbilitySpec"); return; } SptPool.Free(ref rushAbilitySpec); } } public sealed class GARushSpec : AbilitySpec, ISptPool { private Fixed64 m_TimeAcc; private bool m_StartAnimPlayed; private bool m_LoopAnimPlayed; private bool m_EndAnimPlayed; private Fixed64 m_StartAnimEndTime; private Fixed64 m_LoopAnimEndTime; private Fixed64 m_EndAnimEndTime; private Fixed64 m_RushSpeed; private Fixed64 m_Distance; private Fixed64Vector2 m_RushDir; private static Collider2D[] s_HitResults; private LayerMask m_LayerMask; private Fixed64 m_DirAngle; private List m_HitDataList; private List m_VFXList; private int m_SoundIdx; private static List s_CacheEnts = new(); private GARushAsset RushAsset => Ability.DataReference as GARushAsset; public override void Awake(GameplayAbility ability, GameAbilityContext gaCtx) { base.Awake(ability, gaCtx); m_HitDataList = ListPool.Pop(); m_VFXList = ListPool.Pop(); } public override void ActivateAbility() { m_TimeAcc = 0f; m_SoundIdx = -1; s_HitResults = new Collider2D[20]; m_LayerMask = ColliderSrv.GetLayerMask(ctx.ownerEnt.faction.faction, 5); TargetSelectSrv.SpellSelectEnts(ctx, RushAsset.castPointSelectCfgId, ctx.castPos, s_CacheEnts); ctx.FillInCastEnt(s_CacheEnts); var offset = ctx.castPos[0] - ctx.ownerEnt.logicTransform.position; m_RushSpeed = RushAsset.speed; switch (RushAsset.rushType) { case GARushAsset.RushType.GetTo: m_Distance = offset.Magnitude; m_RushDir = offset / m_Distance; break; case GARushAsset.RushType.Toward: m_Distance = RushAsset.distance; m_RushDir = offset; m_RushDir.Normalize(); break; default: throw new ArgumentOutOfRangeException(); } m_DirAngle = FixedMath.Angle(Fixed64Vector2.right, m_RushDir); m_StartAnimEndTime = RushAsset.startAnimDuration; m_LoopAnimEndTime = m_StartAnimEndTime + m_Distance / m_RushSpeed; m_EndAnimEndTime = m_LoopAnimEndTime + RushAsset.endAnimDuration; DoCost(); } protected override void AbilityTick(Fixed64 dt) { // var animationProxy = ctx.ownerEnt.animationProxy; // if (m_TimeAcc < m_StartAnimEndTime) // { // if (!m_StartAnimPlayed) // { // if (RushAsset.startAnimStateName != string.Empty) // { // animationProxy.Play(RushAsset.StartAnimStateNameFName, 1f, true); // } // m_StartAnimPlayed = true; // } // } // else if (m_TimeAcc < m_LoopAnimEndTime) // { // if (!m_LoopAnimPlayed) // { // if (!string.IsNullOrEmpty(RushAsset.loopAnimStateName)) // { // animationProxy.Play(RushAsset.LoopAnimStateNameFName, 1f, true); // } // if (RushAsset.castEffectId > 0) // { // TexiaoShowParam param = default; // param.effectId = RushAsset.castEffectId; // param.scale = Vector3.one; // param.rotation = Quaternion.identity; // param.offset = Vector2.zero; // ctx.ownerEnt.effectShowProxy.GA_ShowCastEffect(ref param, null, m_VFXList); // } // if (!string.IsNullOrEmpty(RushAsset.rushSound)) // { // var soundDesc = SoundDescMgr.Instance.GetConfig(RushAsset.rushSound); // m_SoundIdx = SoundManager.Instance.PlayLoop(soundDesc.path); // } // m_LoopAnimPlayed = true; // } // // // 移动 // var offset = m_RushSpeed * dt * m_RushDir; // if (!ForceMoveSrv.ForceMoveEntity(ctx.ownerEnt, offset, true)) // { // m_TimeAcc = m_LoopAnimEndTime; // return; // } // // // 碰撞检测 // var cnt = PhysicsHelper.OverlapBoxNonAlloc2D(ctx.ownerEnt.transformProxy.position, RushAsset.boxSize, // m_DirAngle, ref s_HitResults, m_LayerMask); // // for (var i = 0; i < cnt; i++) // { // var hitEnt = ColliderSrv.GetEntityByCollider(s_HitResults[i]); // if (hitEnt == null) continue; // // var canHit = true; // for (var j = m_HitDataList.Count - 1; j >= 0; j--) // { // if (m_HitDataList[j].targetEid != hitEnt.creationIndex) continue; // canHit = false; // break; // } // // if (!canHit) continue; // // var hitPos = hitEnt.transformProxy.position; // var hitData = SptPool.Malloc(); // hitData.Awake(hitEnt.creationIndex, m_TimeAcc, hitPos, m_RushDir); // m_HitDataList.Add(hitData); // // // 造成伤害 // var context = AbilitySrv.GrantTransferAbility(ctx.ownerEnt, RushAsset.castHurtSkillId, // ctx.abilitySpec.gaInitCfg, null, ctx.level); // if (context != null) // { // context.castTarget.Add(hitEnt.creationIndex); // context.castPos.Add(hitPos); // context.AddHitDataByRefs(m_HitDataList); // context.dropAbilityWhenEnd = true; // context.asc.TryActivateAbility_WithSeqAndParam(context.gaSeq, ctx.abilitySpec.gaParams); // } // } // } // else if (RushAsset.endAnimStateName == string.Empty || RushAsset.endAnimDuration <= 0.01f) // { // TryEndAbility(); // return; // } // else if (m_TimeAcc < m_EndAnimEndTime) // { // if (!m_EndAnimPlayed) // { // animationProxy.Play(RushAsset.EndAnimStateNameFName, 1f, true); // DestroyEffect(); // m_EndAnimPlayed = true; // } // } // else // { // TryEndAbility(); // return; // } // // m_TimeAcc += dt; } public override void CancelAbility() { } public override void EndAbility() { ctx.ownerEnt.animationProxy.Play(FNameLookup.Idle, 1f, true); m_StartAnimPlayed = false; m_LoopAnimPlayed = false; m_EndAnimPlayed = false; for (var i = m_HitDataList.Count - 1; i >= 0; i--) { var hasHitEid = m_HitDataList[i]; SptPool.Free(ref hasHitEid); } DestroyEffect(); m_HitDataList.Clear(); m_VFXList.Clear(); } private void DestroyEffect() { if (RushAsset.castEffectId > 0) { ctx.ownerEnt.effectShowProxy.DestroyEffect(m_VFXList); } if (!string.IsNullOrEmpty(RushAsset.rushSound) && m_SoundIdx != -1) { SoundManager.Instance.StopLoop(m_SoundIdx); } } public void Reset() { ListPool.Push(ref m_HitDataList); ListPool.Push(ref m_VFXList); } } }