TH1/Unity/Assets/Scripts/TH1_Logic/AI/AIActionGenerator.cs
2026-05-06 01:59:03 +08:00

738 lines
34 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* @Author: 白哉
* @Description: AI Action 生成器
* @Date: 2025年04月30日 星期三 11:04:38
* @Modify:
*/
using System.Collections.Generic;
using Logic.Action;
using Logic.CrashSight;
using Logic.Pool;
using RuntimeData;
using TH1_Logic.Action;
using TH1_Logic.Core;
using UnityEngine;
namespace Logic.AI
{
public class AIActionGenerator
{
private MapData _mapData;
private PlayerData _player;
private List<UnitData> _waitUnits;
private List<GridData> _waitGrids;
private List<CityData> _waitCity;
private uint _actionRecord;
private uint _recordCount;
public AIActionType ActionType => (AIActionType)(_actionRecord % (int)AIActionType.Max);
private HashSet<uint> _territoryGridSet;
private List<UnitData> _tmpUnitList;
private List<CityData> _tmpCityList;
public void Init(MapData map, PlayerData player)
{
_mapData = map;
_player = player;
_waitUnits ??= new List<UnitData>();
_waitGrids ??= new List<GridData>();
_waitCity ??= new List<CityData>();
_waitUnits.Clear();
_waitGrids.Clear();
_waitCity.Clear();
_territoryGridSet ??= new HashSet<uint>();
_territoryGridSet.Clear();
map.GetPlayerTerritoryGridIdSet(player.Id, _territoryGridSet);
_tmpUnitList ??= new List<UnitData>();
_tmpUnitList.Clear();
map.GetUnitDataListByPlayerId(player.Id, _tmpUnitList);
_tmpCityList ??= new List<CityData>();
_tmpCityList.Clear();
map.GetCityDataListByPlayerId(player.Id, _tmpCityList);
foreach (var unit in _tmpUnitList) _waitUnits.Add(unit);
foreach (var city in _tmpCityList) _waitCity.Add(city);
foreach (var grid in _mapData.GridMap.GridList)
if(_territoryGridSet.Contains(grid.Id)) _waitGrids.Add(grid);
_actionRecord = 0;
_recordCount = 0;
}
public void GeneratorOneStepActions(MapData map, PlayerData player, List<AIActionBase> aiActions = null)
{
if (aiActions == null) aiActions = new List<AIActionBase>();
for (int i = 0; i < (int)AIActionType.Max; i++)
{
if (_recordCount > 100) break;
_recordCount++;
_actionRecord++;
var actionType = (AIActionType)(_actionRecord % (int)AIActionType.Max);
if (actionType == AIActionType.Unit) GeneratorUnitActions(aiActions);
else if (actionType == AIActionType.Grid) GeneratorGridActions(aiActions);
else if (actionType == AIActionType.City) GeneratorCityActions(aiActions);
else if (actionType == AIActionType.Tech) GeneratorTechActions(aiActions);
if (aiActions.Count != 0) break;
}
}
private void GeneratorUnitActions(List<AIActionBase> aiActions)
{
if (_waitUnits.Count == 0 || aiActions == null) return;
for (int i = _waitUnits.Count - 1; i >= 0; i--)
{
GeneratorOneUnitActions(_waitUnits[i], aiActions);
if (aiActions.Count != 0) break;
_waitUnits.RemoveAt(i);
}
}
private void GeneratorOneUnitActions(UnitData unit, List<AIActionBase> aiActions)
{
if (ActionLogicFactory.UnitHasMoveAndAttackAction(_mapData, unit, out var aiActionList))
{
foreach (var aiAction in aiActionList) aiActions.Add(aiAction);
}
var param = new CommonActionParams(_mapData, playerData:_player, unitData:unit);
param.RefreshParams();
if (!ActionLogicFactory.UnitHasAction(param, out var actions)) return;
foreach (var action in actions)
{
if (param.PlayerData.PlayerCoin < action.GetCost(param)) continue;
aiActions.Add(new AIActionBase(param, action));
}
}
private void GeneratorGridActions(List<AIActionBase> aiActions)
{
if (_waitGrids.Count == 0 || aiActions == null) return;
for (int i = _waitGrids.Count - 1; i >= 0; i--)
{
GeneratorOneGridActions(_waitGrids[i], aiActions);
if (aiActions.Count != 0) break;
_waitGrids.RemoveAt(i);
}
}
private void GeneratorOneGridActions(GridData grid, List<AIActionBase> aiActions)
{
var gridParam = new CommonActionParams(_mapData, playerData:_player, gridData:grid, mainObjectType:MainObjectType.Grid);
var actionList = new List<ActionLogicBase>();
if (!ActionLogicFactory.GridHasAction(gridParam, actionList)) return;
foreach (var action in actionList)
{
if (action.ActionId.GridMiscActionType == GridMiscActionType.Destroy) continue;
if (action.ActionId.GridMiscActionType == GridMiscActionType.ClearForest) continue;
if (gridParam.PlayerData.PlayerCoin < action.GetCost(gridParam)) continue;
aiActions.Add(new AIActionBase(gridParam, action));
}
}
private void GeneratorCityActions(List<AIActionBase> aiActions)
{
if (_waitCity.Count == 0 || aiActions == null) return;
for (int i = _waitCity.Count - 1; i >= 0; i--)
{
GeneratorOneCityActions(_waitCity[i], aiActions);
if (aiActions.Count != 0) break;
_waitCity.RemoveAt(i);
}
}
private void GeneratorOneCityActions(CityData city, List<AIActionBase> aiActions)
{
var param = new CommonActionParams(_mapData, playerData:_player, cityData:city);
param.RefreshParams();
if (!ActionLogicFactory.CityHasAction(param, out var actions)) return;
foreach (var action in actions)
{
if (param.PlayerData.PlayerCoin < action.GetCost(param)) continue;
aiActions.Add(new AIActionBase(param, action));
}
}
// 穷举科技树行动
private void GeneratorTechActions(List<AIActionBase> aiActions)
{
if (aiActions == null) aiActions = new List<AIActionBase>();
// 玩家行为
var param = new CommonActionParams(_mapData, playerData:_player, mainObjectType:MainObjectType.Player);
param.RefreshParams();
if (!ActionLogicFactory.PlayerHasAction(param, out var actions)) return;
foreach (var action in actions)
{
if (action.ActionId.ActionType != CommonActionType.LearnTech) continue;
if (param.PlayerData.PlayerCoin < action.GetCost(param)) continue;
aiActions.Add(new AIActionBase(param, action));
}
}
// 穷举式生成所有可能的行动
public void GeneratorActions(MapData map, PlayerData player, List<AIActionBase> aiActions = null)
{
if (aiActions == null) aiActions = new List<AIActionBase>();
// 小兵行为
var unitList = new List<UnitData>();
map.GetUnitDataListByPlayerId(player.Id, unitList);
foreach (var unit in unitList)
{
if (ActionLogicFactory.UnitHasMoveAndAttackAction(map, unit, out var aiActionList))
{
foreach (var aiAction in aiActionList) aiActions.Add(aiAction);
}
var param = new CommonActionParams(map, playerData: player, unitData: unit);
param.RefreshParams();
if (!ActionLogicFactory.UnitHasAction(param, out var actions)) continue;
foreach (var action in actions)
{
if (param.PlayerData.PlayerCoin < action.GetCost(param)) continue;
aiActions.Add(new AIActionBase(param, action));
}
}
// 地块行为
var gridSet = map.GetPlayerTerritoryGridIdSet(player.Id);
var gridParam = new CommonActionParams(map, playerData: player, gridData: null,
mainObjectType: MainObjectType.Grid);
var actionList = new List<ActionLogicBase>();
foreach (var gird in map.GridMap.GridList)
{
if (!gridSet.Contains(gird.Id)) continue;
gridParam.GridData = gird;
gridParam.RefreshParams();
if (!ActionLogicFactory.GridHasAction(gridParam, actionList)) continue;
var param = new CommonActionParams(map, playerData: player, gridData: gird,
mainObjectType: MainObjectType.Grid);
foreach (var action in actionList)
{
if (param.PlayerData.PlayerCoin < action.GetCost(param)) continue;
aiActions.Add(new AIActionBase(param, action));
}
}
// 城市行为
var cityList = new List<CityData>();
map.GetCityDataListByPlayerId(player.Id, cityList);
foreach (var city in cityList)
{
var param = new CommonActionParams(map, playerData: player, cityData: city);
param.RefreshParams();
if (!ActionLogicFactory.CityHasAction(param, out var actions)) continue;
foreach (var action in actions)
{
if (param.PlayerData.PlayerCoin < action.GetCost(param)) continue;
aiActions.Add(new AIActionBase(param, action));
}
}
GeneratorTechActions(map, player, aiActions);
}
// 穷举科技树行动
public static void GeneratorTechActions(MapData map, PlayerData player, List<AIActionBase> aiActions = null)
{
if (aiActions == null) aiActions = new List<AIActionBase>();
// 玩家行为
var param = new CommonActionParams(map, playerData:player, mainObjectType:MainObjectType.Player);
param.RefreshParams();
if (!ActionLogicFactory.PlayerHasAction(param, out var actions)) return;
foreach (var action in actions)
{
if (action.ActionId.ActionType != CommonActionType.LearnTech) continue;
if (param.PlayerData.PlayerCoin < action.GetCost(param)) continue;
aiActions.Add(new AIActionBase(param, action));
}
}
// 穷举地图预期收益行动
public static void GeneratorFutureActions(MapData map, PlayerData player, List<AIActionBase> aiActions = null)
{
if (aiActions == null) aiActions = new List<AIActionBase>();
GeneratorTechActions(map, player, aiActions);
for (int i = aiActions.Count - 1; i >= 0; i--)
{
if (aiActions[i].ActionLogic.ActionId == null)
{
aiActions.RemoveAt(i);
continue;
}
if (aiActions[i].ActionLogic.ActionId.ActionType == CommonActionType.Gain) continue;
if (aiActions[i].ActionLogic.ActionId.ActionType == CommonActionType.BuildWonder) continue;
if (aiActions[i].ActionLogic.ActionId.ActionType == CommonActionType.Build) continue;
if (aiActions[i].ActionLogic.ActionId.ActionType == CommonActionType.TrainUnit) continue;
aiActions.RemoveAt(i);
}
}
public static List<AIActionBase> GeneratorAllActionIdsForUse(MapData map, PlayerData selfPlayer)
{
var data = new AICalculatorData();
data.Map = map;
data.Player = selfPlayer;
using var pooledSelfUnits = THCollectionPool.GetHashSetHandle<UnitData>(out var selfUnits);
map.GetUnitDataListByPlayerId(selfPlayer.Id, selfUnits);
using var pooledSelfCities = THCollectionPool.GetHashSetHandle<CityData>(out var selfCities);
map.GetCityDataListByPlayerId(selfPlayer.Id, selfCities);
data.TargetParam.MapData = map;
data.TargetParam.PlayerData = selfPlayer;
GeneratorActionIds(data, CommonActionType.LearnTech);
GeneratorActionIds(data, CommonActionType.StartWonder);
GeneratorActionIds(data, CommonActionType.PlayerAction);
foreach (var city in selfCities)
{
data.TargetParam.CityData = city;
GeneratorActionIds(data, CommonActionType.Gain);
GeneratorActionIds(data, CommonActionType.Build);
GeneratorActionIds(data, CommonActionType.BuildWonder);
GeneratorActionIds(data, CommonActionType.GridMisc);
GeneratorActionIds(data, CommonActionType.TrainUnit);
GeneratorActionIds(data, CommonActionType.CityLevelUpAction);
}
foreach (var unit in selfUnits)
{
data.TargetParam.UnitData = unit;
GeneratorActionIds(data, CommonActionType.UnitAction);
GeneratorActionIds(data, CommonActionType.UnitSkill);
GeneratorActionIds(data, CommonActionType.UnitMove);
GeneratorActionIds(data, CommonActionType.UnitAttack);
// GeneratorActionIds(data, CommonActionType.AIParamControl);
// GeneratorActionIds(data, CommonActionType.UnitAttackAlly);
}
for (int i = data.AIActions.Count - 1; i >= 0; i--)
{
if (data.AIActions[i].ActionLogic.ActionId.PlayerActionType == PlayerActionType.FinishHeroTask)
{
data.AIActions.RemoveAt(i);
continue;
}
if (data.AIActions[i].ActionLogic.ActionId.UnitActionType == UnitActionType.Disband)
{
data.AIActions.RemoveAt(i);
continue;
}
if (data.AIActions[i].ActionLogic.ActionId.UnitActionType == UnitActionType.ForceDisband)
{
data.AIActions.RemoveAt(i);
continue;
}
if (data.AIActions[i].ActionLogic.ActionId.GridMiscActionType == GridMiscActionType.Destroy)
{
data.AIActions.RemoveAt(i);
continue;
}
}
return data.AIActions;
}
public static List<AIActionBase> GeneratorAllActionIds(MapData map, PlayerData selfPlayer)
{
var data = new AICalculatorData();
data.Map = map;
data.Player = selfPlayer;
using var pooledSelfUnits = THCollectionPool.GetHashSetHandle<UnitData>(out var selfUnits);
map.GetUnitDataListByPlayerId(selfPlayer.Id, selfUnits);
using var pooledSelfCities = THCollectionPool.GetHashSetHandle<CityData>(out var selfCities);
map.GetCityDataListByPlayerId(selfPlayer.Id, selfCities);
data.TargetParam.MapData = map;
data.TargetParam.PlayerData = selfPlayer;
GeneratorActionIds(data, CommonActionType.LearnTech);
GeneratorActionIds(data, CommonActionType.StartWonder);
GeneratorActionIds(data, CommonActionType.PlayerAction);
foreach (var city in selfCities)
{
data.TargetParam.CityData = city;
GeneratorActionIds(data, CommonActionType.Gain);
GeneratorActionIds(data, CommonActionType.Build);
GeneratorActionIds(data, CommonActionType.BuildWonder);
GeneratorActionIds(data, CommonActionType.GridMisc);
GeneratorActionIds(data, CommonActionType.TrainUnit);
GeneratorActionIds(data, CommonActionType.CityLevelUpAction);
}
foreach (var unit in selfUnits)
{
data.TargetParam.UnitData = unit;
GeneratorActionIds(data, CommonActionType.UnitAction);
GeneratorActionIds(data, CommonActionType.UnitSkill);
GeneratorActionIds(data, CommonActionType.UnitMove);
GeneratorActionIds(data, CommonActionType.UnitAttack);
GeneratorActionIds(data, CommonActionType.AIParamControl);
GeneratorActionIds(data, CommonActionType.UnitAttackAlly);
}
return data.AIActions;
}
public static void GeneratorActionIds(AICalculatorData data, CommonActionType type)
{
var actions = ActionLogicFactory.GetActionLogicByType(type);
if (actions == null || actions.Count == 0) return;
if (type == CommonActionType.Gain || type == CommonActionType.Build ||
type == CommonActionType.BuildWonder || type == CommonActionType.GridMisc)
{
if (data.TargetParam.CityData == null) return;
data.TargetParam.MainObjectType = ActionLogicFactory.GetMainObjectType(type);
//AI减枝位置
foreach (var gridId in data.TargetParam.CityData.Territory.TerritoryArea)
{
if (!data.Map.GridMap.GetGridDataByGid(gridId, out var grid)) continue;
data.TargetParam.GridData = grid;
data.TargetParam.OnParamChanged();
foreach (var action in actions)
{
if (action.ActionId.GridMiscActionType == GridMiscActionType.Destroy) continue;
if (!action.CheckCan(data.TargetParam)) continue;
var param = data.TargetParam.GetCopyParam();
param.UnitData = null;
param.TargetUnitData = null;
param.TargetGridData = null;
param.TargetPlayerData = null;
param.OnParamChanged();
data.AIActions.Add(new AIActionBase(param, action));
}
}
}
if (type == CommonActionType.StartWonder || type == CommonActionType.LearnTech)
{
data.TargetParam.MainObjectType = ActionLogicFactory.GetMainObjectType(type);
foreach (var action in actions)
{
if (!action.CheckCan(data.TargetParam)) continue;
var param = data.TargetParam.GetCopyParam();
param.UnitData = null;
param.CityData = null;
param.GridData = null;
param.TargetUnitData = null;
param.TargetGridData = null;
param.TargetPlayerData = null;
param.OnParamChanged();
data.AIActions.Add(new AIActionBase(param, action));
}
}
if (type == CommonActionType.TrainUnit || type == CommonActionType.CityLevelUpAction)
{
if (data.TargetParam.CityData == null) return;
data.TargetParam.MainObjectType = ActionLogicFactory.GetMainObjectType(type);
foreach (var action in actions)
{
if (!action.CheckCan(data.TargetParam)) continue;
var param = data.TargetParam.GetCopyParam();
param.UnitData = null;
param.GridData = null;
param.TargetUnitData = null;
param.TargetGridData = null;
param.TargetPlayerData = null;
param.OnParamChanged();
data.AIActions.Add(new AIActionBase(param, action));
}
data.TargetParam.MainObjectType = MainObjectType.Grid;
var cityGrid = data.TargetParam.CityData.Grid(data.TargetParam.MapData);
foreach (var id in data.TargetParam.CityData.Territory.TerritoryArea)
{
if (!data.TargetParam.MapData.GridMap.GetGridDataByGid(id, out var grid)) continue;
if (grid == cityGrid) continue;
data.TargetParam.GridData = grid;
foreach (var action in actions)
{
if (!action.CheckCan(data.TargetParam)) continue;
var param = data.TargetParam.GetCopyParam();
param.UnitData = null;
param.TargetUnitData = null;
param.TargetGridData = null;
param.TargetPlayerData = null;
param.OnParamChanged();
data.AIActions.Add(new AIActionBase(param, action));
}
}
}
if (type == CommonActionType.UnitAction || type == CommonActionType.UnitSkill)
{
if (data.TargetParam.UnitData == null) return;
data.TargetParam.MainObjectType = ActionLogicFactory.GetMainObjectType(type);
foreach (var action in actions)
{
if (!action.CheckCan(data.TargetParam)) continue;
var param = data.TargetParam.GetCopyParam();
param.CityData = null;
param.GridData = null;
param.TargetUnitData = null;
param.TargetGridData = null;
param.TargetPlayerData = null;
param.OnParamChanged();
data.AIActions.Add(new AIActionBase(param, action));
}
}
if (type == CommonActionType.UnitMove)
{
if (data.TargetParam.UnitData == null) return;
if (!data.TargetParam.UnitData.IsAlive()) return;
if (data.TargetParam.UnitData.GetActionPoint(ActionPointType.Move) <= 0) return;
if (!data.Map.GetGridDataByUnitId(data.TargetParam.UnitData.Id, out var unitGrid)) return;
data.TargetParam.MainObjectType = ActionLogicFactory.GetMainObjectType(type);
Main.UnitLogic.CalcUnitMoveInfo(data.Map, data.TargetParam.UnitData.Id);
if (data.TargetList.Count > 0)
{
for (int i = data.TargetList.Count - 1; i >= 0; i--)
{
var gridId = data.TargetList[i];
if (!data.Map.GridMap.GetGridDataByGid(gridId, out var grid)) continue;
var result = Main.UnitLogic.CheckUnitCanMoveOrAttack(data.Map, data.TargetParam.UnitData, grid);
if (result != MoveAttackType.Move && result != MoveAttackType.MoveToPort && result != MoveAttackType.MoveAshore) continue;
data.TargetParam.GridData = grid;
data.TargetParam.OnParamChanged();
foreach (var action in actions)
{
if (!action.CheckCan(data.TargetParam)) continue;
var param = data.TargetParam.GetCopyParam();
param.CityData = null;
param.TargetUnitData = null;
param.TargetGridData = null;
param.TargetPlayerData = null;
param.OnParamChanged();
data.AIActions.Add(new AIActionBase(param, action));
}
break;
}
}
else
{
foreach (var grid in data.Map.GridMap.GridList)
{
if (grid.Id == unitGrid.Id) continue;
var result = Main.UnitLogic.CheckUnitCanMoveOrAttack(data.Map, data.TargetParam.UnitData, grid);
if (result != MoveAttackType.Move && result != MoveAttackType.MoveToPort && result != MoveAttackType.MoveAshore) continue;
data.TargetParam.GridData = grid;
data.TargetParam.OnParamChanged();
foreach (var action in actions)
{
if (!action.CheckCan(data.TargetParam)) continue;
var param = data.TargetParam.GetCopyParam();
param.CityData = null;
param.TargetUnitData = null;
param.TargetGridData = null;
param.TargetPlayerData = null;
param.OnParamChanged();
data.AIActions.Add(new AIActionBase(param, action));
}
}
}
// if (data.TargetList.Count > 0 && data.AIActions.Count == 0)
// {
// data.Map.GridMap.GetGridDataByGid(data.TargetList[0], out var targetGrid);
// var can = Main.UnitLogic.CheckUnitAbleForGrid(data.TargetParam.MapData, data.TargetParam.PlayerData, data.TargetParam.UnitData, targetGrid);
// var test = Main.UnitLogic.CheckUnitCanMoveOrAttack(data.Map, data.TargetParam.UnitData, targetGrid);
// LogSystem.LogError($"提示可能存在问题!!!");
// }
}
if (type == CommonActionType.UnitAttack)
{
if (data.TargetParam.UnitData == null) return;
if (!data.TargetParam.UnitData.IsAlive()) return;
if (data.TargetParam.UnitData.GetActionPoint(ActionPointType.Attack) <= 0) return;
data.TargetParam.MainObjectType = ActionLogicFactory.GetMainObjectType(type);
Main.UnitLogic.CalcUnitMoveInfo(data.Map, data.TargetParam.UnitData.Id);
foreach (var grid in data.Map.GridMap.GridList)
{
//TODO check playerData right
if (!grid.VisibleUnit(data.Map,data.TargetParam.PlayerData, out var targetUnit)) continue;
var result = Main.UnitLogic.CheckUnitCanMoveOrAttack(data.Map, data.TargetParam.UnitData, grid);
if (result != MoveAttackType.Attack) continue;
data.TargetParam.GridData = grid;
data.TargetParam.TargetUnitData = targetUnit;
data.TargetParam.OnParamChanged();
foreach (var action in actions)
{
if (!action.CheckCan(data.TargetParam)) continue;
var param = data.TargetParam.GetCopyParam();
param.CityData = null;
param.TargetGridData = null;
param.TargetPlayerData = null;
param.OnParamChanged();
data.AIActions.Add(new AIActionBase(param, action));
}
}
}
if (type == CommonActionType.PlayerAction)
{
if (data.TargetParam.PlayerData == null) return;
data.TargetParam.MainObjectType = ActionLogicFactory.GetMainObjectType(type);
foreach (var player in data.TargetParam.MapData.PlayerMap.PlayerDataList)
{
if (player.Id == data.TargetParam.PlayerData.Id) continue;
data.TargetParam.TargetPlayerData = player;
data.TargetParam.OnParamChanged();
foreach (var action in actions)
{
if (action.ActionId.PlayerActionType == PlayerActionType.SelectHero ||
action.ActionId.PlayerActionType == PlayerActionType.FinishHeroTask) continue;
if (!action.CheckCan(data.TargetParam)) continue;
var param = data.TargetParam.GetCopyParam();
param.UnitData = null;
param.CityData = null;
param.GridData = null;
param.TargetUnitData = null;
param.TargetGridData = null;
param.OnParamChanged();
data.AIActions.Add(new AIActionBase(param, action));
}
}
// TODO: 暂时屏蔽 Indian/Satori 阵营的英雄选择
//if (data.TargetParam.PlayerData.CivEnum == CivEnum.Indian)
{
// Indian 阵营 AI 不允许选择英雄
}
//else
{
foreach (var action in actions)
{
if (action.ActionId.PlayerActionType != PlayerActionType.SelectHero &&
action.ActionId.PlayerActionType != PlayerActionType.FinishHeroTask) continue;
if (!action.CheckCan(data.TargetParam)) continue;
var param = data.TargetParam.GetCopyParam();
param.UnitData = null;
param.CityData = null;
param.GridData = null;
param.TargetUnitData = null;
param.TargetGridData = null;
param.TargetPlayerData = null;
param.OnParamChanged();
data.AIActions.Add(new AIActionBase(param, action));
}
}
}
if (type == CommonActionType.AIParamControl)
{
if (data.TargetParam.PlayerData == null) return;
if (data.TargetParam.UnitData == null) return;
if (!data.TargetParam.UnitData.IsAlive()) return;
foreach (var action in actions)
{
if (action.ActionId.AIParamType == AIParamControlType.AIMoney) continue;
if (!action.CheckCan(data.TargetParam)) continue;
var param = data.TargetParam.GetCopyParam();
param.CityData = null;
param.GridData = null;
param.TargetUnitData = null;
param.TargetGridData = null;
param.TargetPlayerData = null;
param.OnParamChanged();
data.AIActions.Add(new AIActionBase(param, action));
}
}
if (type == CommonActionType.UnitAttackAlly)
{
if (data.TargetParam.UnitData == null) return;
if (!data.TargetParam.UnitData.IsAlive()) return;
if (data.TargetParam.UnitData.GetActionPoint(ActionPointType.Attack) <= 0) return;
data.TargetParam.MainObjectType = ActionLogicFactory.GetMainObjectType(type);
foreach (var unit in data.TargetParam.MapData.UnitMap.UnitList)
{
if (unit.Id == data.TargetParam.UnitData.Id) continue;
if (!data.TargetParam.MapData.IsLeagueUnitByUnit(unit.Id, data.TargetParam.UnitData.Id)) continue;
data.TargetParam.TargetUnitData = unit;
data.TargetParam.OnParamChanged();
foreach (var action in actions)
{
if (!action.CheckCan(data.TargetParam)) continue;
var param = data.TargetParam.GetCopyParam();
param.CityData = null;
param.GridData = null;
param.TargetGridData = null;
param.TargetPlayerData = null;
param.OnParamChanged();
data.AIActions.Add(new AIActionBase(param, action));
}
}
}
if (type == CommonActionType.UnitAttackGround)
{
if (data.TargetParam.UnitData == null) return;
data.TargetParam.MainObjectType = ActionLogicFactory.GetMainObjectType(type);
var grid = data.TargetParam.UnitData.Grid(data.TargetParam.MapData);
var range = data.TargetParam.UnitData.GetAttackRange(data.TargetParam.MapData);
// 提前为该单位计算移动信息,确保 IsCanAttackTargetGrid 中调用的 IsFinalReachable 可用INFILTRATE 移动优先于 AttackGround 的判定依赖此)
Main.UnitLogic.CalcUnitMoveInfo(data.TargetParam.MapData, data.TargetParam.UnitData.Id);
foreach (var around in data.TargetParam.MapData.GridMap.GetAroundGridData(range, range, grid))
{
data.TargetParam.GridData = around;
data.TargetParam.OnParamChanged();
foreach (var action in actions)
{
if (!action.CheckCan(data.TargetParam)) continue;
var param = data.TargetParam.GetCopyParam();
param.CityData = null;
param.TargetGridData = null;
param.TargetPlayerData = null;
param.TargetUnitData = null;
param.OnParamChanged();
data.AIActions.Add(new AIActionBase(param, action));
}
}
}
if (type == CommonActionType.BuyCultureCard)
{
if (data.TargetParam.PlayerData == null) return;
data.TargetParam.MainObjectType = ActionLogicFactory.GetMainObjectType(type);
foreach (var action in actions)
{
if (!action.CheckCan(data.TargetParam)) continue;
var param = data.TargetParam.GetCopyParam();
param.UnitData = null;
param.CityData = null;
param.GridData = null;
param.TargetUnitData = null;
param.TargetGridData = null;
param.TargetPlayerData = null;
param.OnParamChanged();
data.AIActions.Add(new AIActionBase(param, action));
}
}
}
}
}