NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Gameplay/AI/Task/BTMoveAround.cs

296 lines
9.0 KiB
C#
Raw Normal View History

2024-12-19 16:37:23 +08:00
using System;
using Gameplay;
using Framework;
using Gameplay.AI;
using UnityEngine;
using Gameplay.Unit;
using Gameplay.Level;
using Gameplay.BT.Variables;
2024-12-20 19:56:53 +08:00
using Cysharp.Threading.Tasks;
2024-12-25 14:51:58 +08:00
using System.Collections.Generic;
2024-12-19 16:37:23 +08:00
using BehaviorDesigner.Runtime.Tasks;
using Action = BehaviorDesigner.Runtime.Tasks.Action;
2024-12-20 14:52:23 +08:00
public class BTMoveAround : Action
2024-12-19 16:37:23 +08:00
{
public SharedBattleInfo SharedBattleInfo;
2024-12-20 19:56:53 +08:00
private GameUnit _owner;
private GameUnit _target;
2024-12-19 16:37:23 +08:00
private Map map;
private EStage _stage = EStage.None;
private int _stageTargetCellIndex = -1;
private int _targetCellIndex = -1;
private int attackDistance;
private Vector2Int targetV2;
private Vector2Int ownerV2;
2024-12-20 19:56:53 +08:00
private bool needCheck;
2024-12-26 19:39:22 +08:00
// 格子,原来的通行等级
private Dictionary<int, int> crossLevelCells = new Dictionary<int, int>();
2024-12-20 14:52:23 +08:00
2024-12-27 14:57:24 +08:00
private bool _isRegistered;
2024-12-19 16:37:23 +08:00
private enum EStage
{
None,
Stage1,
Stage2,
}
public override void OnStart()
{
2024-12-27 14:57:24 +08:00
if (!_isRegistered)
{
EventManager.Instance.Register(EventManager.EventName.INFIGHT_CHARACTER_AI_FINDPATH, ResetCells);
_isRegistered = true;
}
2024-12-20 19:56:53 +08:00
_owner = GameUnitManager.instance.infightUnits.Search(SharedBattleInfo.Value.ownerId);
_target = GameUnitManager.instance.infightUnits.Search(SharedBattleInfo.Value.theChosenOneId);
2024-12-19 16:37:23 +08:00
map = LevelManager.Instance.CurrentLevel.Map;
_stageTargetCellIndex = -1;
_targetCellIndex = -1;
}
public override TaskStatus OnUpdate()
{
2024-12-20 19:56:53 +08:00
if (_owner == null) return TaskStatus.Failure;
// 避开其他AI
AvoidOtherUnit();
2024-12-19 16:37:23 +08:00
if (SharedBattleInfo.Value.theChosenOneId != Constants.INVALID_UINT_ID)
{
2024-12-20 19:56:53 +08:00
if (_owner?.controlData.targetEnemy == null && _stage == EStage.Stage2)
2024-12-19 16:37:23 +08:00
{
2024-12-20 14:52:23 +08:00
// 继续追击目标
2024-12-19 16:37:23 +08:00
var enemy = GameUnitManager.instance.infightUnits.Search(SharedBattleInfo.Value.theChosenOneId);
if (enemy != null && !enemy.statusData.isDead)
{
2024-12-20 14:52:23 +08:00
if (_targetCellIndex != enemy.transData.cellIndex)
{
2024-12-20 19:56:53 +08:00
_target = enemy;
2024-12-20 14:52:23 +08:00
_targetCellIndex = -1;
}
2024-12-19 16:37:23 +08:00
}
else
{
2025-01-07 13:09:22 +08:00
ResetCells();
2024-12-19 16:37:23 +08:00
SharedBattleInfo.Value.theChosenOneId = Constants.INVALID_UINT_ID;
2024-12-20 14:52:23 +08:00
return TaskStatus.Failure;
2024-12-19 16:37:23 +08:00
}
}
if (HasTargetMoved())
{
RememberTarget();
switch (_stage)
{
case EStage.None:
_stageTargetCellIndex = GetStageTargetCell();
_stage = EStage.Stage1;
2024-12-20 19:56:53 +08:00
AIUtils.CheckAndMove(_owner, _stageTargetCellIndex);
2024-12-19 16:37:23 +08:00
break;
case EStage.Stage1:
_stageTargetCellIndex = GetStageTargetCell();
2024-12-20 19:56:53 +08:00
AIUtils.CheckAndMove(_owner, _stageTargetCellIndex);
2024-12-19 16:37:23 +08:00
break;
case EStage.Stage2:
2024-12-20 19:56:53 +08:00
_stageTargetCellIndex = _target.transData.cellIndex;
AIUtils.CheckAndMove(_owner, _target.transData.cellIndex);
2024-12-19 16:37:23 +08:00
break;
default:
throw new ArgumentOutOfRangeException();
}
return TaskStatus.Running;
}
2024-12-20 19:56:53 +08:00
if (HasStageArrived() && !AIUtils.IsNeedStop(_owner))
2024-12-19 16:37:23 +08:00
{
switch (_stage)
{
case EStage.Stage1:
_stage = EStage.Stage2;
2024-12-20 19:56:53 +08:00
_stageTargetCellIndex = _target.transData.cellIndex;
AIUtils.CheckAndMove(_owner, _target.transData.cellIndex);
2024-12-19 16:37:23 +08:00
break;
}
}
return TaskStatus.Running;
}
return TaskStatus.Failure;
}
private int GetStageTargetCell()
{
2024-12-20 19:56:53 +08:00
attackDistance = _target.fightData.attackDistance / 2;
targetV2 = map.TGSCellIndex2BlockPosition(_target.transData.cellIndex);
ownerV2 = map.TGSCellIndex2BlockPosition(_owner.transData.cellIndex);
2024-12-19 16:37:23 +08:00
var correctPos = targetV2;
if (targetV2.y > ownerV2.y && targetV2.x > ownerV2.x) //左下
{
var x = targetV2.x + attackDistance;
var y = targetV2.y + attackDistance + 1;
while (x >= map.MapData.Height)
{
x--;
}
while (y >= map.MapData.Width)
{
y--;
}
correctPos = new Vector2Int(x, y);
// DebugUtil.Log("在目标的左下方,获取到的正确位置是:{0}", correctPos);
}
if (targetV2.y > ownerV2.y && targetV2.x < ownerV2.x) //左上
{
var x1 = targetV2.x - attackDistance;
var y1 = targetV2.y + attackDistance + 1;
while (x1 < 0)
{
x1++;
}
while (y1 >= map.MapData.Width)
{
y1--;
}
correctPos = new Vector2Int(x1, y1);
// DebugUtil.LogError("在目标的左上方,获取到的正确位置是:{0}", correctPos);
}
if (targetV2.y < ownerV2.y && targetV2.x > ownerV2.x) //右下
{
var x = targetV2.x + attackDistance;
var y = targetV2.y - attackDistance + 1;
while (x >= map.MapData.Height)
{
x--;
}
while (y < 0)
{
y++;
}
correctPos = new Vector2Int(x, y);
// DebugUtil.LogError("在目标的右下方,获取到的正确位置是:{0}", correctPos);
}
if (targetV2.y < ownerV2.y && targetV2.x < ownerV2.x) //右上
{
var x1 = targetV2.x - attackDistance;
var y2 = targetV2.y - attackDistance + 1;
while (x1 < 0)
{
x1++;
}
while (y2 < 0)
{
y2++;
}
correctPos = new Vector2Int(x1, y2);
// DebugUtil.LogError("在目标的右上方,获取到的正确位置是:{0}", correctPos);
}
2024-12-20 14:52:23 +08:00
var targetCellIndex = map.BlockPosition2TGSCellIndex(correctPos);
2024-12-20 19:56:53 +08:00
if (!AIUtils.CheckPathExits(_owner, targetCellIndex))
2024-12-20 14:52:23 +08:00
{
2024-12-20 19:56:53 +08:00
targetCellIndex = AIUtils.GetCanReachCellAround(map, _owner, targetCellIndex);
2024-12-20 14:52:23 +08:00
if (targetCellIndex == -1)
2024-12-20 19:56:53 +08:00
targetCellIndex = _owner.transData.cellIndex;
2024-12-20 14:52:23 +08:00
}
2024-12-19 16:37:23 +08:00
return targetCellIndex;
}
private bool HasTargetMoved()
{
2024-12-20 19:56:53 +08:00
return _targetCellIndex != _target.transData.cellIndex;
2024-12-19 16:37:23 +08:00
}
private void RememberTarget()
{
2024-12-20 19:56:53 +08:00
_targetCellIndex = _target.transData.cellIndex;
2024-12-25 14:51:58 +08:00
if (_stage == EStage.Stage2) return;
2025-01-07 13:09:22 +08:00
// 目标未移动
if (_owner.controlData.targetEnemy != null && _owner.controlData.targetEnemy.GetID() == _target.GetID()) return;
2024-12-25 14:51:58 +08:00
// 将敌人周围一圈的通行级别设高
var cells = AIUtils.SetCellCrossLevel(map, _owner, _targetCellIndex);
2024-12-26 19:39:22 +08:00
foreach (var cell in cells)
2024-12-25 14:51:58 +08:00
{
2024-12-26 19:39:22 +08:00
crossLevelCells[cell.Key] = cell.Value;
2024-12-25 14:51:58 +08:00
}
2024-12-19 16:37:23 +08:00
}
private bool HasStageArrived()
{
2024-12-20 19:56:53 +08:00
return _stageTargetCellIndex == _owner?.transData.cellIndex;
}
2024-12-27 14:57:24 +08:00
private void ResetCells()
{
// 还原通行级别
AIUtils.SetCellCrossLevel(map, crossLevelCells);
crossLevelCells.Clear();
}
2024-12-20 19:56:53 +08:00
private async void AvoidOtherUnit()
{
if (AIUtils.IsNeedStop(_owner)) return;
if (_owner.statusData.isMoveing && !needCheck)
{
needCheck = true;
}
if (needCheck && !_owner.statusData.isMoveing &&
_owner.controlData.targetCellIndex == -1)
{
needCheck = false;
2025-01-07 13:09:22 +08:00
ResetCells();
2024-12-25 14:51:58 +08:00
2024-12-20 19:56:53 +08:00
// 随机等待 防止同步
var randomDelay = UnityEngine.Random.Range(0f, 1f);
await UniTask.Delay((int)(randomDelay * 1000));
AIUtils.CheckAreaIsOtherEnemyUnit(_owner, SharedBattleInfo.Value.theChosenOneId);
}
2024-12-19 16:37:23 +08:00
}
2024-12-27 14:57:24 +08:00
public override void OnEnd()
{
if (!_isRegistered) return;
EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_CHARACTER_AI_FINDPATH, ResetCells);
_isRegistered = false;
}
public override void OnBehaviorComplete()
{
if (!_isRegistered) return;
EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_CHARACTER_AI_FINDPATH, ResetCells);
_isRegistered = false;
}
2024-12-19 16:37:23 +08:00
}