using System; using BehaviorDesigner.Runtime.Tasks; using Gameplay; using Gameplay.AI; using Gameplay.BT.Variables; using Gameplay.Character; using Gameplay.Level; using Gameplay.Unit; using UnityEngine; using Action = BehaviorDesigner.Runtime.Tasks.Action; // 包抄移动 public class BTMoveAroundTo : Action { public SharedBattleInfo SharedBattleInfo; public EMoveDirection MoveDirection = EMoveDirection.Clockwise; private Character _owner; private Character _target; private Map _map; public enum EMoveDirection { Clockwise, AntiClockwise, } // target owner // | // | 1 // | 3 | // | 2 | // -------------------- // private enum EStage { None, Stage1, Stage2, MoveToTarget // 3 } private EStage _stage = EStage.None; private int _stageTargetCellIndex = -1; private int _targetCellIndex = -1; private Vector3 _baseDirection = Vector3.zero; public override void OnStart() { var level = LevelManager.Instance.CurrentLevel; _owner = GameUnitManager.instance.infightUnits.Search(SharedBattleInfo.Value.ownerId) as Character; _target = GameUnitManager.instance.infightUnits.Search(SharedBattleInfo.Value.theChosenOneId) as Character; _map = level?.Map; _stage = EStage.None; _stageTargetCellIndex = -1; _targetCellIndex = -1; if (_owner != null) { DebugUtil.Log("BT move to start, owner: {0}",_owner?.GetID()); } if (_map != null && _target != null && _owner != null) { var targetPosition = _map.TGSCellIndex2WorldPosition(_target.transData.cellIndex); var selfPosition = _map.TGSCellIndex2WorldPosition(_owner.transData.cellIndex); _baseDirection = targetPosition - selfPosition; } } public override TaskStatus OnUpdate() { if (_target == null) { return TaskStatus.Failure; } var attackDistance = _owner.fightData.attackDistance; var selfAsideDistance = attackDistance / 2; var targetAsideDistance = attackDistance; if (HasTargetMoved()) { RememberTarget(); switch (_stage) { case EStage.None: _stageTargetCellIndex = GetStage1TargetCell(selfAsideDistance); _stage = EStage.Stage1; _owner?.MoveTo(_stageTargetCellIndex, true); break; case EStage.Stage1: _stageTargetCellIndex = GetStage1TargetCell(selfAsideDistance); _owner?.MoveTo(_stageTargetCellIndex, true); break; case EStage.Stage2: _stageTargetCellIndex = GetStage2TargetCell(targetAsideDistance); _owner?.MoveTo(_stageTargetCellIndex, true); break; case EStage.MoveToTarget: break; default: throw new ArgumentOutOfRangeException(); } return TaskStatus.Running; } else if (HasStageArrived() && !AIUtils.IsNeedStop(_owner)) { switch (_stage) { case EStage.None: DebugUtil.LogError(" BTMoveAroundTo OnUpdate error, stage is none, owner: {0}",_owner?.GetID()); break; case EStage.Stage1: _stageTargetCellIndex = GetStage2TargetCell(targetAsideDistance); _stage = EStage.Stage2; _owner?.MoveTo(_stageTargetCellIndex, true); return TaskStatus.Running; case EStage.Stage2: _stage = EStage.MoveToTarget; _owner?.MoveTo(_target); return TaskStatus.Success; } } return TaskStatus.Running; } private int GetStage1TargetCell(int distance) { var targetPosition = _map.TGSCellIndex2WorldPosition(_target.transData.cellIndex); var supposedStartPosition = targetPosition - _baseDirection; Vector3 move; if (MoveDirection == EMoveDirection.Clockwise) { move = new Vector3(_baseDirection.z, 0, -_baseDirection.x); } else { move = new Vector3(-_baseDirection.z, 0, _baseDirection.x); } while (distance-- > 0) { var supposedMoveTo = supposedStartPosition + move.normalized * distance; if (_map.WorldPosition2TGSCellIndex(supposedMoveTo, out var cellIndex) && PathFinder.CanPass(cellIndex, _owner)) { return cellIndex; } } return _owner.transData.cellIndex; } private int GetStage2TargetCell(int distance) { var targetPosition = _map.TGSCellIndex2WorldPosition(_target.transData.cellIndex); Vector3 move; if (MoveDirection == EMoveDirection.Clockwise) { move = new Vector3(_baseDirection.z, 0, -_baseDirection.x); } else { move = new Vector3(-_baseDirection.z, 0, _baseDirection.x); } while (distance-- > 0) { var supposedMoveTo = targetPosition + move.normalized * distance; if (_map.WorldPosition2TGSCellIndex(supposedMoveTo, out var cellIndex) && PathFinder.CanPass(cellIndex, _owner)) { return cellIndex; } } return _target.transData.cellIndex; } private bool HasTargetMoved() { return _targetCellIndex != _target.transData.cellIndex; } private void RememberTarget() { _targetCellIndex = _target.transData.cellIndex; } private bool HasStageArrived() { return _stageTargetCellIndex == _owner?.transData.cellIndex; } }