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

303 lines
11 KiB
C#

using System.Collections.Generic;
using Gameplay.Common;
using Gameplay.Performance;
using Gameplay.Unit;
namespace Gameplay.Area
{
using Framework;
using Effect;
using Level;
using Skill;
using UnityEngine;
public class SkillAreaSelecter
{
public bool isOnSelecting;
public GameUnit unit;
public SkillHandle skillHandle;
private int _areaId;
private int _lastPlayerCellIndex;
private readonly RaycastHit[] _raycastHits;
private readonly List<int> _cacheCellIndexList;
private int _lastCenterCellIndex;
private List<int> _totalCellIndexList;
private Color _bgAreaColor;
private readonly Color _selectColor;
// private Color _selectCenterColorY;
// private Color _selectCenterColorN;
private readonly Color _hintColor;
private readonly Color _hintColor2;
private TGS.Territory _cacheTerritory;
private GameObject _cacheObjBoarder;
private bool _isCenterCellValid;
private AreaChecker _checker;
private EffectPlayingData _skillAreaEffect;
private static readonly int Color1 = Shader.PropertyToID("_Color");
private static readonly int SecondColor = Shader.PropertyToID("_SecondColor");
public SkillAreaSelecter()
{
_checker = new AreaChecker();
_raycastHits = new RaycastHit[10];
_cacheCellIndexList = new List<int>();
_totalCellIndexList = new List<int>();
_hintColor = ColorUtility.TryParseHtmlString("#C1C336", out Color color) ? color : Color.red;
_selectColor = ColorUtility.TryParseHtmlString("#FF9600", out Color color1) ? color1 : Color.red;
_selectColor.a = 0.45f;
_hintColor2 = ColorUtility.TryParseHtmlString("#c26b36", out Color color2) ? color2 : Color.red;
_hintColor2.a = 0;
}
public void Init()
{
}
public void Dispose()
{
if (_skillAreaEffect != null)
{
_skillAreaEffect.Destroy();
_skillAreaEffect = null;
}
}
public void ShowArea(SkillHandle inSkillHandle)
{
if (isOnSelecting)
{
DebugUtil.LogError("错误的调用: 已经在技能预选中");
return;
}
_isCenterCellValid = false;
isOnSelecting = true;
skillHandle = inSkillHandle;
unit = inSkillHandle.owner;
_areaId = inSkillHandle.runtimeData.configData.ShowAreaId;
_lastCenterCellIndex = -1;
_cacheCellIndexList.Clear();
// 初始化checker
_checker.InitFromCharacterSkill(inSkillHandle);
var map = LevelManager.Instance.CurrentLevel.Map;
var playerCellIndex = unit.transData.cellIndex;
_lastPlayerCellIndex = playerCellIndex;
var seletRange = Mathf.CeilToInt(skillHandle.runtimeData.configData.ReleaseArea * skillHandle.owner.fightData.skillReleaseDistanceScale);
_totalCellIndexList = map.TerrainGridSystem.CellGetNeighboursWithinRange(playerCellIndex, -1, seletRange, canCrossCheckType: TGS.CanCrossCheckType.IgnoreCanCrossCheckOnAllCells);
_totalCellIndexList.Add(playerCellIndex);
_bgAreaColor = new Color(1, 1, 1, 0.5f);
// _selectCenterColorY = Color.green;
// _selectCenterColorN = Color.red;
map.SetBlocksColor(_totalCellIndexList, true, _bgAreaColor);
if (inSkillHandle.runtimeData.configData.ShowEffectId > 0)
{
var pos = unit.transData.pos;
_skillAreaEffect = EffectManager.instance.PlayEffectById(inSkillHandle.runtimeData.configData.ShowEffectId, pos);
}
// 生成技能边框区域
_cacheTerritory = map.TerrainGridSystem.TerritoryCreate(_totalCellIndexList);
var obj = map.TerrainGridSystem.ForceDrawTerritoryDrawInteriorBorder(_cacheTerritory, 0, 1, _hintColor, _hintColor2);
var getMat = obj.transform.GetChild(0).GetComponent<MeshRenderer>().material;
getMat.SetColor(Color1, _hintColor);
getMat.SetColor(SecondColor, _hintColor2);
_cacheObjBoarder = obj;
}
private void _HideAreaBoarderObj()
{
var map = LevelManager.Instance.CurrentLevel.Map;
var territoryIndex = map.TerrainGridSystem.TerritoryGetIndex(_cacheTerritory);
map.TerrainGridSystem.TerritoryDestroy(territoryIndex);
_cacheObjBoarder.Destroy();
}
public void EndShow(bool realUse)
{
if (!isOnSelecting)
{
DebugUtil.LogError("错误的调用: 不在技能预选状态");
return;
}
if (!skillHandle.canRelease)
{
DebugUtil.LogError("技能CD没好,强制取消释放");
realUse = false;
}
_HideAreaBoarderObj();
var map = LevelManager.Instance.CurrentLevel.Map;
if (_skillAreaEffect != null)
{
_skillAreaEffect.Destroy();
_skillAreaEffect = null;
}
isOnSelecting = false;
map.SetBlocksColor(_cacheCellIndexList, false, _bgAreaColor);
map.SetBlocksColor(_totalCellIndexList, false, _bgAreaColor);
if (realUse)
{
if (!_isCenterCellValid)
{
UITipsManager.ShowTips("技能释放点不合法");
EventManager.Instance.Send(EventManager.EventName.UI_SKILL_CANCEL);
return;
}
// 从lastCellIndex进行释放
var eventData = new EventDataUseSkill()
{
sender = unit,
pointCellIndex = _lastCenterCellIndex,
};
EventManager.Instance.Send(EventManager.EventName.UI_USE_SKILL, eventData);
}
else
{
EventManager.Instance.Send(EventManager.EventName.UI_SKILL_CANCEL);
}
}
public void LogicUpdate(float dt)
{
if (!isOnSelecting)
{
return;
}
var mousePos = Input.mousePosition * PerformanceManager.instance.screenScale;
// mousePos = Input.mousePosition;
var camera = Camera.main;
if (camera == null) return;
var map = LevelManager.Instance.CurrentLevel.Map;
var playerNowCellIndex = unit.transData.cellIndex;
if (playerNowCellIndex != _lastPlayerCellIndex)
{
// Debug.LogError("playerNowCellIndex != _lastCenterCellIndex");
_lastPlayerCellIndex = playerNowCellIndex;
// 清除之前的
_HideAreaBoarderObj();
map.SetBlocksColor(_cacheCellIndexList, false, _bgAreaColor);
map.SetBlocksColor(_totalCellIndexList, false, _bgAreaColor);
_cacheCellIndexList.Clear();
// 更新技能影响区域
var seletRange = Mathf.CeilToInt(skillHandle.runtimeData.configData.ReleaseArea * skillHandle.owner.fightData.skillReleaseDistanceScale);
_totalCellIndexList = map.TerrainGridSystem.CellGetNeighboursWithinRange(playerNowCellIndex, -1, seletRange, canCrossCheckType: TGS.CanCrossCheckType.IgnoreCanCrossCheckOnAllCells);
_totalCellIndexList.Add(playerNowCellIndex);
_cacheTerritory = map.TerrainGridSystem.TerritoryCreate(_totalCellIndexList);
var obj = map.TerrainGridSystem.ForceDrawTerritoryDrawInteriorBorder(_cacheTerritory, 0, 1, _hintColor, _hintColor2);
var getMat = obj.transform.GetChild(0).GetComponent<MeshRenderer>().material;
getMat.SetColor(Color1, _hintColor);
getMat.SetColor(SecondColor, _hintColor2);
_cacheObjBoarder = obj;
_lastCenterCellIndex = -1;
}
var ray = camera.ScreenPointToRay(mousePos);
var layerMask = LayerMask.GetMask("Ground");
var raycast = Physics.RaycastNonAlloc(ray, _raycastHits, 1000, layerMask);
if (raycast <= 0) return;
var firstHit = _raycastHits[0];
var hitPoint = firstHit.point;
if (!map.WorldPosition2TGSCellIndex(hitPoint, out var cellIndex)) return;
var mouseCellIndex = cellIndex;
var skillConfig = skillHandle.runtimeData.configData;
if (!_totalCellIndexList.Contains(cellIndex))
{
// 计算出最近的点并进行设置
var minDistance = float.MaxValue;
var newCellIndex = cellIndex;
for (var i = 0; i < _totalCellIndexList.Count; ++i)
{
var bgIndex = _totalCellIndexList[i];
var distance = map.TerrainGridSystem.CellGetHexagonDistance(cellIndex, bgIndex);
if (distance < minDistance)
{
minDistance = distance;
newCellIndex = bgIndex;
}
}
cellIndex = newCellIndex;
}
// if (skillConfig.SkillActionId == 2)
// {
// // 2号技能不需要中心点
// cellIndex = unit.transData.cellIndex;
// }
if (cellIndex != _lastCenterCellIndex)
{
// Debug.LogError("cellIndex != _lastCenterCellIndex");
if (_lastCenterCellIndex != -1)
{
// 将之前的变回
for (var i = 0; i < _cacheCellIndexList.Count; ++i)
{
var index = _cacheCellIndexList[i];
var isInBg = _totalCellIndexList.Contains(index);
map.SetBlockColor(index, isInBg, _bgAreaColor);
}
_cacheCellIndexList.Clear();
}
_lastCenterCellIndex = cellIndex;
// 更新技能影响区域
AreaManager.instance.GetCellIndexs(cellIndex, _areaId, _cacheCellIndexList);
map.SetBlocksColor(_cacheCellIndexList, true, _selectColor);
// map.SetBlockColor(cellIndex, true, _isCenterCellValid ? _selectCenterColorY : _selectCenterColorN);
var centerWorldPos = map.TGSCellIndex2WorldPosition(cellIndex);
if (_skillAreaEffect != null)
{
_skillAreaEffect.transform.position = centerWorldPos;
}
}
// 中心点单独设置
_isCenterCellValid = _CheckCenterAvilable(cellIndex);
if (_isCenterCellValid && skillConfig.ReleaseArea != 0)
{
// 需要处理鼠标是否在技能影响区域内
var isInArea = _cacheCellIndexList.Contains(mouseCellIndex);
if (!isInArea)
{
_isCenterCellValid = false;
}
}
}
private bool _CheckCenterAvilable(int centerCellIndex)
{
return _checker.CheckAvailable(centerCellIndex);
}
}
}