private static async ETVoid StartCommonAttack(this CommonAttackComponent self)
        {
            self.CancellationTokenSource?.Cancel();
            self.CancellationTokenSource = new CancellationTokenSource();
            //如果有要执行攻击流程替换的内容,就执行替换流程
            if (self.HasAttackReplaceInfo())
            {
                NP_RuntimeTree npRuntimeTree = self.Entity.GetComponent <NP_RuntimeTreeManager>().GetTreeByRuntimeID(self.AttackReplaceNPTreeId);
                Blackboard     blackboard    = npRuntimeTree.GetBlackboard();

                blackboard.Set(self.AttackReplaceBB.BBKey, true);
                blackboard.Set(self.CancelAttackReplaceBB.BBKey, false);

                blackboard.Set("NormalAttackUnitIds", new List <long>()
                {
                    self.CachedUnitForAttack.Id
                });

                return;
            }
            else
            {
                await self.CommonAttack_Internal();
            }

            //此次攻击完成
            self.CancellationTokenSource.Dispose();
            self.CancellationTokenSource = null;
        }
        public static void Update(this CommonAttackComponent self)
        {
            if (!self.CanAttack)
            {
                if (TimeHelper.Now() - self.LastAttackTime > self.AttackInterval)
                {
                    self.CanAttack = true;
                }
            }

            if (self.CanAttack && self.Entity.GetComponent <StackFsmComponent>().GetCurrentFsmState().StateTypes == StateTypes.CommonAttack)
            {
                //目标不为空,且处于攻击状态,且上次攻击已完成或取消
                if (self.CachedUnitForAttack != null && !self.CachedUnitForAttack.IsDisposed &&
                    (self.CancellationTokenSource == null || self.CancellationTokenSource.IsCancellationRequested))
                {
                    float distance = Vector3.Distance((self.Entity as Unit).Position, self.CachedUnitForAttack.Position);
                    //目标距离大于当前攻击距离会先进行寻路,这里的1.75为175码
                    if (distance > 1.75)
                    {
                        self.Entity.GetComponent <UnitPathComponent>().MoveTo_InternalWithOutStateChange(self.CachedUnitForAttack.Position)
                        .Coroutine();
                    }
                    else
                    {
                        self.Entity.GetComponent <UnitPathComponent>().CancelMove();
                        self.StartCommonAttack().Coroutine();
                    }
                }
            }
        }
        private static async ETTask CommonAttack_Internal(this CommonAttackComponent self)
        {
            HeroDataComponent heroDataComponent = self.Entity.GetComponent <HeroDataComponent>();
            float             attackPre         = heroDataComponent.NodeDataForHero.OriAttackPre / (1 + heroDataComponent.NodeDataForHero.ExtAttackSpeed);
            float             attackPos         = heroDataComponent.NodeDataForHero.OriAttackPos / (1 + heroDataComponent.NodeDataForHero.ExtAttackSpeed);
            float             attackSpeed       = heroDataComponent.NodeDataForHero.OriAttackSpeed + heroDataComponent.NodeDataForHero.ExtAttackSpeed;

            //播放动画,如果动画播放完成还不能进行下一次普攻,则播放空闲动画
            await Game.Scene.GetComponent <TimerComponent>().WaitAsync((long)(attackPre * 1000), self.CancellationTokenSource.Token);

            List <NP_RuntimeTree> targetSkillCanvas = self.Entity.GetComponent <SkillCanvasManagerComponent>().GetSkillCanvas(10001);

            foreach (var skillCanva in targetSkillCanvas)
            {
                skillCanva.GetBlackboard().Set("CastNormalAttack", true);
                skillCanva.GetBlackboard().Set("NormalAttackUnitIds", new List <long>()
                {
                    self.CachedUnitForAttack.Id
                });
            }

            Game.EventSystem.Run(EventIdType.ChangeHP, self.CachedUnitForAttack.Id, -50.0f);
            self.LastAttackTime = TimeHelper.Now();
            self.CanAttack      = false;
            self.AttackInterval = (long)(1 / attackSpeed - attackPre) * 1000;

            await Game.Scene.GetComponent <TimerComponent>().WaitAsync(self.AttackInterval, self.CancellationTokenSource.Token);

            //此次攻击完成
            self.CancellationTokenSource.Dispose();
            self.CancellationTokenSource = null;
        }
        private static async ETVoid StartCommonAttack(this CommonAttackComponent self)
        {
            self.CancellationTokenSource?.Cancel();
            self.CancellationTokenSource = new CancellationTokenSource();

            MessageHelper.Broadcast(new M2C_CommonAttack()
            {
                AttackCasterId = self.Entity.Id, TargetUnitId = self.CachedUnitForAttack.Id, CanAttack = true
            });
            await self.CommonAttack_Internal();
        }
        /// <summary>
        /// 取消攻击但不重置攻击对象
        /// </summary>
        public static void CancelCommonAttackWithOutResetTarget(this CommonAttackComponent self)
        {
            self.CancellationTokenSource?.Cancel();
            self.CancellationTokenSource = null;
            if (self.HasCancelAttackReplaceInfo())
            {
                self.Entity.GetComponent <NP_RuntimeTreeManager>().GetTreeByRuntimeID(self.CancelAttackReplaceNPTreeId).GetBlackboard()
                .Set(self.AttackReplaceBB.BBKey, false);
                self.Entity.GetComponent <NP_RuntimeTreeManager>().GetTreeByRuntimeID(self.CancelAttackReplaceNPTreeId).GetBlackboard()
                .Set(self.CancelAttackReplaceBB.BBKey, true);
            }

            //MessageHelper.Broadcast(new M2C_CancelAttack() { UnitId = self.Entity.Id });
        }
        private static async ETTask CommonAttack_Internal(this CommonAttackComponent self)
        {
            MessageHelper.Broadcast(new M2C_CommonAttack()
            {
                AttackCasterId = self.Entity.Id, TargetUnitId = self.CachedUnitForAttack.Id, CanAttack = true
            });
            HeroDataComponent heroDataComponent = self.Entity.GetComponent <HeroDataComponent>();
            float             attackPre         = heroDataComponent.NodeDataForHero.OriAttackPre / (1 + heroDataComponent.GetAttribute(NumericType.AttackSpeedAdd));
            float             attackSpeed       = heroDataComponent.GetAttribute(NumericType.AttackSpeed);

            //播放动画,如果动画播放完成还不能进行下一次普攻,则播放空闲动画
            await TimerComponent.Instance.WaitAsync((long)(attackPre * 1000), self.CancellationTokenSource.Token);

            DamageData damageData = ReferencePool.Acquire <DamageData>().InitData(BuffDamageTypes.PhysicalSingle | BuffDamageTypes.CommonAttack,
                                                                                  heroDataComponent.GetAttribute(NumericType.Attack), self.Entity as Unit, self.CachedUnitForAttack);

            self.Entity.GetComponent <CastDamageComponent>().BaptismDamageData(damageData);
            float finalDamage = self.CachedUnitForAttack.GetComponent <ReceiveDamageComponent>().BaptismDamageData(damageData);

            if (finalDamage >= 0)
            {
                self.CachedUnitForAttack.GetComponent <HeroDataComponent>().NumericComponent.ApplyChange(NumericType.Hp, -finalDamage);
                //抛出伤害事件,需要监听伤害的buff(比如吸血buff)需要监听此事件
                Game.Scene.GetComponent <BattleEventSystem>().Run($"{EventIdType.ExcuteDamage}{self.Entity.Id}", damageData);
                //抛出受伤事件,需要监听受伤的Buff(例如反甲)需要监听此事件
                Game.Scene.GetComponent <BattleEventSystem>().Run($"{EventIdType.TakeDamage}{self.CachedUnitForAttack.Id}", damageData);
            }

            CDComponent.Instance.TriggerCD(self.Entity.Id, "CommonAttack");
            CDInfo commonAttackCDInfo = CDComponent.Instance.GetCDData(self.Entity.Id, "CommonAttack");

            commonAttackCDInfo.Interval = (long)(1 / attackSpeed - attackPre) * 1000;

            List <NP_RuntimeTree> targetSkillCanvas = self.Entity.GetComponent <SkillCanvasManagerComponent>().GetSkillCanvas(10001);

            foreach (var skillCanva in targetSkillCanvas)
            {
                skillCanva.GetBlackboard().Set("CastNormalAttack", true);
                skillCanva.GetBlackboard().Set("NormalAttackUnitIds", new List <long>()
                {
                    self.CachedUnitForAttack.Id
                });
            }

            await TimerComponent.Instance.WaitAsync(commonAttackCDInfo.Interval, self.CancellationTokenSource.Token);
        }
        public static void SetAttackTarget(this CommonAttackComponent self, Unit targetUnit)
        {
            if (targetUnit == null)
            {
                Log.Error("普攻组件接受到的targetUnit为null");
                return;
            }

            if (targetUnit.GetComponent <B2S_RoleCastComponent>()?.RoleCast == RoleCast.Adverse)
            {
                if (self.CachedUnitForAttack != targetUnit)
                {
                    self.CancelCommonAttack();
                }

                self.CachedUnitForAttack = targetUnit;
                self.Entity.GetComponent <StackFsmComponent>().ChangeState <CommonAttackState>(StateTypes.CommonAttack, "CommonAttack", 1);
            }
        }
        public static void Update(this CommonAttackComponent self)
        {
            if (self.Entity.GetComponent <StackFsmComponent>().GetCurrentFsmState().StateTypes == StateTypes.CommonAttack)
            {
                if (self.CachedUnitForAttack != null && !self.CachedUnitForAttack.IsDisposed)
                {
                    Vector3 selfUnitPos = (self.Entity as Unit).Position;
                    double  distance    = Vector3.Distance(selfUnitPos, self.CachedUnitForAttack.Position);
                    float   attackRange = self.Entity.GetComponent <HeroDataComponent>().NumericComponent[NumericType.AttackRange] / 100;
                    //目标距离大于当前攻击距离会先进行寻路,这里的1.75为175码
                    if (distance >= attackRange)
                    {
                        if (!CDComponent.Instance.GetCDResult(self.Entity.Id, "MoveToAttack"))
                        {
                            return;
                        }

                        CDComponent.Instance.TriggerCD(self.Entity.Id, "MoveToAttack");
                        self.IsMoveToTarget = true;

                        //移动完进入攻击状态
                        CommonAttackState commonAttackState = ReferencePool.Acquire <CommonAttackState>();
                        commonAttackState.SetData(StateTypes.CommonAttack, "CommonAttack", 1);

                        self.Entity.GetComponent <UnitPathComponent>()
                        .NavigateTodoSomething(self.CachedUnitForAttack.Position, attackRange, commonAttackState);
                    }
                    else
                    {
                        //目标不为空,且处于攻击状态,且上次攻击已完成或取消
                        if ((self.CancellationTokenSource == null || self.CancellationTokenSource.IsCancellationRequested))
                        {
                            if (distance <= 1.75 && CDComponent.Instance.GetCDResult(self.Entity.Id, "CommonAttack"))
                            {
                                self.StartCommonAttack().Coroutine();
                            }
                        }
                    }
                }
            }
        }
 /// <summary>
 /// 取消攻击并且重置攻击对象
 /// </summary>
 public static void CancelCommonAttackExtension(this CommonAttackComponent self)
 {
     self.CancelCommonAttackWithOutResetTarget();
     self.CachedUnitForAttack = null;
 }