NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Gameplay/Unit/AI/UnitAIManager.cs

334 lines
11 KiB
C#

using System.Collections.Generic;
using cfg.AICfg;
using cfg.SkillCfg;
using Framework;
using Gameplay.Area;
using Gameplay.Character;
using Gameplay.Level;
using Gameplay.Skill;
using UnityEngine;
namespace Gameplay.Unit.AI
{
public class UnitAIManager
{
public GameUnit owner;
public DataAISkillControll rawConfig;
private SkillHandle _skillHandle;
private float _remainCheckTime;
private int _checkDistance;
private bool _requireSort;
private int _prelockCellIndex;
private List<GameUnit> _preSelectUnits;
public UnitAIManager(GameUnit owner)
{
this.owner = owner;
_preSelectUnits = new List<GameUnit>();
}
public void Init()
{
_Init();
}
private void _LoadRawConfig()
{
var skillUnitManager = SkillManager.instance.GetUnitSkillManager(owner);
if (skillUnitManager == null)
{
return;
}
var pSkill = skillUnitManager.positiveSkill;
if (pSkill == null)
{
return;
}
var skillConfig = pSkill.runtimeData.configData;
if (skillConfig == null)
{
return;
}
var aiControlId = skillConfig.AIControllId;
if (aiControlId == 0)
{
return;
}
rawConfig = TableManager.Instance.Tables.AISkillControlCfg.Get(aiControlId);
_skillHandle = pSkill;
}
private void _Init()
{
_LoadRawConfig();
if (rawConfig == null)
{
return;
}
_InitRuntimeData();
}
private void _InitRuntimeData()
{
_checkDistance = rawConfig.CheckDistance;
if (_checkDistance == -1)
{
_checkDistance = _skillHandle.runtimeData.configData.ReleaseArea;
}
_requireSort = rawConfig.HpCheck != HPCheckType.None;
}
public void LogicUpdate(float dt)
{
if (rawConfig == null)
{
return;
}
// 全局跳帧
if (SkillManager.instance.inSkillingUnitAI != null)
{
return;
}
if (_skillHandle.runtimeData.remainCDTime > 0) return;
// 逃跑过程中不释放技能
if (_skillHandle.owner.statusData.isRetreat) return;
// 死亡不释放技能
if (_skillHandle.owner.statusData.isDead) return;
// 检测是否在战斗中
var inFight = (LevelManager.Instance.CurrentLevel.LevelTime - owner.commonData.lastInFightSeconds) > 3;
if (rawConfig.OnlyReleaseInAttack && inFight) return;
_remainCheckTime -= dt;
if (_remainCheckTime > 0)
{
return;
}
_remainCheckTime = rawConfig.CheckTime;
var canRelease = _CheckLogic();
if (canRelease)
{
if (owner.commonData.troopId != ETroopsId.Self)
{
// 非己方单位,需要记录到AI释放列表中,防止多个AI一起释放技能
SkillManager.instance.inSkillingUnitAI = owner;
}
_UseSkill();
}
}
private void _UseSkill()
{
switch (rawConfig.AIReleasePos)
{
case EAIReleasePosType.Self:
// 对自己释放
_skillHandle.Use(owner.transData.cellIndex);
break;
case EAIReleasePosType.TargetCell:
// 对目标释放
_skillHandle.Use(_prelockCellIndex);
break;
case EAIReleasePosType.AroundTargetCellEmpty:
// 对目标周围空位释放
_ReleaseToAroundEmpty();
break;
default:
DebugUtil.LogError("暂未实现的AI释放位置类型:{0}", rawConfig.AIReleasePos);
break;
}
}
private void _ReleaseToAroundEmpty()
{
var aroundCellIndexs = AreaManager.instance.GetCellIndexsAround(_prelockCellIndex, 1);
for (int i = 0; i < aroundCellIndexs.Count; i++)
{
var cellIndex = aroundCellIndexs[i];
if (AreaManager.instance.IsCellEmpty(cellIndex))
{
_skillHandle.Use(cellIndex);
return;
}
}
DebugUtil.LogError("周围没有空位:" + _prelockCellIndex);
}
private bool _CheckLogic()
{
var checkTargetType = rawConfig.CheckTargetType;
switch (checkTargetType)
{
case ETargetType.AnyCell:
// 默认锁定自己
_prelockCellIndex = owner.transData.cellIndex;
return true;
case ETargetType.SelfSide:
return _CheckSelfSide();
case ETargetType.EnemySide:
return _CheckEnemySide();
}
DebugUtil.LogError("暂未实现的AI逻辑检测类型:{0}", checkTargetType);
return false;
}
private bool _CheckEnemySide()
{
_preSelectUnits.Clear();
var enemyTroopId = owner.commonData.troopId == ETroopsId.Self ? ETroopsId.Enemy1 : ETroopsId.Self;
var allEnemySideUnits = GameUnitManager.instance.infightUnits.GetListByTroop(enemyTroopId);
for (int i = 0; i < allEnemySideUnits.Count; i++)
{
var unit = allEnemySideUnits[i];
if (unit == owner) continue;
if (rawConfig.RequireTargetAlive && unit.statusData.isDead) continue;
var distance = AreaManager.instance.GetDistance(unit.transData.cellIndex, owner.transData.cellIndex);
if (distance < _checkDistance)
{
// 满足需求
if (_requireSort)
{
_preSelectUnits.Add(unit);
}
else
{
// 直接使用这个
_prelockCellIndex = unit.transData.cellIndex;
return true;
}
}
}
// 第二次筛选
if (_preSelectUnits.Count > 0)
{
return _ReSelectUnits();
}
return false;
}
private bool _CheckSelfSide()
{
_preSelectUnits.Clear();
var selfTroopId = owner.commonData.troopId;
var allSelfSideUnits = GameUnitManager.instance.infightUnits.GetListByTroop(selfTroopId);
for (int i = 0; i < allSelfSideUnits.Count; i++)
{
var unit = allSelfSideUnits[i];
if (unit == owner) continue;
if (rawConfig.RequireTargetAlive && unit.statusData.isDead) continue;
var distance = AreaManager.instance.GetDistance(unit.transData.cellIndex, owner.transData.cellIndex);
if (distance < _checkDistance)
{
// 满足需求
if (_requireSort)
{
_preSelectUnits.Add(unit);
}
else
{
// 直接使用这个
_prelockCellIndex = unit.transData.cellIndex;
return true;
}
}
}
// 第二次筛选
if (_preSelectUnits.Count > 0)
{
return _ReSelectUnits();
}
return false;
}
private bool _ReSelectUnits()
{
switch (rawConfig.HpCheck)
{
case HPCheckType.HpPercentMax:
_SelectHPPercentMax();
break;
case HPCheckType.HpPercentMin:
_SelectHPPercentMin();
break;
case HPCheckType.HpPercentLowerThan:
return _SelectMatchLowerThan();
default:
DebugUtil.LogError("暂未实现的AI血量检测类型:{0}", rawConfig.HpCheck);
return false;
}
return true;
}
private bool _SelectMatchLowerThan()
{
var lowerThan = _TryGetFloatParam(0);
for (int i = 0; i < _preSelectUnits.Count; i++)
{
var unit = _preSelectUnits[i];
var percent = unit.aliveData.currentHp / (unit.aliveData.maxHp * 1f);
if (percent < lowerThan)
{
_prelockCellIndex = unit.transData.cellIndex;
return true;
}
}
return false;
}
private void _SelectHPPercentMin()
{
var minUnit = _preSelectUnits[0];
var minPercent = minUnit.aliveData.currentHp / (minUnit.aliveData.maxHp * 1f);
for (int i = 1; i < _preSelectUnits.Count; i++)
{
var unit = _preSelectUnits[i];
var percent = unit.aliveData.currentHp / (unit.aliveData.maxHp * 1f);
if (percent < minPercent)
{
minPercent = percent;
minUnit = unit;
}
}
_prelockCellIndex = minUnit.transData.cellIndex;
}
private void _SelectHPPercentMax()
{
var maxUnit = _preSelectUnits[0];
var maxPercent = maxUnit.aliveData.currentHp / (maxUnit.aliveData.maxHp * 1f);
for (int i = 1; i < _preSelectUnits.Count; i++)
{
var unit = _preSelectUnits[i];
var percent = unit.aliveData.currentHp / (unit.aliveData.maxHp * 1f);
if (percent > maxPercent)
{
maxPercent = percent;
maxUnit = unit;
}
}
_prelockCellIndex = maxUnit.transData.cellIndex;
}
private float _TryGetFloatParam(int index)
{
if (rawConfig.FloatParams.Count <= index)
{
DebugUtil.LogError("AI参数不足: " + rawConfig.Id + " " + index);
return 0;
}
return rawConfig.FloatParams[index];
}
private int _TryGetIntParam(int index)
{
var floatVal = _TryGetFloatParam(index);
return Mathf.RoundToInt(floatVal);
}
}
}