using System; using Gameplay; using Framework; using Gameplay.AI; using UnityEngine; using Gameplay.Unit; using Gameplay.Level; using Gameplay.BT.Variables; using BehaviorDesigner.Runtime.Tasks; using Action = BehaviorDesigner.Runtime.Tasks.Action; public class BTMoveAroundTo : Action { public SharedBattleInfo SharedBattleInfo; private GameUnit _owner; private GameUnit _target; private Map _map; private EStage _stage = EStage.None; private int _stageTargetCellIndex = -1; private int _targetCellIndex = -1; private int _targetAttackDistance; private PosDirection posDirection; private Vector2Int targetV2; private Vector2Int ownerV2; private uint _lastTarget; private enum PosDirection { Left, Right, } private enum EStage { None, Stage1, Stage2, MoveToTarget } public override void OnStart() { var level = LevelManager.Instance.CurrentLevel; _map = level?.Map; UpdateEnemyData(); posDirection = targetV2.y > ownerV2.y ? PosDirection.Left : PosDirection.Right; } private void UpdateEnemyData() { _owner = GameUnitManager.instance.infightUnits.Search(SharedBattleInfo.Value.ownerId); _target = GameUnitManager.instance.infightUnits.Search(SharedBattleInfo.Value.theChosenOneId); _targetAttackDistance = _target.fightData.attackDistance; _stage = EStage.None; _stageTargetCellIndex = -1; _targetCellIndex = -1; if (_map != null && _target != null && _owner != null) { targetV2 = _map.TGSCellIndex2BlockPosition(_target.transData.cellIndex); ownerV2 = _map.TGSCellIndex2BlockPosition(_owner.transData.cellIndex); } } public override TaskStatus OnUpdate() { if (SharedBattleInfo.Value.theChosenOneId != Constants.INVALID_UINT_ID) { if (_owner?.controlData.targetEnemy == null && _stage == EStage.MoveToTarget) { var enemy = GameUnitManager.instance.infightUnits.Search(SharedBattleInfo.Value.theChosenOneId); if (enemy != null && !enemy.statusData.isDead) { _target = enemy; _targetCellIndex = enemy.transData.cellIndex; _stage = EStage.None; } else { SharedBattleInfo.Value.theChosenOneId = Constants.INVALID_UINT_ID; } } if (HasTargetMoved()) { RememberTarget(); switch (_stage) { case EStage.None: _stageTargetCellIndex = GetStage1TargetCell(); _stage = EStage.Stage1; AIUtils.CheckAndMove(_owner, _stageTargetCellIndex); break; case EStage.Stage1: _stageTargetCellIndex = GetStage1TargetCell(); AIUtils.CheckAndMove(_owner, _stageTargetCellIndex); break; case EStage.Stage2: _stageTargetCellIndex = GetStage2TargetCell(); AIUtils.CheckAndMove(_owner, _stageTargetCellIndex); break; case EStage.MoveToTarget: break; default: throw new ArgumentOutOfRangeException(); } return TaskStatus.Running; } if (HasStageArrived() && !AIUtils.IsNeedStop(_owner)) { switch (_stage) { case EStage.Stage1: _stageTargetCellIndex = GetStage2TargetCell(); _stage = EStage.Stage2; AIUtils.CheckAndMove(_owner, _stageTargetCellIndex); break; case EStage.Stage2: _stageTargetCellIndex = _target.transData.cellIndex; _stage = EStage.MoveToTarget; AIUtils.CheckAndMove(_owner, _stageTargetCellIndex, false); break; } } return TaskStatus.Running; } return TaskStatus.Failure; } private int GetStage1TargetCell() { // 竖轴移动 默认逆时针 var curDistance = MapUtils.Distance(_map, targetV2, ownerV2); var targetCellIndex = _owner.transData.cellIndex; // 在攻击范围内 先移出攻击范围 if (curDistance <= _targetAttackDistance) { // 方位在右边 // 顺时针 +x 逆时针-x if (posDirection == PosDirection.Right) //(ownerV2.y >= targetV2.y) { var targetX = targetV2.x + _targetAttackDistance + 1; while (targetX >= _map.MapData.Height) { targetX--; } var newPos = new Vector2Int(targetX, ownerV2.y); var newIndex = _map.BlockPosition2TGSCellIndex(newPos); targetCellIndex = AIUtils.CheckAndGetCanPassOneCycleCellIndex(_map, _owner, newIndex); } // 方位在左边 else { var targetX = targetV2.x - _targetAttackDistance - 1; while (targetX < 0) { targetX++; } var newPos = new Vector2Int(targetX, ownerV2.y); var newIndex = _map.BlockPosition2TGSCellIndex(newPos); targetCellIndex = AIUtils.CheckAndGetCanPassOneCycleCellIndex(_map, _owner, newIndex); } } // DebugUtil.LogError("阶段一找到的位置是:{0}", targetCellIndex); return targetCellIndex; } // TODO 多余走了好几步 能攻击就停下 private int GetStage2TargetCell() { // 横轴移动 改变y值 targetV2 = _map.TGSCellIndex2BlockPosition(_target.transData.cellIndex); ownerV2 = _map.TGSCellIndex2BlockPosition(_owner.transData.cellIndex); var targetY = ownerV2.y; if (posDirection == PosDirection.Right) { while (targetV2.y - 1 <= targetY) { targetY--; } } else { while (targetV2.y + 1 >= targetY) { targetY++; } } var newPos = new Vector2Int(ownerV2.x, targetY); var newIndex = _map.BlockPosition2TGSCellIndex(newPos); var targetCellIndex = AIUtils.CheckAndGetCanPassOneCycleCellIndex(_map, _owner, newIndex); // DebugUtil.LogError("阶段二找到的位置是:{0}", targetCellIndex); return targetCellIndex; } private bool HasTargetMoved() { return _targetCellIndex != _target.transData.cellIndex; } private void RememberTarget() { _targetCellIndex = _target.transData.cellIndex; } private bool HasStageArrived() { return _stageTargetCellIndex == _owner?.transData.cellIndex; } }