1 line
7.2 KiB
C#
1 line
7.2 KiB
C#
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;
|
|
}
|
|
} |