using System.Collections.Generic; using UnityEngine; using System; using DG.Tweening; using Spine; public class SkillBase { protected H0604_tagUseSkillAttack tagUseSkillAttack; protected SkillConfig skillConfig; protected bool isFinished = false; protected BattleField battleField = null; // 战场 protected RectTransform targetNode = null; // 目标节点 protected BattleObject caster = null; // 施法者 protected bool startCounting = false; protected bool pauseState = false; protected int curFrame = 0; protected List packList; protected SkillBase otherSkill; public SkillBase(BattleObject _caster, SkillConfig _skillCfg, H0604_tagUseSkillAttack vNetData, List _packList, BattleField _battleField = null) { caster = _caster; skillConfig = _skillCfg; tagUseSkillAttack = vNetData; battleField = _battleField; packList = _packList; } public virtual void Run() { if (startCounting) { curFrame++; } } protected virtual void OnActiveSkillFrame() { } protected virtual void OnStartSkillFrame() { } protected virtual void OnEndSkillFrame() { } public void Pause() { pauseState = startCounting; startCounting = false; } public void Resume() { startCounting = pauseState; } // 0·移动到距离目标n码,的距离释放(可配置,9999即原地释放,负数则是移动到人物背面,人物要转身) // 1·移动到距离阵容位置n码的距离(如2号位,5号位)释放(即战场中央此类) public virtual void Cast() { // 高亮所有本次技能相关的目标 HighLightAllTargets(); // 距离配成负数要转身 TurnBack switch (skillConfig.castMode) { case SkillCastMode.Self: PlayCastAnimation(() => DoSkillLogic(OnSkillFinished)); break; case SkillCastMode.Enemy: MoveToTarget(caster.GetEnemyCamp(), skillConfig.CastIndexNum, _onComplete: () => TurnBack(() => PlayCastAnimation(() => DoSkillLogic(() => { BackToOrigin(OnSkillFinished); })))); break; case SkillCastMode.Target: // 目标是敌方主目标 BattleObject mainTarget = battleField.battleObjMgr.GetBattleObject((int)tagUseSkillAttack.AttackID); if (mainTarget == null) { Debug.LogError("目标为空 mainTarget == null AttackID : " + tagUseSkillAttack.AttackID); OnSkillFinished(); return; } MoveToTarget(mainTarget.Camp, mainTarget.teamHero.positionNum, _onComplete: () => TurnBack(() => PlayCastAnimation(() => DoSkillLogic(() => { BackToOrigin(OnSkillFinished); })))); break; case SkillCastMode.Allies: MoveToTarget(caster.Camp, skillConfig.CastIndexNum, _onComplete: () => TurnBack(() => PlayCastAnimation(() => DoSkillLogic(() => { BackToOrigin(OnSkillFinished); })))); break; // case SkillCastMode.DashCast: // DashToTarget(() => BackToOrigin(OnSkillFinished)); // break; default: Debug.LogError("暂时不支持其他的方式释放 有需求请联系策划"); break; } } // 冲刺的技能 动作 跟移动 是同时进行的 移动到目标的一瞬间就要进行技能逻辑 // protected void DashToTarget(Action _onComplete) // { // TrackEntry entry = PlayCastAnimation(); // BattleObject mainTarget = battleField.battleObjMgr.GetBattleObject((int)tagUseSkillAttack.AttackID); // if (mainTarget == null) // { // Debug.LogError("目标为空 mainTarget == null AttackID : " + tagUseSkillAttack.AttackID); // _onComplete?.Invoke(); // return; // } // // 做一个微微的提前 // MoveToTarget(mainTarget.Camp, mainTarget.teamHero.positionNum, entry.AnimationEnd - 0.05f, () => DoSkillLogic(_onComplete)); // } // 这里其实是技能后摇结束的地方 protected virtual void DoSkillLogic(Action _onComplete = null) { } protected TrackEntry PlayCastAnimation(Action onComplete = null) { // 播放施法动作 return caster.motionBase.PlaySkillAnimation(skillConfig, onComplete, OnStartSkillFrame,//攻击前摇结束 OnActiveSkillFrame);//攻击中摇结束 } public void MoveToTarget(BattleCamp camp, int index, float duration = 0.2f, Action _onComplete = null) { // GetTargetNode(); targetNode = battleField.GetTeamNode(camp, index); Vector2 offset = new Vector2(skillConfig.CastDistance, 0); RectTransform selfRect = caster.heroGo.transform as RectTransform; 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.heroGo.transform as RectTransform; Vector2 targetAnchoredPos = Vector2.zero; var tween = selfRect.DOAnchorPos(targetAnchoredPos, 0.2f) .SetEase(Ease.Linear) .OnComplete(() => { // 转成正确方向 caster.heroGo.transform.localScale = Vector3.one; _onComplete?.Invoke(); }); battleField.battleTweenMgr.OnPlayTween(tween); } protected void HighLightAllTargets() { // 高亮所有目标 HashSet highlightList = new HashSet(battleField.battleObjMgr.GetBattleObjList(tagUseSkillAttack)); highlightList.Add(caster); // 把这些BO全高亮 或者说把除了这些的都放在遮罩后面 // YYL TODO } // 命中目标后的回调 正常是以各技能的方式来处理的 protected virtual void OnHitTargets(int _hitIndex, List hitList) { for (int i = 0; i < hitList.Count; i++) { H0604_tagUseSkillAttack.tagSkillHurtObj hurt = hitList[i]; BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID); if (target == null) { Debug.LogError("目标为空 target == null ObjId : " + hurt.ObjID); continue; } // 伤害结算 int[] damageDivide = skillConfig.DamageDivide[_hitIndex]; List damageList = new List(); long totalDamage = GeneralDefine.GetFactValue(hurt.HurtHP, hurt.HurtHPEx); for (int j = 0; j < damageDivide.Length; j++) { long damage = totalDamage * damageDivide[j] / 10000; damageList.Add(damage); } OnHitEachTarget(target, damageList, ref hurt); } } protected virtual void OnHitEachTarget(BattleObject target, List damageList, ref H0604_tagUseSkillAttack.tagSkillHurtObj hurt) { target.Hurt(damageList, hurt.AttackType); // 击中目标的时候,不管近战远程 都确认一下是否有爆炸特效 然后播放 if (skillConfig.ExplosionEffectId > 0) { // 播放爆炸特效 target.battleField.battleEffectMgr.PlayEffect( target.ObjID, skillConfig.ExplosionEffectId, target.heroGo.transform ); } } public virtual bool IsFinished() { return isFinished; } public virtual void ForceFinished() { isFinished = true; } public void OnSkillFinished() { isFinished = true; } }