NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Gameplay/PVP/PrepareTeamManager.cs

241 lines
7.0 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using Framework;
using Gameplay;
using Gameplay.Character;
using Gameplay.Level;
using Gameplay.Unit;
using Gameplay.Utils;
using Gameplay.Vehicle.Impl;
using PhxhSDK;
using TGS;
using UnityEngine;
using Action = BehaviorDesigner.Runtime.Tasks.Action;
using Constants = PhxhSDK.Constants;
using Object = UnityEngine.Object;
/// <summary>
/// 用于布阵
/// </summary>
public class PrepareTeamManager : Singlenton<PrepareTeamManager>
{
private const string STAGE_ROOT_NAME = "StageRoot";
private Map _map;
private int _prepareRegionId;
private LevelData.CharacterToward _toward;
private TerrainGridSystem _tgs;
private Quaternion _rotation;
private bool _hasInit;
private Transform _stageRoot;
//key:cellIndex
private Dictionary<int, GameObject> _onStageUnits = new();
//key:prefabPath
private Dictionary<string, List<GameObject>> _modelPool = new();
private Dictionary<GameObject, string> _gameObjectToPathDic = new();
#region API
//当前选择的预制体
public string CurrPrefabPath { get; set; }
//是否可以放置多个相同预制
public bool CanMultiple { get; set; }
public void ShowPrepareRegion()
{
_tgs.showCells = true;
//todo 颜色从配置中获取
_map.SetRegionColor(_prepareRegionId, true, ColorEx.FromStr("#FF960072"));
}
public void HidePrepareRegion()
{
_tgs.showCells = false;
_map.SetRegionColor(_prepareRegionId, false, ColorEx.FromStr("#FF960072"));
}
public void Init(TerrainGridSystem tgs, MapData mapData, int prepareRegionID, LevelData.CharacterToward toward)
{
if (_hasInit)
Dispose();
_tgs = tgs;
_map = MapUtils.LoadMap(tgs, mapData);
MapUtils.BindCameraController(CameraManager.Instance.MainCamera, _map);
_tgs.showCells = true;
if (prepareRegionID < 0 || prepareRegionID >= mapData.regions.Count)
{
Debug.LogError($"找不到region!,regionID:{prepareRegionID}");
return;
}
_toward = toward;
_rotation = Quaternion.Euler(new Vector3(0, LevelUtils.SetCharaterToward(_toward), 0));
_hasInit = true;
_stageRoot = new GameObject(STAGE_ROOT_NAME).transform;
InputManager.Instance.OnClick += OnClick;
}
public void Dispose()
{
_hasInit = false;
_map = null;
_tgs = null;
_onStageUnits.Clear();
_modelPool.Clear();
_gameObjectToPathDic.Clear();
Object.Destroy(_stageRoot.gameObject);
InputManager.Instance.OnClick -= OnClick;
}
#endregion
private void OnClick(Vector2 screenPos)
{
var cellIndex = GroundHitHelper.CalcHitCellIndex(screenPos, _tgs);
if (cellIndex >= 0 && _map.MapData.IsCellInsideRegion(cellIndex, _prepareRegionId) &&
!string.IsNullOrEmpty(CurrPrefabPath))
{
//获得当前选择模型在台上的index
var currPrefabOnStageIndex = GetCellIndexOnStage(CurrPrefabPath);
if (_onStageUnits.TryGetValue(cellIndex, out var go))
{
//如果点击的位置已经有模型了
var pathOnStage = GameObjectToPath(go);
if (pathOnStage == CurrPrefabPath)
{
//台上的模型路径和当前选择的路径相同 下阵
RemoveModel(cellIndex);
return;
}
}
if (currPrefabOnStageIndex >= 0 && !CanMultiple)
{
//如果台上已经有当前选择模型,则和点击位置的模型互换位置
SwapModel(currPrefabOnStageIndex, cellIndex);
}
else
{
//如果台上没有当前选择的模型,则替换掉当前点击位置的模型
AddModel(CurrPrefabPath, cellIndex);
}
}
}
private string GameObjectToPath(GameObject go)
{
return _gameObjectToPathDic.GetValueOrDefault(go);
}
private int GetCellIndexOnStage(string prefabPath)
{
foreach (var kv in _onStageUnits)
{
var cellIndex = kv.Key;
var go = kv.Value;
if (_gameObjectToPathDic[go] == prefabPath)
{
return cellIndex;
}
}
return -1;
}
private async UniTask<GameObject> GetAModel(string prefabPath)
{
GameObject model = null;
if (_modelPool.TryGetValue(prefabPath, out var modelList))
{
if (modelList.Count > 0)
{
model = modelList[^1];
modelList.RemoveAt(modelList.Count - 1);
}
}
if (model == null)
{
var go = await AssetManager.Instance.LoadAssetAsync<GameObject>(prefabPath);
model = Object.Instantiate(go, _stageRoot);
_gameObjectToPathDic.Add(model, prefabPath);
}
return model;
}
private void ReturnModelToPool(GameObject model)
{
var path = _gameObjectToPathDic[model];
if (!_modelPool.TryGetValue(path, out var modelList))
{
modelList = new();
_modelPool.Add(path, modelList);
}
modelList.Add(model);
}
private async void AddModel(string prefabPath, int cellIndex)
{
if (_onStageUnits.ContainsKey(cellIndex))
{
RemoveModel(cellIndex);
}
var model = await GetAModel(prefabPath);
model.SetActive(true);
SetModelPosition(model, cellIndex);
_onStageUnits.Add(cellIndex, model);
}
private void RemoveModel(int cellIndex)
{
if (_onStageUnits.TryGetValue(cellIndex, out var model))
{
model.SetActive(false);
_onStageUnits.Remove(cellIndex);
ReturnModelToPool(model);
}
}
private void SwapModel(int cellIndexLeft, int cellIndexRight)
{
if (cellIndexLeft == cellIndexRight ||
!_map.MapData.IsCellInsideRegion(cellIndexLeft, _prepareRegionId) ||
!_map.MapData.IsCellInsideRegion(cellIndexRight, _prepareRegionId))
return;
var leftModel = _onStageUnits.GetValueOrDefault(cellIndexLeft);
var rightModel = _onStageUnits.GetValueOrDefault(cellIndexRight);
_onStageUnits.Remove(cellIndexLeft);
_onStageUnits.Remove(cellIndexRight);
if (leftModel != null)
{
_onStageUnits.Add(cellIndexRight, leftModel);
SetModelPosition(leftModel, cellIndexRight);
}
if (rightModel != null)
{
_onStageUnits.Add(cellIndexLeft, rightModel);
SetModelPosition(rightModel, cellIndexLeft);
}
}
private void SetModelPosition(GameObject model, int cellIndex)
{
var positionWS = _map.TGSCellIndex2WorldPosition(cellIndex);
model.transform.SetPositionAndRotation(positionWS, _rotation);
}
}