hch
2025-09-03 bc4197c636bd2bbf011bf94cd24ebfc7b060f2d7
Main/System/Battle/Skill/SkillBase.cs
@@ -9,6 +9,8 @@
public class SkillBase
{
   const float moveTime = 0.5f;
   protected SkillEffect skillEffect;
   protected HB427_tagSCUseSkill tagUseSkillAttack;
@@ -54,6 +56,11 @@
         curFrame++;
      }
      if (null != skillEffect)
      {
         skillEffect.Run();
      }
      if (otherSkillAction != null)
      {
         if (otherSkillAction.IsFinished())
@@ -86,12 +93,14 @@
   // 1·移动到距离阵容位置n码的距离(如2号位,5号位)释放(即战场中央此类)
   public virtual void Cast()
   {
      Debug.LogError(GetType().Name + " Skill Cast Start");
      EventBroadcast.Instance.Broadcast<string, SkillConfig, TeamHero>(EventName.BATTLE_CAST_SKILL, battleField.guid, skillConfig, caster.teamHero);
      BattleDebug.LogError(GetType().Name + " Skill Cast Start");
      //   高亮所有本次技能相关的目标
      HighLightAllTargets();
      //   距离配成负数要转身 TurnBack
      Debug.LogError(GetType().Name + " Skill CastMode : " + skillConfig.castMode);
      BattleDebug.LogError(GetType().Name + " Skill CastMode : " + skillConfig.castMode);
      switch (skillConfig.castMode)
      {
         case SkillCastMode.Self:
@@ -110,7 +119,7 @@
         //    DashToTarget(() => BackToOrigin(OnSkillFinished));
         //    break;
         default:
            Debug.LogError("暂时不支持其他的方式释放 有需求请联系策划 技能id:" + skillConfig.SkillID + " cast position " + skillConfig.CastPosition);
            BattleDebug.LogError("暂时不支持其他的方式释放 有需求请联系策划 技能id:" + skillConfig.SkillID + " cast position " + skillConfig.CastPosition);
            OnSkillFinished();
            break;
      }
@@ -118,6 +127,14 @@
   protected void MoveToTarget(RectTransform target, Vector2 offset, float duration, Action onComplete = null)
   {
      BattleDebug.LogError("Move to target , target is " + target.name);
      //   原地释放
      if (skillConfig.CastDistance >= 9999)
      {
         onComplete?.Invoke();
         return;
      }
      caster.motionBase.PlayAnimation(MotionName.run, true);
      var tweener = BattleUtility.MoveToTarget(caster.heroRectTrans, target, offset, duration, () =>
      {
@@ -141,7 +158,6 @@
   protected void CastToEnemy()
   {
      const float moveTime = 0.5f;
      RectTransform target = battleField.GetTeamNode(caster.GetEnemyCamp(), skillConfig);
@@ -161,6 +177,7 @@
                     {
                        TurnBack(null, 1f);
                        caster.motionBase.PlayAnimation(MotionName.idle, true);
                        OnAllAttackMoveFinished();
                     });
                  }
               , -1f);
@@ -176,7 +193,7 @@
      // 目标是敌方主目标
      if (tagUseSkillAttack.HurtCount <= 0)
      {
         Debug.LogError("技能攻击包没有目标 HurtCount <= 0");
         BattleDebug.LogError("技能攻击包没有目标 HurtCount <= 0");
         OnSkillFinished();
         return;
      }
@@ -186,22 +203,85 @@
      BattleObject mainTarget = battleField.battleObjMgr.GetBattleObject((int)mainHurt.ObjID);
      if (mainTarget == null)
      {
         Debug.LogError("目标为空 mainTarget == null ObjID : " + mainHurt.ObjID);
         BattleDebug.LogError("目标为空 mainTarget == null ObjID : " + mainHurt.ObjID);
         OnSkillFinished();
         return;
      }
      // MoveToTarget(mainTarget.Camp, mainTarget, _onComplete: () => TurnBack(() => CastImpl(() => DoSkillLogic(() => { BackToOrigin(OnSkillFinished); }))));
      MoveToTarget(mainTarget.heroRectTrans, new Vector2(skillConfig.CastDistance, 0), moveTime, () =>
      {
         //   到位置转身(不一定非要转身 但是流程要写)
         TurnBack(() =>
         {
            //   到达目标位置
            CastImpl(() =>
            {
               TurnBack(
                  () =>
                  {
                     //   回到原来的位置
                     MoveToTarget(battleField.GetTeamNode(caster.Camp, caster.teamHero.positionNum), Vector2.zero, moveTime, () =>
                     {
                        TurnBack(null, 1f);
                        caster.motionBase.PlayAnimation(MotionName.idle, true);
                        OnAllAttackMoveFinished();
                     });
                  }
               , -1f);
            });
         }, -1f);
      });
   }
   protected virtual void OnAllAttackMoveFinished()
   {
   }
   protected void CastToAllies()
   {
      // MoveToTarget(caster.Camp, skillConfig, _onComplete: () => TurnBack(() => CastImpl(() => DoSkillLogic(() => { BackToOrigin(OnSkillFinished); }))));
      RectTransform target = battleField.GetTeamNode(caster.Camp, skillConfig);
      MoveToTarget(target, new Vector2(skillConfig.CastDistance, 0), moveTime, () =>
      {
         //   到位置转身(不一定非要转身 但是流程要写)
         TurnBack(() =>
         {
            //   到达目标位置
            CastImpl(() =>
            {
               TurnBack(
                  () =>
                  {
                     //   回到原来的位置
                     MoveToTarget(battleField.GetTeamNode(caster.Camp, caster.teamHero.positionNum), Vector2.zero, moveTime, () =>
                     {
                        TurnBack(null, 1f);
                        caster.motionBase.PlayAnimation(MotionName.idle, true);
                        OnAllAttackMoveFinished();
                     });
                  }
               , -1f);
            });
         }, -1f);
      });
   }
   //   承载技能大部分的逻辑
   protected TrackEntry CastImpl(Action onComplete = null)
   {
      // 播放施法动作
      return caster.motionBase.PlaySkillAnimation(skillConfig, this, onComplete);//攻击中摇结束
      //   onComplete是指施法动作播放完的回调 不代表是技能结束
      //   具体技能结束的时间应该看技能对应的逻辑
      //   这里只提供6个动作相关的函数
      // OnSkillStart 动作第一帧
      // OnStartSkillFrameEnd 前摇结束
      // OnMiddleFrameStart 中摇开始
      // OnMiddleFrameEnd 中摇结束
      // OnFinalFrameStart 后摇开始
      // OnFinalFrameEnd 后摇结束
      return caster.motionBase.PlaySkillAnimation(skillConfig, this, onComplete);
   }
   //   技能开始
@@ -230,12 +310,12 @@
   /// <param name="times"></param>
   public virtual void OnMiddleFrameStart(int times)
   {
      skillEffect.OnMiddleFrameStart(times);
   }
   public virtual void OnMiddleFrameEnd(int times, int hitIndex)
   {
      skillEffect.OnMiddleFrameEnd(times, hitIndex);
   }
   /// <summary>
@@ -256,56 +336,6 @@
   // public void MoveToTarget(BattleCamp camp, BattleObject target, float duration = 0.2f, Action _onComplete = null)
   // {
   //    targetNode = battleField.GetTeamNode(camp, target);
   //    Vector2 offset = new Vector2(skillConfig.CastDistance, 0);
   //    RectTransform selfRect = caster.heroRectTrans;
   //    RectTransform targetRect = targetNode;
   //    var tweener = BattleUtility.MoveToTarget(selfRect, targetRect, offset, duration, _onComplete);
   //    battleField.battleTweenMgr.OnPlayTween(tweener);
   // }
   // public void MoveToTarget(BattleCamp camp, SkillConfig skillCfg, float duration = 0.2f, Action _onComplete = null)
   // {
   //    targetNode = battleField.GetTeamNode(camp, skillCfg);
   //    Vector2 offset = new Vector2(skillConfig.CastDistance, 0);
   //    RectTransform selfRect = caster.heroRectTrans;
   //    RectTransform targetRect = targetNode;
   //    var tweener = BattleUtility.MoveToTarget(selfRect, targetRect, offset, duration, _onComplete);
   //    battleField.battleTweenMgr.OnPlayTween(tweener);
   // }
   // public void TurnBack(Action _onComplete)
   // {
   //    if (skillConfig.CastDistance < 0)
   //    {
   //       //   转身
   //       caster.heroGo.transform.localScale = new Vector3(-1, 1, 1);
   //    }
   //    _onComplete?.Invoke();
   // }
   // public void BackToOrigin(Action _onComplete = null)
   // {
   //    RectTransform selfRect = caster.heroRectTrans;
   //    Vector2 targetAnchoredPos = Vector2.zero;
   //    var tween = selfRect.DOAnchorPos(targetAnchoredPos, 0.2f)
   //       .SetEase(Ease.Linear);
   //    tween.onComplete += () =>
   //    {
   //       //   转成正确方向
   //       caster.heroGo.transform.localScale = Vector3.one;
   //       _onComplete?.Invoke();
   //    };
   //    battleField.battleTweenMgr.OnPlayTween(tween);
   // }
   protected void HighLightAllTargets()
   {
@@ -328,32 +358,62 @@
         BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
         if (target == null)
         {
            Debug.LogError("目标为空 target == null ObjId : " + hurt.ObjID);
            BattleDebug.LogError("目标为空 target == null ObjId : " + hurt.ObjID);
            continue;
         }
         // 伤害分布 (万分比)
         int[] damageDivide = skillConfig.DamageDivide[_hitIndex];
         long totalDamage = GeneralDefine.GetFactValue(hurt.HurtHP, hurt.HurtHPEx);
         // 保证所有分配项加起来等于totalDamage,避免因整除导致的误差
         List<long> damageList = BattleUtility.DivideDamageToList(damageDivide, totalDamage);
         OnHitEachTarget(target, totalDamage, damageList, ref hurt);
         OnHitEachTarget(_hitIndex, target, hurt);
      }
      HandleDead();
   }
   protected virtual void OnHitEachTarget(int _hitIndex, BattleObject target, HB427_tagSCUseSkill.tagSCUseSkillHurt hurt)
   {
      // 伤害分布 (万分比)
      int[] damageDivide = skillConfig.DamageDivide[_hitIndex];
      long totalDamage = GeneralDefine.GetFactValue(hurt.HurtHP, hurt.HurtHPEx);
      // 保证所有分配项加起来等于totalDamage,避免因整除导致的误差
      List<long> damageList = BattleUtility.DivideDamageToList(damageDivide, totalDamage);
      // public uint ObjID;
      // public uint AttackTypes;        // 飘血类型汇总,支持多种类型并存,如无视防御且暴击同时被格挡,二进制或运算最终值;0-失败;1-普通;2-回血;5-格挡;6-无视防御;7-暴击;9-闪避
      // public uint HurtHP;        // 飘血值,求余亿部分
      // public uint HurtHPEx;        // 飘血值,整除亿部分
      // public uint CurHP;        // 更新剩余血量,求余亿部分
      // public uint CurHPEx;        // 更新剩余血量,整除亿部分
      // public uint SuckHP;        // 本次伤害转化的吸血量
      // public uint BounceHP;        // 本次伤害反弹的伤害量
      //   TODO YYL AttackTypes  要表现成什么样呢? 支持多种类型并存,如无视防御且暴击同时被格挡,二进制或运算最终值;0-失败;1-普通;2-回血;5-格挡;6-无视防御;7-暴击;9-闪避
      target.Hurt(damageList, totalDamage, hurt.AttackTypes);
      //   TODO YYL 这里是要做统一计算后再hurt跟suckhp还是怎样
      // caster.SuckHp(hurt.SuckHP);//   吸血
      // caster.HurtByReflect(hurt.BounceHP);// 反弹伤害
   }
   protected void HandleDead()
   {
      var deadPackList = BattleUtility.FindDeadPack(packList);
      int deadCount = deadPackList.Count;
      if (deadCount <= 0)
      {
         //   如果没死亡就不用管
         return;
      }
      CheckAfterDeadhPack();
      // 处理掉落包 提前distribute之后 PackManager才有掉落物 所以不跟assignexp一样distribute
      foreach (var _dropPack in dropPackList)
      {
         BattleDebug.LogError("distribute pack " + _dropPack.GetType().Name);
         PackageRegedit.Distribute(_dropPack);
         packList.Remove(_dropPack);
      }
@@ -366,7 +426,7 @@
         where item != null && item.isAuction
         select item);
      int deadCount = deadPackList.Count;
      // 分配掉落和经验
      var dropAssign = AssignDrops(itemList, deadCount);
@@ -378,7 +438,7 @@
         BattleObject deadTarget = battleField.battleObjMgr.GetBattleObject((int)deadPackList[i].ObjID);
         List<ItemModel> itemModelDrops = dropAssign[i];
         List<int> itemModelDropsIndexList = new List<int>(
            from item in itemModelDrops  select item.gridIndex);
            from item in itemModelDrops select item.gridIndex);
         BattleDrops battleDrops = new BattleDrops()
         {
            rectTransform = deadTarget.heroRectTrans,
@@ -389,12 +449,15 @@
      }
      // 分发死亡包
      battleField.OnObjsDead(deadPackList);
      battleField.OnObjsDead(new List<HB422_tagMCTurnFightObjDead>(deadPackList));
      foreach (var deadPack in deadPackList)
      {
         packList.Remove(deadPack);
      }
      deadPackList.Clear();
   }
@@ -442,22 +505,6 @@
   }
   protected virtual void OnHitEachTarget(BattleObject target, long totalDamage, List<long> damageList, ref HB427_tagSCUseSkill.tagSCUseSkillHurt hurt)
   {
      target.Hurt(damageList, totalDamage, hurt.AttackTypes);
      //   击中目标的时候,不管近战远程 都确认一下是否有爆炸特效 然后播放
      if (skillConfig.ExplosionEffectId > 0)
      {
         // 播放爆炸特效
         target.battleField.battleEffectMgr.PlayEffect(
            target.ObjID,
            skillConfig.ExplosionEffectId,
            target.heroGo.transform
         );
      }
   }
   protected void CheckAfterDeadhPack()
   {
@@ -515,6 +562,19 @@
   }
   public virtual bool IsFinished()
   {
      if (skillEffect != null)
      {
         if (!skillEffect.IsFinished())
         {
            return false;
         }
         else
         {
            OnSkillFinished();
            skillEffect = null;
         }
      }
      return isFinished;
   }
@@ -525,8 +585,16 @@
   public void OnSkillFinished()
   {
      Debug.LogError(GetType().Name + " Skill Finished");
      if (packList.Count > 0)
      if (skillEffect != null)
      {
         if (!skillEffect.IsFinished())
         {
            return;
         }
      }
      BattleDebug.LogError(GetType().Name + " Skill Finished");
      while (packList.Count > 0)
      {
         var pack = packList[0];
         packList.RemoveAt(0);
@@ -540,7 +608,7 @@
               return;
            }
         }
         BattleDebug.LogError("distribute pack " + pack.GetType().Name);
         PackageRegedit.Distribute(pack);
      }