NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Gameplay/Area/AreaManager.cs

533 lines
18 KiB
C#

using cfg.AreaCfg;
using Framework;
using Gameplay.Level;
using System;
using System.Collections.Generic;
using Gameplay.Area.AttackArea;
using Gameplay.Area.Ready;
using Gameplay.Common;
using Gameplay.Fight.Protect;
using Gameplay.Unit;
using Gameplay.Unit.Data;
using UnityEngine;
namespace Gameplay.Area
{
using Skill;
public class AreaManager
{
public static bool ENABLE_LOG = false;
private static AreaManager _instance;
public static AreaManager instance
{
get
{
return _instance;
}
}
public static void CreateInstance()
{
if (_instance != null)
{
DebugUtil.LogError("请勿重复创建AreaManager");
return;
}
_instance = new AreaManager();
}
private readonly Dictionary<int, List<Vector2Int>> _areaDict;
private readonly SkillAreaSelecter _skillAreaSelecter;
private readonly Dictionary<int, List<GameUnit>> _cellIndex2Units;
private Map _map;
private readonly List<RoadLineView> _beProtectUnitLines;
private readonly AttackAreaView _attackArea;
public readonly ReadyAreaManager readyAreaManager;
public readonly AttackAreaManager attackAreaManager;
public readonly MoveAreaView moveAreaView;
public SkillAreaSelecter SkillAreaSelecter => _skillAreaSelecter;
private Dictionary<int, AroundCellData> _aroundCellDatas = new Dictionary<int, AroundCellData>();
public bool isInSelecting
{
get
{
return _skillAreaSelecter.isOnSelecting;
}
}
private AreaManager()
{
_areaDict = new Dictionary<int, List<Vector2Int>>();
_skillAreaSelecter = new SkillAreaSelecter();
_cellIndex2Units = new Dictionary<int, List<GameUnit>>();
_attackArea = new AttackAreaView();
_beProtectUnitLines = new List<RoadLineView>();
_map = LevelManager.Instance.CurrentLevel.Map;
readyAreaManager = new ReadyAreaManager(_map);
attackAreaManager = new AttackAreaManager();
moveAreaView = new MoveAreaView();
}
public void Init()
{
moveAreaView.Init();
_skillAreaSelecter.Init();
_attackArea.Init();
readyAreaManager.Init();
attackAreaManager.Init();
_RegistEvents();
}
public void Dispose()
{
_skillAreaSelecter.Dispose();
for (int i = 0; i < _beProtectUnitLines.Count; i++)
{
var line = _beProtectUnitLines[i];
line.Dispose();
}
_beProtectUnitLines.Clear();
readyAreaManager.Dispose();
attackAreaManager.Dispose();
moveAreaView.Dispose();
_aroundCellDatas.Clear();
_UnRegistEvents();
_instance = null;
}
public void RegistBeProtectUnit(BeProtectUnit unit)
{
var line = new RoadLineView();
line.owner = unit;
line.Init();
_beProtectUnitLines.Add(line);
}
private void _RegistEvents()
{
EventManager.Instance.Register(EventManager.EventName.UI_START_USE_SKILL, (Action<GameUnit>)_OnPreUseSkill);
EventManager.Instance.Register(EventManager.EventName.UI_END_USE_SKILL, (Action<bool>)_OnEndUseSkill);
EventManager.Instance.Register(EventManager.EventName.INFIGHT_UNIT_READY, (Action<GameUnit>)_OnUnitReady);
EventManager.Instance.Register(EventManager.EventName.INFIGHT_UNIT_REMOVE, (Action<GameUnit>)_OnUnitRemove);
EventManager.Instance.Register(EventManager.EventName.INFIGHT_UNIT_CELLINDEX_CHANGE, (Action<GameUnit>)_OnUnitCellChange);
EventManager.Instance.Register(EventManager.EventName.LevelUnitSelect, (Action<GameUnit>)_OnSelectCharacter);
EventManager.Instance.Register(EventManager.EventName.LevelUnitUnSelect, (Action<GameUnit>)_OnUnSelectCharacter);
EventManager.Instance.Register(EventManager.EventName.INFIGHT_UP_VEHICLE, (Action<GameUnit>)_OnUpVehicle);
EventManager.Instance.Register(EventManager.EventName.INFIGHT_DOWN_VEHICLE, (Action<EDDownVehicle>)_OnDownVehicle);
EventManager.Instance.Register(EventManager.EventName.INFIGHT_SKILL_END_PAUSE, _OnSkillPauseEnd);
}
private void _UnRegistEvents()
{
EventManager.Instance.Unregister(EventManager.EventName.UI_START_USE_SKILL, (Action<GameUnit>)_OnPreUseSkill);
EventManager.Instance.Unregister(EventManager.EventName.UI_END_USE_SKILL, (Action<bool>)_OnEndUseSkill);
EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_UNIT_READY, (Action<GameUnit>)_OnUnitReady);
EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_UNIT_REMOVE, (Action<GameUnit>)_OnUnitRemove);
EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_UNIT_CELLINDEX_CHANGE, (Action<GameUnit>)_OnUnitCellChange);
EventManager.Instance.Unregister(EventManager.EventName.LevelUnitSelect, (Action<GameUnit>)_OnSelectCharacter);
EventManager.Instance.Unregister(EventManager.EventName.LevelUnitUnSelect, (Action<GameUnit>)_OnUnSelectCharacter);
EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_UP_VEHICLE, (Action<GameUnit>)_OnUpVehicle);
EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_DOWN_VEHICLE, (Action<EDDownVehicle>)_OnDownVehicle);
EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_SKILL_END_PAUSE, _OnSkillPauseEnd);
}
private void _OnUpVehicle(GameUnit unit)
{
var cellIndex = unit.transData.cellIndex;
// 设置地图通行状态
// _map.GetRuntimeBlockProperty(cellIndex, out var oldData);
// var blockData = _map.GetBlockData(cellIndex);
// oldData.crossLevel = blockData.GetTerrainTypeProperty().crossLevel;
// _map.SetRuntimeBlockProperty(cellIndex, oldData);
// 移除角色
var unitList = _cellIndex2Units[cellIndex];
unitList.Remove(unit);
_Log($"Unit: {unit.GetID()} Up Vehicle at:{cellIndex}");
}
private void _OnDownVehicle(EDDownVehicle ed)
{
var unit = ed.unit;
var bornCellIndex = unit.transData.cellIndex;
_Log($"Unit: {unit.GetID()} Down Vehicle at:{bornCellIndex}");
_AddUnitToCellIndex(bornCellIndex, unit);
}
private void _OnSelectCharacter(GameUnit c)
{
_attackArea.SetOwner(c);
moveAreaView.Show(c);
}
private void _OnUnSelectCharacter(GameUnit c)
{
_attackArea.HideArea();
moveAreaView.Hide();
}
private void _OnUnitReady(GameUnit unit)
{
var bornCellIndex = unit.transData.cellIndex;
_Log($"Unit: {unit.GetID()} Ready at: {bornCellIndex}");
_AddUnitToCellIndex(bornCellIndex, unit);
}
private void _AddUnitToCellIndex(int cellIndex,
GameUnit unit)
{
// 设置地图通行状态
// >0 才进行设置
// if (unit.commonData.standLevel > 0)
// {
// _map.GetRuntimeBlockProperty(cellIndex, out var setData);
// setData.crossLevel = unit.commonData.standLevel;
// _map.SetRuntimeBlockProperty(cellIndex, setData);
// }
if (_cellIndex2Units.TryGetValue(cellIndex, out var unitList))
{
unitList.Add(unit);
}
else
{
unitList = new List<GameUnit>();
unitList.Add(unit);
_cellIndex2Units.Add(cellIndex, unitList);
}
_Log($"add unit:{unit.GetID()} to cellIndex:{cellIndex}");
}
private void _OnUnitRemove(GameUnit unit)
{
var cellIndex = unit.transData.cellIndex;
if (DebugUtil.LogEnable)
_Log($"Unit: {unit.GetID()} Remove at: {cellIndex}");
// 这里必须能去到,所以不用tryget, 如果报错 需要排查上游
// if (unit.commonData.standLevel > 0)
// {
// // 设置地图通行状态
// _map.GetRuntimeBlockProperty(cellIndex, out var oldData);
// var blockData = _map.GetBlockData(cellIndex);
// oldData.crossLevel = blockData.GetTerrainTypeProperty().crossLevel;
// _map.SetRuntimeBlockProperty(cellIndex, oldData);
// }
var unitList = _cellIndex2Units[cellIndex];
unitList.Remove(unit);
}
private void _OnUnitCellChange(GameUnit unit)
{
var lastCellIndex = unit.transData.lastCellIndex;
var newCellIndex = unit.transData.cellIndex;
if (lastCellIndex != -1)
{
// 设置地图通行状态
// if (unit.commonData.standLevel > 0)
// {
// _map.GetRuntimeBlockProperty(lastCellIndex, out var oldData);
// var blockData = _map.GetBlockData(lastCellIndex);
// oldData.crossLevel = blockData.GetTerrainTypeProperty().crossLevel;
// _map.SetRuntimeBlockProperty(lastCellIndex, oldData);
// }
// 移除旧的
var unitList = _cellIndex2Units[lastCellIndex];
unitList.Remove(unit);
}
// 添加新的
_AddUnitToCellIndex(newCellIndex, unit);
if (DebugUtil.LogEnable)
_Log($"Unit CellIndexChange:{unit.GetID()} from:{lastCellIndex} to {newCellIndex}");
}
private static void _Log(string str)
{
if (!ENABLE_LOG) return;
DebugUtil.Log("[AreaManager] {0}", str);
}
public DataArea GetConfigById(int areaId)
{
return TableManager.Instance.Tables.AreaConfig.Get(areaId);
}
private List<int> _emptyList = new List<int>();
public List<int> GetCellIndexsAround(int centerCellIndex,
int distance, bool containsCenter = true)
{
var key = AroundCellData.GetKey(centerCellIndex, distance, containsCenter);
if (_aroundCellDatas.TryGetValue(key, out var data))
{
return data.aroundCellIndexs;
}
var list = _GetCellIndexsAround(centerCellIndex, distance, containsCenter);
var aroundData = new AroundCellData(centerCellIndex, distance, containsCenter);
aroundData.aroundCellIndexs = list;
_aroundCellDatas.Add(key, aroundData);
return list;
}
private List<int> _GetCellIndexsAround(int centerCellIndex,
int distance, bool containsCenter = true)
{
if (distance <= 0)
{
if (containsCenter)
{
return new List<int>()
{
centerCellIndex
};
}
else
{
return _emptyList;
}
}
var list = _map.TerrainGridSystem.CellGetNeighboursWithinRange(centerCellIndex, 0, distance, canCrossCheckType: TGS.CanCrossCheckType.IgnoreCanCrossCheckOnAllCells);
if (containsCenter)
{
list.Insert(0, centerCellIndex);
}
return list;
}
public bool IsCellEmpty(int cellIndex)
{
var unitList = GetUnitsByCellIndex(cellIndex);
return unitList.Count == 0;
}
public int GetDistance(int cellIndex1,
int cellIndex2)
{
return _map.TerrainGridSystem.CellGetHexagonDistance(cellIndex1, cellIndex2);
}
public Vector3 GetCellPosByIndex(int cellIndex)
{
var getPos = _map.TerrainGridSystem.CellGetPosition(cellIndex);
return getPos;
}
public int GetCellIndexByPos(Vector3 pos)
{
if (_map.WorldPosition2TGSCellIndex(pos, out var result))
{
return result;
}
DebugUtil.LogError("无法获取到CellIndex:" + pos);
return -1;
}
public bool CheckIsNeighbour(int fromIndex,
int checkIndex)
{
var aroundList = _map.TerrainGridSystem.CellGetNeighbours(fromIndex);
for (var i = 0; i < aroundList.Count; i++)
{
var around = aroundList[i];
if (around.index == checkIndex)
{
return true;
}
}
return false;
}
public List<int> GetCellIndexs(int centerCellIndex,
int areaId)
{
var list = new List<int>();
GetCellIndexs(centerCellIndex, areaId, list);
return list;
}
public void GetCellIndexs(int centerCellIndex,
int areaId,
List<int> list)
{
var map = LevelManager.Instance.CurrentLevel.Map;
var posVec = map.TGSCellIndex2BlockPosition(centerCellIndex);
var offsetList = _GetOffsetList(areaId);
for (var i = 0; i < offsetList.Count; ++i)
{
var offset = offsetList[i];
var calcPos = posVec + offset;
if (posVec.x % 2 == 1 && calcPos.x % 2 == 0)
{
calcPos.y += 1;
}
var cellIndex = map.BlockPosition2TGSCellIndex(calcPos);
if (cellIndex == -1)
{
continue;
}
var getSuccess = map.GetRuntimeBlockProperty(cellIndex, out var blockData);
if (!getSuccess)
{
continue;
}
if (blockData.selectable == false)
{
continue;
}
list.Add(cellIndex);
}
}
private List<Vector2Int> _GetOffsetList(int areaId)
{
if (_areaDict.TryGetValue(areaId, out var offsetList))
{
return offsetList;
}
else
{
// 不存在,现场进行加载
var areaData = GetConfigById(areaId);
if (areaData == null)
{
DebugUtil.LogError("AreaId:{0}不存在", areaId);
return null;
}
offsetList = new List<Vector2Int>();
var intList = areaData.Points;
for (int i = 0; i < intList.Count; i += 2)
{
offsetList.Add(new Vector2Int(intList[i], intList[i + 1]));
}
_areaDict.Add(areaId, offsetList);
return offsetList;
}
}
private void _OnPreUseSkill(GameUnit unit)
{
var skillUnit = SkillManager.instance.GetUnitSkillManager(unit);
if (skillUnit == null)
{
DebugUtil.LogError("Unit:{0} 未挂载UnitSkillManager", unit.GetID());
return;
}
if (skillUnit.positiveSkill == null)
{
DebugUtil.LogError("Unit:{0} 未挂载PositiveSkill", unit.GetID());
return;
}
_attackArea.ForceHide();
_skillAreaSelecter.ShowArea(skillUnit.positiveSkill);
}
private void _OnEndUseSkill(bool isCancel)
{
if (DebugUtil.LogEnable)
DebugUtil.Log("UI事件: 结束技能预选: 是否cancel:{0}", isCancel);
var isUse = _skillAreaSelecter.EndShow(!isCancel);
if (isUse)
{
// 使用技能的话 要等技能结束才显示攻击范围
}
else
{
_attackArea.CancelForce();
}
}
private void _OnSkillPauseEnd()
{
if (_attackArea == null)
{
DebugUtil.LogError("AttackArea为空");
return;
}
_attackArea.CancelForce();
}
public void LogicUpdate(float dt)
{
_skillAreaSelecter.LogicUpdate(dt);
for (int i = 0; i < _beProtectUnitLines.Count; i++)
{
var line = _beProtectUnitLines[i];
line.LogicUpdate(dt);
}
_attackArea.LogicUpdate(dt);
readyAreaManager.LogicUpdate(dt);
attackAreaManager.LogicUpdate(dt);
moveAreaView.LogicUpdate();
}
public bool CheckContainsMoveUnit(int cellIndex)
{
var units = GetUnitsByCellIndex(cellIndex);
for (int i = 0; i < units.Count; i++)
{
var unit = units[i];
if (unit.gameunitType == EGameUnitType.Character
|| unit.gameunitType == EGameUnitType.Vehicle)
{
return true;
}
}
return false;
}
public List<GameUnit> GetUnitsByCellIndex(int cellIndex)
{
if (_cellIndex2Units.TryGetValue(cellIndex, out var result))
{
return result;
}
else
{
var newList = new List<GameUnit>();
_cellIndex2Units.Add(cellIndex, newList);
return newList;
}
}
public bool CheckCellCanCross(int targetCellIndex, int crossLevel)
{
_map.GetRuntimeBlockProperty(targetCellIndex, out var blockData);
return blockData.crossLevel >= crossLevel;
}
}
}