| | |
| | | |
| | | } |
| | | |
| | | // 技能运行主逻辑:处理技能效果和其他技能动作 |
| | | // 技能运行主逻辑:仅驱动技能效果(skillEffect),子技能和死亡由IsFinished()推进 |
| | | public virtual void Run() |
| | | { |
| | | if (skillEffect != null) |
| | |
| | | } |
| | | return; |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | | protected void ShadowIllutionCreate(bool create) |
| | |
| | | return; |
| | | } |
| | | |
| | | int mainTargetPosNum = BattleUtility.GetMainTargetPositionNum(this, caster, tagUseSkillAttack.HurtList.ToList(), skillConfig); |
| | | int mainTargetPosNum = BattleUtility.GetMainTargetPositionNum(this, caster, tagUseSkillAttack.HurtList, skillConfig); |
| | | BattleCamp battleCamp = skillConfig.TagFriendly != 0 ? caster.Camp : caster.GetEnemyCamp(); |
| | | RectTransform targetTrans = battleField.GetTeamNode(battleCamp, mainTargetPosNum); |
| | | |
| | |
| | | protected virtual void OnAllAttackMoveFinished() |
| | | { |
| | | moveFinished = true; |
| | | List<BattleObject> allList = battleField.battleObjMgr.allBattleObjDict.Values.ToList<BattleObject>(); |
| | | foreach (BattleObject bo in allList) |
| | | foreach (var kv in battleField.battleObjMgr.allBattleObjDict) |
| | | { |
| | | BattleObject bo = kv.Value; |
| | | bo.layerMgr.SetFront(); |
| | | bo.GetHeroInfoBar()?.SetActive(true); |
| | | } |
| | |
| | | // 确保施法者也被高亮(原逻辑) |
| | | var highlightList = new List<BattleObject>(targetSet) { caster }; |
| | | |
| | | var allList = battleField.battleObjMgr.allBattleObjDict.Values.ToList(); |
| | | var allList = battleField.battleObjMgr.allBattleObjDict.Values; |
| | | |
| | | // 构造集合便于判断 |
| | | var targetSetLookup = new HashSet<BattleObject>(targetSet); |
| | |
| | | // 获取并分配掉落物品和经验 |
| | | var dropPack = PackManager.Instance.GetSinglePack(PackType.DropItem); |
| | | var itemDict = dropPack.GetAllItems(); |
| | | List<ItemModel> itemList = new List<ItemModel>(itemDict.Values.Where(item => item != null && item.isAuction)); |
| | | List<ItemModel> itemList = new List<ItemModel>(); |
| | | foreach (var item in itemDict.Values) |
| | | { |
| | | if (item != null && item.isAuction) |
| | | itemList.Add(item); |
| | | } |
| | | |
| | | var dropAssign = AssignDrops(itemList, deadPackList.Count); |
| | | var expAssign = AssignExp(expPackList, deadPackList.Count); |
| | |
| | | continue; |
| | | } |
| | | |
| | | List<int> itemIndexList = dropAssign[i].Select(item => item.gridIndex).ToList(); |
| | | List<int> itemIndexList = new List<int>(dropAssign[i].Count); |
| | | for (int j = 0; j < dropAssign[i].Count; j++) |
| | | itemIndexList.Add(dropAssign[i][j].gridIndex); |
| | | |
| | | BattleDrops battleDrops = new BattleDrops() |
| | | { |
| | |
| | | return false; |
| | | } |
| | | |
| | | // 检查技能是否完成:综合检查所有完成条件 |
| | | // 检查技能是否完成:同时推进状态(清理完成的子技能、处理剩余包、触发死亡判定) |
| | | // 注意:此方法有副作用,这是设计使然——由SkillRecordAction.Run()每帧调用来驱动状态推进 |
| | | public virtual bool IsFinished() |
| | | { |
| | | if (!isPlay) return false; |
| | |
| | | tempRetValue = false; |
| | | } |
| | | |
| | | // 检查其他技能动作是否完成 |
| | | // 检查跟进的技能动作是否完成(追击/连击/反击等) |
| | | if (currentWaitingSkill.Count > 0) |
| | | { |
| | | if (currentWaitingSkill.Any(s => s.IsFinished())) |
| | |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // 检查最终完成状态 |
| | | if (isFinished && moveFinished) |
| | | { |
| | |
| | | return false; |
| | | } |
| | | |
| | | // 如果自己内部的recora action的 inner record player还有没执行完的包 也是返回false |
| | | // 如果自己内部的 innerRecordPlayer 还有没执行完的包 也是返回false |
| | | if (ownRecordAction != null && ownRecordAction.GetInnerRecordPlayer().IsPlaying()) |
| | | { |
| | | return false; |
| | |
| | | { |
| | | battleField.RemoveCastingSkill(caster.ObjID, this); |
| | | |
| | | // 传递parentRecordAction,让死亡技能等待当前技能完成 |
| | | DeathRecordAction recordAction = battleField.OnObjsDead(new List<BattleDeadPack>(tempDeadPackList.Values), null, ownRecordAction); |
| | | if (null != recordAction) |
| | | { |
| | |
| | | |
| | | // 取消幻影效果 |
| | | caster.ShowIllusionShadow(false); |
| | | |
| | | // 重置MotionBase的技能动画状态,防止playingSkillWithAnim卡住后续技能 |
| | | if (caster is HeroBattleObject heroCaster) |
| | | { |
| | | heroCaster.ForceResetMotionSkillState(); |
| | | } |
| | | } |
| | | |
| | | // 5. 恢复 UI 状态 |
| | |
| | | skillRecordAction.fromSkill = this; |
| | | currentWaitingSkill.Add(skillRecordAction); |
| | | |
| | | // 需要给真正parent播的 |
| | | // 根据后续技能的属性决定是否需要等待当前技能归位 |
| | | RecordAction waitAction = GetFollowUpWaitAction(skillRecordAction); |
| | | |
| | | if (skillRecordAction.useParentRecordPlayer && skillRecordAction.parentSkillAction != null) |
| | | { |
| | | skillRecordAction.parentSkillAction.GetInnerRecordPlayer().PlayRecord(skillRecordAction); |
| | | if (waitAction != null) |
| | | skillRecordAction.parentSkillAction.GetInnerRecordPlayer().PlayRecord(skillRecordAction, waitAction); |
| | | else |
| | | skillRecordAction.parentSkillAction.GetInnerRecordPlayer().PlayRecord(skillRecordAction); |
| | | } |
| | | else |
| | | { |
| | | ownRecordAction.GetInnerRecordPlayer().PlayRecord(skillRecordAction); |
| | | if (waitAction != null) |
| | | ownRecordAction.GetInnerRecordPlayer().PlayRecord(skillRecordAction, waitAction); |
| | | else |
| | | ownRecordAction.GetInnerRecordPlayer().PlayRecord(skillRecordAction); |
| | | } |
| | | |
| | | return false; |
| | |
| | | return true; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 判定后续技能(追击/连击/反击等)是否需要等待当前技能完成动作后再释放 |
| | | /// 综合判别:技能是否有动画、释放模式是否需要位移、是否同一施法者 |
| | | /// 仅在确认安全时返回waitAction,避免不必要的等待和潜在的跨角色相互等待 |
| | | /// </summary> |
| | | private RecordAction GetFollowUpWaitAction(SkillRecordAction followUp) |
| | | { |
| | | // 当前技能已经归位,无需等待 |
| | | if (moveFinished) return null; |
| | | |
| | | if (followUp.skillBase == null) return null; |
| | | |
| | | // 后续技能没有动画动作(无SkillMotionName),不涉及位移,无需等待归位 |
| | | // 这类技能在CanCastSkill中也不受playingSkillWithAnim限制 |
| | | var followUpSkin = followUp.skillBase.skillSkinConfig; |
| | | if (followUpSkin == null || string.IsNullOrEmpty(followUpSkin.SkillMotionName)) |
| | | return null; |
| | | |
| | | // 后续技能原地释放(None/Self),虽有动画但不需要位移到目标,无需等待 |
| | | if (followUpSkin.castMode == SkillCastMode.None || followUpSkin.castMode == SkillCastMode.Self) |
| | | return null; |
| | | |
| | | // 同一施法者的后续技能(连击等):必须等待归位 |
| | | // 原因:同一角色的CastToEnemy/CastToTarget会MoveToTarget, |
| | | // 如果上一个技能的DOTween归位还没完成就发起新位移,两个DOTween会冲突 |
| | | if (followUp.skillBase.caster == caster) |
| | | return ownRecordAction; |
| | | |
| | | // 不同施法者的后续技能(追击/反击等):不添加等待 |
| | | // 原因:不同角色从各自位置出发,不存在DOTween冲突 |
| | | // 注意:此处不添加跨角色等待关系,避免技能链A等B、B等A的相互等待风险 |
| | | return null; |
| | | } |
| | | |
| | | // 添加清理方法:防止内存泄漏 |
| | | public virtual void Cleanup() |
| | | { |