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 moveCellList = new List(); public GameObject rootObj; private bool _needRefresh; private List _teamUnits = new List(); private List _buffCellNotices = new List(); private GameObject _buffNoticeObj; private List _boardViewDataList; public void Init() { rootObj = new GameObject("[MoveArea]"); _buffNoticeObj = new GameObject("[BuffNotice]"); _InitBuffCellNotices(_buffNoticeObj.transform); } private void _InitBuffCellNotices(Transform parent) { var map = LevelManager.Instance.CurrentLevel.Map; 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(EventManager.EventName.INFIGHT_UNIT_CELLINDEX_CHANGE, _OnCellIndexChange); EventManager.Instance.Register(EventManager.EventName.INFIGHT_ENTER_UNITCONTAINER, _OnEnterUnitContainer); EventManager.Instance.Register(EventManager.EventName.INFIGHT_EXIT_UNITCONTAINER, _OnExitUnitContainer); EventManager.Instance.Register(EventManager.EventName.INFIGHT_UNIT_REMOVE, _OnUnitRemove); EventManager.Instance.Register(EventManager.EventName.INFIGHT_UNIT_READY, _OnUnitReady); EventManager.Instance.Register(EventManager.EventName.INFIGHT_VEHICLE_DESTROY, _OnVehicleDestroy); EventManager.Instance.Register(EventManager.EventName.INFIGHT_STATE_ENTER_RETREAT, _OnRetreatStateChange); EventManager.Instance.Register(EventManager.EventName.INFIGHT_STATE_EXIT_RETREAT, _OnRetreatStateChange); } private void _UnRegisterEvent() { EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_UNIT_CELLINDEX_CHANGE, _OnCellIndexChange); EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_ENTER_UNITCONTAINER, _OnEnterUnitContainer); EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_EXIT_UNITCONTAINER, _OnExitUnitContainer); EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_UNIT_REMOVE, _OnUnitRemove); EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_UNIT_READY, _OnUnitReady); EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_VEHICLE_DESTROY, _OnVehicleDestroy); EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_STATE_ENTER_RETREAT, _OnRetreatStateChange); EventManager.Instance.Unregister(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(); } _boardViewDataList = null; } } 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 List _workList = new List(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.Add(centerCell); centerCell.isVisited = true; while (workList.Count > 0) { var workCell = workList[^1]; workList.RemoveAt(workList.Count - 1); // 判断当前格子是否可通行 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.Add(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() { if (_boardViewDataList != null) { for (int i = 0; i < _boardViewDataList.Count; i++) { var boardViewData = _boardViewDataList[i]; boardViewData.Destroy(); } } _boardViewDataList = BoardViewHelper.GenerateBoard(moveCellList); for (int i = 0; i < _boardViewDataList.Count; i++) { var boardViewData = _boardViewDataList[i]; boardViewData.CreateBoardSideView(); } } private void _RefreshViewStatus() { if (moveCellList.Count != rootObj.transform.childCount) { // 需要匹配个数 if (moveCellList.Count < rootObj.transform.childCount) { // 多了, 需要删除 var needRemoveCount = rootObj.transform.childCount - moveCellList.Count; for (int i = 0; i < needRemoveCount; i++) { var child = rootObj.transform.GetChild(moveCellList.Count + i); Object.Destroy(child.gameObject); } } else { // 少了, 需要添加 var needAddCount = moveCellList.Count - rootObj.transform.childCount; for (int i = 0; i < needAddCount; i++) { var sampleObj = AssetManager.Instance.GetPreLoadResult(PathDefine.MoveArea.MOVE_AREA_POINT_PATH); Object.Instantiate(sampleObj, rootObj.transform); } } } // 刷新位置 for (int i = 0; i < moveCellList.Count; i++) { var cellIndex = moveCellList[i]; var worldPos = AreaManager.instance.GetWorldPosByIndex(cellIndex); var child = rootObj.transform.GetChild(i); child.position = worldPos; } } private void _RefreshMoveArea() { moveCellList.Clear(); if (owner.statusData.isRetreat) { // 逃跑状态 // do nothing } else { _UpdateMoveCellList(); } // 刷新显示 _RefreshBoardView(); // _RefreshViewStatus(); // 将队友相关的格子移除 _AutoRemoveSelfUnits(); // 将敌人所在格子加入 _AutoAddEnemiesCellIndex(); } public void Dispose() { Hide(); owner = null; moveCellList.Clear(); for (int i = 0; i < _buffCellNotices.Count; i++) { var notice = _buffCellNotices[i]; notice.Dispose(); } _buffCellNotices.Clear(); if (rootObj != null) { Object.Destroy(rootObj); rootObj = null; } if (_buffNoticeObj != null) { Object.Destroy(_buffNoticeObj); _buffNoticeObj = null; } } } }