577 lines
18 KiB
C#
577 lines
18 KiB
C#
using System.Collections.Generic;
|
|
using AOT.PostProcess.BlackArea;
|
|
using Framework;
|
|
using Gameplay.Area.BoardView;
|
|
using Gameplay.Common;
|
|
using Gameplay.Level;
|
|
using Gameplay.Unit;
|
|
using Gameplay.Unit.Data;
|
|
using Gameplay.Vehicle.Impl;
|
|
using PhxhSDK;
|
|
using UnityEngine;
|
|
|
|
namespace Gameplay.Area
|
|
{
|
|
public class MoveAreaView
|
|
{
|
|
public GameUnit owner;
|
|
|
|
public List<int> moveCellList = new List<int>();
|
|
|
|
public GameObject rootObj;
|
|
|
|
private bool _needRefresh;
|
|
private Map _map;
|
|
|
|
private List<GameUnit> _teamUnits = new List<GameUnit>();
|
|
private List<BuffCellNotice> _buffCellNotices = new List<BuffCellNotice>();
|
|
|
|
private GameObject _buffNoticeObj;
|
|
private List<BoardViewData> _boardViewDataList = new List<BoardViewData>();
|
|
|
|
public BoardLineObjPool boardLineObjPool = new BoardLineObjPool();
|
|
|
|
// 存储所有格子对象的数组
|
|
private GameObject[] _cellObjects;
|
|
// 标记是否已初始化格子对象
|
|
private bool _isInitialized = false;
|
|
|
|
public void Init(Map map)
|
|
{
|
|
rootObj = new GameObject("[MoveArea]");
|
|
_buffNoticeObj = new GameObject("[BuffNotice]");
|
|
_map = map;
|
|
_InitBuffCellNotices(_buffNoticeObj.transform);
|
|
boardLineObjPool.Init();
|
|
|
|
// 提前初始化所有格子对象,避免首次刷新时卡顿
|
|
_InitializeCellObjects();
|
|
}
|
|
|
|
private void _InitBuffCellNotices(Transform parent)
|
|
{
|
|
var mapData = _map.MapData;
|
|
for (int i = 0; i < mapData.showBuffPoints.Count; i++)
|
|
{
|
|
var buffPoint = mapData.showBuffPoints[i];
|
|
if (string.IsNullOrEmpty(buffPoint.path))
|
|
{
|
|
continue;
|
|
}
|
|
var cellIndex = buffPoint.cellIndex;
|
|
var notice = new BuffCellNotice()
|
|
{
|
|
cellIndex = cellIndex,
|
|
loadPath = buffPoint.path,
|
|
};
|
|
DebugUtil.LogG("BuffCellNotice:" + cellIndex + " " + buffPoint.path);
|
|
notice.CreateView(parent);
|
|
_buffCellNotices.Add(notice);
|
|
}
|
|
}
|
|
|
|
public void Show(GameUnit setOwner)
|
|
{
|
|
owner = setOwner;
|
|
|
|
_UpdateTeamUnits();
|
|
_RefreshMoveArea();
|
|
_needRefresh = false;
|
|
_ShowBuffNotices();
|
|
|
|
rootObj.SetActive(true);
|
|
_buffNoticeObj.SetActive(true);
|
|
|
|
_RegisterEvent();
|
|
}
|
|
|
|
private void _ShowBuffNotices()
|
|
{
|
|
for (int i = 0; i < _buffCellNotices.Count; i++)
|
|
{
|
|
var notice = _buffCellNotices[i];
|
|
if (moveCellList.Contains(notice.cellIndex))
|
|
{
|
|
notice.SetActive(true);
|
|
}
|
|
else
|
|
{
|
|
notice.SetActive(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
private void _RegisterEvent()
|
|
{
|
|
EventManager.Instance.Register<GameUnit>(EventManager.EventName.INFIGHT_UNIT_CELLINDEX_CHANGE, _OnCellIndexChange);
|
|
EventManager.Instance.Register<GameUnit>(EventManager.EventName.INFIGHT_ENTER_UNITCONTAINER, _OnEnterUnitContainer);
|
|
EventManager.Instance.Register<EDExitUnitContainer>(EventManager.EventName.INFIGHT_EXIT_UNITCONTAINER, _OnExitUnitContainer);
|
|
EventManager.Instance.Register<GameUnit>(EventManager.EventName.INFIGHT_UNIT_REMOVE, _OnUnitRemove);
|
|
EventManager.Instance.Register<GameUnit>(EventManager.EventName.INFIGHT_UNIT_READY, _OnUnitReady);
|
|
EventManager.Instance.Register<GameUnit>(EventManager.EventName.INFIGHT_VEHICLE_DESTROY, _OnVehicleDestroy);
|
|
EventManager.Instance.Register<GameUnit>(EventManager.EventName.INFIGHT_STATE_ENTER_RETREAT, _OnRetreatStateChange);
|
|
EventManager.Instance.Register<GameUnit>(EventManager.EventName.INFIGHT_STATE_EXIT_RETREAT, _OnRetreatStateChange);
|
|
}
|
|
|
|
private void _UnRegisterEvent()
|
|
{
|
|
EventManager.Instance.Unregister<GameUnit>(EventManager.EventName.INFIGHT_UNIT_CELLINDEX_CHANGE, _OnCellIndexChange);
|
|
EventManager.Instance.Unregister<GameUnit>(EventManager.EventName.INFIGHT_ENTER_UNITCONTAINER, _OnEnterUnitContainer);
|
|
EventManager.Instance.Unregister<EDExitUnitContainer>(EventManager.EventName.INFIGHT_EXIT_UNITCONTAINER, _OnExitUnitContainer);
|
|
EventManager.Instance.Unregister<GameUnit>(EventManager.EventName.INFIGHT_UNIT_REMOVE, _OnUnitRemove);
|
|
EventManager.Instance.Unregister<GameUnit>(EventManager.EventName.INFIGHT_UNIT_READY, _OnUnitReady);
|
|
EventManager.Instance.Unregister<GameUnit>(EventManager.EventName.INFIGHT_VEHICLE_DESTROY, _OnVehicleDestroy);
|
|
EventManager.Instance.Unregister<GameUnit>(EventManager.EventName.INFIGHT_STATE_ENTER_RETREAT, _OnRetreatStateChange);
|
|
EventManager.Instance.Unregister<GameUnit>(EventManager.EventName.INFIGHT_STATE_EXIT_RETREAT, _OnRetreatStateChange);
|
|
}
|
|
|
|
private void _OnCellIndexChange(GameUnit unit)
|
|
{
|
|
if (unit == owner) return;
|
|
_needRefresh = true;
|
|
}
|
|
|
|
private void _OnRetreatStateChange(GameUnit unit)
|
|
{
|
|
if (unit == owner)
|
|
{
|
|
_needRefresh = true;
|
|
}
|
|
}
|
|
|
|
private void _OnVehicleDestroy(GameUnit unit)
|
|
{
|
|
_needRefresh = true;
|
|
}
|
|
|
|
private void _OnUnitReady(GameUnit unit)
|
|
{
|
|
_needRefresh = true;
|
|
}
|
|
|
|
private void _OnUnitRemove(GameUnit unit)
|
|
{
|
|
_needRefresh = true;
|
|
}
|
|
|
|
private void _OnEnterUnitContainer(GameUnit unit)
|
|
{
|
|
_needRefresh = true;
|
|
}
|
|
|
|
private void _OnExitUnitContainer(EDExitUnitContainer ed)
|
|
{
|
|
_needRefresh = true;
|
|
}
|
|
|
|
private void _UpdateTeamUnits()
|
|
{
|
|
|
|
_teamUnits.Clear();
|
|
var allUnits = GameUnitManager.instance.infightUnits.unitList;
|
|
for (int i = 0; i < allUnits.Count; i++)
|
|
{
|
|
var unit = allUnits[i];
|
|
if (unit == owner)
|
|
{
|
|
continue;
|
|
}
|
|
if (unit.commonData.troopId != owner.commonData.troopId)
|
|
{
|
|
continue;
|
|
}
|
|
// 只要角色和载具
|
|
if (unit.gameunitType != EGameUnitType.Character
|
|
&& unit.gameunitType != EGameUnitType.Vehicle)
|
|
{
|
|
continue;
|
|
}
|
|
_teamUnits.Add(unit);
|
|
}
|
|
}
|
|
|
|
public void Hide()
|
|
{
|
|
_UnRegisterEvent();
|
|
owner = null;
|
|
|
|
if (rootObj != null)
|
|
{
|
|
rootObj.SetActive(false);
|
|
}
|
|
|
|
if (_buffNoticeObj != null)
|
|
{
|
|
_buffNoticeObj.SetActive(false);
|
|
}
|
|
|
|
if (_boardViewDataList != null)
|
|
{
|
|
for (int i = 0; i < _boardViewDataList.Count; i++)
|
|
{
|
|
var boardViewData = _boardViewDataList[i];
|
|
boardViewData.Destroy(LevelManager.Instance.CurrentLevel.Map.TerrainGridSystem);
|
|
}
|
|
_boardViewDataList.Clear();
|
|
}
|
|
|
|
boardLineObjPool.ReturnAll();
|
|
|
|
}
|
|
|
|
public void LogicUpdate()
|
|
{
|
|
if (owner == null) return;
|
|
if (_needRefresh)
|
|
{
|
|
_needRefresh = false;
|
|
_RefreshMoveArea();
|
|
}
|
|
}
|
|
|
|
public bool CheckIsInArea(int cellIndex)
|
|
{
|
|
return moveCellList.Contains(cellIndex);
|
|
}
|
|
|
|
private bool _CheckCanPass(int cellIndex)
|
|
{
|
|
if (cellIndex < 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (cellIndex == owner.transData.cellIndex)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (!PathFinder.CanPass(cellIndex, owner))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!BlackAreaManager.instance.CheckIsInLightArea(cellIndex))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private bool _CheckSelfUnits(int cellIndex)
|
|
{
|
|
// 判断所有队友在不在这个格子上
|
|
// 判断所有队友的targetcell在不在这个格子上
|
|
for (int i = 0; i < _teamUnits.Count; i++)
|
|
{
|
|
var unit = _teamUnits[i];
|
|
if (!unit.statusData.isOnFloor)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (unit.statusData.isDead)
|
|
{
|
|
if (unit.transData.cellIndex == cellIndex)
|
|
{
|
|
return false;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (unit.gameunitType == EGameUnitType.Vehicle)
|
|
{
|
|
// 载具需要额外判断是否已死亡和是否已满载
|
|
var vehicle = unit as NormalVehicle;
|
|
if (vehicle == null)
|
|
{
|
|
continue;
|
|
}
|
|
if (vehicle.CheckCanUp(owner))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
}
|
|
|
|
if (unit.transData.cellIndex == cellIndex)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (unit.controlData.targetCellIndex == cellIndex)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private Queue<TGS.Cell> _workList = new Queue<TGS.Cell>(100);
|
|
|
|
private void _UpdateMoveCellList()
|
|
{
|
|
var centerIndex = owner.transData.cellIndex;
|
|
|
|
var workList = _workList;
|
|
workList.Clear();
|
|
|
|
var mapTgs = LevelManager.Instance.CurrentLevel.Map.TerrainGridSystem;
|
|
var allCellS = mapTgs.cells;
|
|
for (int i = 0; i < allCellS.Count; i++)
|
|
{
|
|
var iCell = allCellS[i];
|
|
iCell.isVisited = false;
|
|
}
|
|
|
|
var centerCell = mapTgs.cells[centerIndex];
|
|
workList.Enqueue(centerCell);
|
|
centerCell.isVisited = true;
|
|
|
|
while (workList.Count > 0)
|
|
{
|
|
var workCell = workList.Dequeue();
|
|
|
|
// 判断当前格子是否可通行
|
|
if (!_CheckCanPass(workCell.index))
|
|
{
|
|
// DebugUtil.LogError("blockedSet.Add:" + lastValue);
|
|
continue;
|
|
}
|
|
// 把自己加入到移动列表
|
|
moveCellList.Add(workCell.index);
|
|
|
|
// 把周围的格子加入到工作列表
|
|
var neighbors = workCell.neighbours;
|
|
for (int i = 0; i < neighbors.Count; i++)
|
|
{
|
|
var iCell = neighbors[i];
|
|
if (iCell.isVisited)
|
|
{
|
|
continue;
|
|
}
|
|
// 添加到检查过列表中
|
|
workList.Enqueue(iCell);
|
|
iCell.isVisited = true;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
private void _AutoRemoveSelfUnits()
|
|
{
|
|
for (int i = 0; i < _teamUnits.Count; i++)
|
|
{
|
|
var unit = _teamUnits[i];
|
|
if (!unit.statusData.isOnFloor)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (unit.statusData.isDead)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (unit.gameunitType == EGameUnitType.Vehicle)
|
|
{
|
|
// 载具需要额外判断是否已死亡和是否已满载
|
|
var vehicle = unit as NormalVehicle;
|
|
if (vehicle == null)
|
|
{
|
|
continue;
|
|
}
|
|
if (vehicle.CheckCanUp(owner))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
var searchIndex = moveCellList.IndexOf(unit.transData.cellIndex);
|
|
if (searchIndex >= 0)
|
|
{
|
|
// fast remove
|
|
moveCellList[searchIndex] = moveCellList[^1];
|
|
moveCellList.RemoveAt(moveCellList.Count - 1);
|
|
}
|
|
}
|
|
|
|
{
|
|
var searchIndex = moveCellList.IndexOf(unit.controlData.targetCellIndex);
|
|
if (searchIndex >= 0)
|
|
{
|
|
// fast remove
|
|
moveCellList[searchIndex] = moveCellList[^1];
|
|
moveCellList.RemoveAt(moveCellList.Count - 1);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
private void _AutoAddEnemiesCellIndex()
|
|
{
|
|
var units = GameUnitManager.instance.infightUnits.unitList;
|
|
for (int i = 0; i < units.Count; i++)
|
|
{
|
|
var unit = units[i];
|
|
if (unit == owner)
|
|
{
|
|
continue;
|
|
}
|
|
if (unit.commonData.troopId == owner.commonData.troopId)
|
|
{
|
|
continue;
|
|
}
|
|
var cellIndex = unit.transData.cellIndex;
|
|
if (!BlackAreaManager.instance.CheckIsInLightArea(cellIndex))
|
|
{
|
|
continue;
|
|
}
|
|
if (unit.statusData.canBeAttack)
|
|
{
|
|
if (!moveCellList.Contains(cellIndex))
|
|
{
|
|
moveCellList.Add(cellIndex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void _RefreshBoardView()
|
|
{
|
|
for (int i = 0; i < _boardViewDataList.Count; i++)
|
|
{
|
|
var boardViewData = _boardViewDataList[i];
|
|
boardViewData.Destroy(LevelManager.Instance.CurrentLevel.Map.TerrainGridSystem);
|
|
}
|
|
_boardViewDataList.Clear();
|
|
boardLineObjPool.ReturnAll();
|
|
BoardViewHelper.GenerateBoard(moveCellList, _boardViewDataList, LevelManager.Instance.CurrentLevel.Map.TerrainGridSystem);
|
|
for (int i = 0; i < _boardViewDataList.Count; i++)
|
|
{
|
|
var boardViewData = _boardViewDataList[i];
|
|
boardViewData.CreateBoardSideView(LevelManager.Instance.CurrentLevel.Map.TerrainGridSystem);
|
|
}
|
|
}
|
|
|
|
private void _RefreshViewStatus()
|
|
{
|
|
var allCellList = LevelManager.Instance.CurrentLevel.Map.TerrainGridSystem.cells;
|
|
var cellCount = allCellList.Count;
|
|
|
|
// 先将所有单元格标记为未访问
|
|
for (int i = 0; i < cellCount; i++)
|
|
{
|
|
allCellList[i].isVisited = false;
|
|
}
|
|
|
|
// 标记可移动格子
|
|
for (int i = 0; i < moveCellList.Count; i++)
|
|
{
|
|
int cellIndex = moveCellList[i];
|
|
allCellList[cellIndex].isVisited = true;
|
|
}
|
|
|
|
// 更新所有格子的显示状态
|
|
for (int i = 0; i < cellCount; i++)
|
|
{
|
|
bool canNotMove = !allCellList[i].isVisited;
|
|
_cellObjects[i].SetActiveEx(canNotMove);
|
|
}
|
|
}
|
|
|
|
// 初始化所有格子对象的方法
|
|
private void _InitializeCellObjects()
|
|
{
|
|
if (_isInitialized) return;
|
|
|
|
var terrainGridSystem = LevelManager.Instance.CurrentLevel.Map.TerrainGridSystem;
|
|
var cellCount = terrainGridSystem.cells.Count;
|
|
|
|
// 创建对象数组
|
|
_cellObjects = new GameObject[cellCount];
|
|
|
|
// 预加载对象模板
|
|
var sampleObj = AssetManager.Instance.GetPreLoadResult<GameObject>(PathDefine.MoveArea.CANNOT_MOVE_AREA_POINT_PATH);
|
|
|
|
// 批量创建所有对象
|
|
for (int i = 0; i < cellCount; i++)
|
|
{
|
|
_cellObjects[i] = Object.Instantiate(sampleObj, rootObj.transform);
|
|
// 设置到对应格子的世界位置
|
|
_cellObjects[i].transform.position = AreaManager.instance.GetWorldPosByIndex(i);
|
|
// 初始时全部隐藏
|
|
_cellObjects[i].SetActive(false);
|
|
}
|
|
|
|
_isInitialized = true;
|
|
}
|
|
|
|
private void _RefreshMoveArea()
|
|
{
|
|
moveCellList.Clear();
|
|
|
|
if (owner.statusData.isRetreat)
|
|
{
|
|
// 逃跑状态
|
|
// do nothing
|
|
}
|
|
else
|
|
{
|
|
_UpdateMoveCellList();
|
|
}
|
|
|
|
// 刷新显示
|
|
// _RefreshBoardView();
|
|
|
|
|
|
// 将队友相关的格子移除
|
|
_AutoRemoveSelfUnits();
|
|
// 将敌人所在格子加入
|
|
_AutoAddEnemiesCellIndex();
|
|
|
|
_RefreshViewStatus();
|
|
|
|
}
|
|
|
|
|
|
public void Dispose()
|
|
{
|
|
Hide();
|
|
moveCellList.Clear();
|
|
|
|
for (int i = 0; i < _buffCellNotices.Count; i++)
|
|
{
|
|
var notice = _buffCellNotices[i];
|
|
notice.Dispose();
|
|
}
|
|
_buffCellNotices.Clear();
|
|
|
|
// 清理格子对象
|
|
_cellObjects = null;
|
|
_isInitialized = false;
|
|
|
|
if (rootObj != null)
|
|
{
|
|
Object.Destroy(rootObj);
|
|
rootObj = null;
|
|
}
|
|
|
|
if (_buffNoticeObj != null)
|
|
{
|
|
Object.Destroy(_buffNoticeObj);
|
|
_buffNoticeObj = null;
|
|
}
|
|
|
|
boardLineObjPool.Dispose();
|
|
boardLineObjPool = null;
|
|
}
|
|
}
|
|
}
|