NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Gameplay/Level/AutoDeployment/AutoDeploymentManager.cs

260 lines
9.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System.Collections.Generic;
using Gameplay;
using Gameplay.Character;
using Gameplay.Level;
using Gameplay.Unit;
using PhxhSDK;
public class AutoDeploymentManager : Singlenton<AutoDeploymentManager>
{
public bool IsAutoDeployEnabled { get; private set; } = true;
// 存储每个格子的前出等级
private Dictionary<int, float> _cellForwardScores = new Dictionary<int, float>();
// 敌人分组信息
private List<EnemyGroup> _enemyGroups = new List<EnemyGroup>();
// 记录已分配的格子
private HashSet<int> _occupiedCells = new HashSet<int>();
private class EnemyGroup
{
public int centerCellIndex; // 改用cellIndex替代世界坐标
public int count;
}
private const int GROUP_DISTANCE_THRESHOLD = 3; // 六边形格子距离阈值
private void GroupEnemies(List<GameUnit> enemies, Map map)
{
_enemyGroups.Clear();
foreach (var enemy in enemies)
{
var enemyCellIndex = enemy.transData.cellIndex;
var added = false;
// 尝试加入现有分组
foreach (var group in _enemyGroups)
{
// 使用 MapUtils.Distance 计算格子距离
int distance = MapUtils.Distance(map, enemyCellIndex, group.centerCellIndex);
if (distance <= GROUP_DISTANCE_THRESHOLD)
{
// 更新组中心格子
var oldCenterCell = group.centerCellIndex;
var newCenterCell =
CalculateGroupCenterCell(group.centerCellIndex, enemyCellIndex, group.count, map);
group.centerCellIndex = newCenterCell;
group.count++;
added = true;
// DebugUtil.LogError($"[GroupEnemies] 敌人(格子={enemyCellIndex})加入组(中心={oldCenterCell}->新中心={newCenterCell}, 数量={group.count})");
break;
}
}
// 如果没有合适的分组,创建新分组
if (!added)
{
_enemyGroups.Add(new EnemyGroup
{
centerCellIndex = enemyCellIndex,
count = 1
});
// DebugUtil.LogError($"[GroupEnemies] 创建新敌人组: 中心格子 = {enemyCellIndex}, 数量 = 1");
}
}
// DebugUtil.LogError($"[GroupEnemies] 敌人分组完成,共 {_enemyGroups.Count} 个组");
}
private int CalculateGroupCenterCell(int currentCenterCell, int newCellIndex, int currentCount, Map map)
{
// 获取当前中心和新格子的世界坐标
var currentCenterPos = map.TGSCellIndex2WorldPosition(currentCenterCell);
var newCellPos = map.TGSCellIndex2WorldPosition(newCellIndex);
// 计算新的中心点位置
var newCenterPos = (currentCenterPos * currentCount + newCellPos) / (currentCount + 1);
// 找到最接近这个世界坐标的格子
map.WorldPosition2TGSCellIndex(newCenterPos, out int nearestCellIndex);
return nearestCellIndex;
}
public void AutoDeploy(Level level)
{
// 清空已分配格子记录
_occupiedCells.Clear();
// 1. 获取可用的己方单位
var availableUnits = new List<GameUnit>();
for (var i = 0; i < GameUnitManager.instance.totalUnits.count; i++)
{
var unit = GameUnitManager.instance.totalUnits.GetByIndex(i);
if (unit.commonData.troopId == ETroopsId.Self &&
!GameUnitManager.instance.infightUnits.Contains(unit.GetID()))
{
availableUnits.Add(unit);
}
}
// DebugUtil.LogError($"[AutoDeploy] 找到可用己方单位: {availableUnits.Count}个");
// 2. 获取敌方单位
var enemies = new List<GameUnit>();
for (var i = 0; i < GameUnitManager.instance.infightUnits.count; i++)
{
var unit = GameUnitManager.instance.infightUnits.GetByIndex(i);
if (unit.commonData.troopId != ETroopsId.Self)
{
enemies.Add(unit);
}
}
// DebugUtil.LogError($"[AutoDeploy] 找到敌方单位: {enemies.Count}个");
// 3. 对敌人进行分组
GroupEnemies(enemies, level.Map);
// 4. 计算每个格子的前出等级
CalculateCellForwardScores(level.Map.MapData, level.GetLevelData().preparingRegionId);
// DebugUtil.LogError($"[AutoDeploy] 格子前出等级计算完成,共 {_cellForwardScores.Count} 个格子");
// 5. 对可用单位按前出程度排序
var sortedUnits = new List<GameUnit>(availableUnits);
UnitDeploymentSorter.SortUnitsForDeployment(sortedUnits);
// DebugUtil.LogError("[AutoDeploy] 单位按前出程度排序完成");
// 6. 为每个单位分配位置
int deployedCount = 0;
foreach(var unit in sortedUnits)
{
var bestCell = FindBestCellForUnit(unit);
if (bestCell >= 0)
{
var yaw = LevelUtils.SetCharaterToward(level.GetLevelData().preparingRegionToward);
// 部署单位
GameUnitManager.instance.MoveUnitToFight(unit.GetID(), bestCell, yaw);
// 标记格子为已占用
_occupiedCells.Add(bestCell);
deployedCount++;
// DebugUtil.LogError($"[AutoDeploy] 部署单位: ID = {unit.GetID()}, 职业 = {unit.commonData.eJob}, 格子 = {bestCell}");
}
else
{
// DebugUtil.LogError($"[AutoDeploy] 未找到合适格子部署单位: ID = {unit.GetID()}, 职业 = {unit.commonData.eJob}");
}
}
// DebugUtil.LogError($"[AutoDeploy] 自动部署完成,成功部署 {deployedCount}/{sortedUnits.Count} 个单位");
}
private int FindBestCellForUnit(GameUnit unit)
{
var unitForwardLevel = UnitForwardLevelHelper.GetUnitForwardLevel(unit);
var bestScore = float.MinValue;
var bestCell = -1;
// DebugUtil.LogError($"[FindBestCellForUnit] 为单位寻找最佳格子: ID = {unit.GetID()}, 职业 = {unit.commonData.eJob}, 前出等级 = {unitForwardLevel}");
// 遍历所有计算过前出等级的格子
foreach (var kvp in _cellForwardScores)
{
var cellIndex = kvp.Key;
var score = kvp.Value;
// 检查格子是否已被占用(使用 HashSet 直接检查)
if (_occupiedCells.Contains(cellIndex)) continue;
// 根据单位的前出程度调整分数
var adjustedScore = score * unitForwardLevel;
if (adjustedScore > bestScore)
{
bestScore = adjustedScore;
bestCell = cellIndex;
}
}
/*if (bestCell >= 0)
{
DebugUtil.LogError($"[FindBestCellForUnit] 找到最佳格子: {bestCell}, 调整后评分 = {bestScore}");
}
else
{
DebugUtil.LogError($"[FindBestCellForUnit] 未找到合适格子");
}*/
return bestCell;
}
private void CalculateCellForwardScores(MapData mapData, int preparingRegionId)
{
// DebugUtil.LogError("[CalculateCellForwardScores] 开始计算格子前出等级");
_cellForwardScores.Clear();
var preparingRegion = mapData.GetRegion(preparingRegionId);
if (preparingRegion == null)
{
// DebugUtil.LogError($"[CalculateCellForwardScores] 错误:找不到准备区域(ID={preparingRegionId})");
return;
}
// DebugUtil.LogError($"[CalculateCellForwardScores] 准备区域格子数: {preparingRegion.positions.Count}");
// 对准备区域的每个格子计算分数
foreach (var cellIndex in preparingRegion.positions)
{
float score = 0;
// 计算与所有敌人组的距离评分
foreach (var group in _enemyGroups)
{
// 使用 MapUtils.Distance 计算格子距离
int distance = MapUtils.Distance(
LevelManager.Instance.CurrentLevel.Map,
cellIndex,
group.centerCellIndex);
// 距离越近分数越高,同时考虑敌人组的数量权重
// 使用 1.0f / (distance + 1) 确保不会除以0并且距离越近分数越高
var groupScore = (1.0f / (distance + 1)) * group.count;
score += groupScore;
}
_cellForwardScores[cellIndex] = score;
}
/*// 记录最高分和最低分
if (_cellForwardScores.Count > 0)
{
var maxScore = _cellForwardScores.Max(p => p.Value);
var minScore = _cellForwardScores.Min(p => p.Value);
DebugUtil.LogError($"[CalculateCellForwardScores] 格子评分范围: 最低 = {minScore}, 最高 = {maxScore}");
}
DebugUtil.LogError($"[CalculateCellForwardScores] 计算完成,共 {_cellForwardScores.Count} 个格子");*/
}
public void SetAutoDeployEnabled(bool enabled)
{
IsAutoDeployEnabled = enabled;
// DebugUtil.LogError($"[SetAutoDeployEnabled] 自动部署功能已{(enabled ? "启用" : "禁用")}");
if (enabled && LevelManager.Instance.CurrentLevel != null)
{
AutoDeploy(LevelManager.Instance.CurrentLevel);
}
}
public void OnLevelPreparationStart()
{
if (IsAutoDeployEnabled)
{
DebugUtil.Log("[OnLevelPreparationStart] 自动部署功能已启用,开始执行自动部署");
AutoDeploy(LevelManager.Instance.CurrentLevel);
}
else
{
DebugUtil.Log("[OnLevelPreparationStart] 自动部署功能未启用,跳过自动部署");
}
}
}