378 lines
14 KiB
C#
378 lines
14 KiB
C#
using System.Collections.Generic;
|
|
using Gameplay.Area.Ready;
|
|
using Gameplay.Common;
|
|
using Gameplay.Performance;
|
|
using Gameplay.Unit;
|
|
|
|
namespace Gameplay.Area
|
|
{
|
|
using Framework;
|
|
using Effect;
|
|
using Level;
|
|
using Skill;
|
|
using UnityEngine;
|
|
using Gameplay.Guide;
|
|
|
|
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> _selectCellIndexList;
|
|
private int _lastCenterCellIndex;
|
|
private Stack<ReadyAreaPoint> _pointsStack;
|
|
private List<ReadyAreaPoint> _selectPointList;
|
|
|
|
private List<int> _totalCellIndexList;
|
|
|
|
private Color _bgAreaColor;
|
|
|
|
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 List<int> selectCellIndexList => _selectCellIndexList;
|
|
|
|
public SkillAreaSelecter()
|
|
{
|
|
_checker = new AreaChecker();
|
|
_raycastHits = new RaycastHit[10];
|
|
_selectCellIndexList = new List<int>();
|
|
_pointsStack = new Stack<ReadyAreaPoint>();
|
|
_selectPointList = new List<ReadyAreaPoint>();
|
|
|
|
_hintColor = ColorUtility.TryParseHtmlString("#C1C336", out Color color) ? color : Color.red;
|
|
_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;
|
|
}
|
|
}
|
|
|
|
private void _SetTotalCellIndex()
|
|
{
|
|
var seletRange = Mathf.CeilToInt(skillHandle.runtimeData.configData.ReleaseArea * skillHandle.owner.fightData.skillReleaseDistanceScale);
|
|
var attackArea = AreaManager.instance.attackAreaManager.GetAttackArea(skillHandle.owner.transData.cellIndex, seletRange);
|
|
if (skillHandle.runtimeData.configData.IgnoreBlock)
|
|
{
|
|
_totalCellIndexList = attackArea.totalCells;
|
|
}
|
|
else
|
|
{
|
|
_totalCellIndexList = attackArea.canAttackCells;
|
|
}
|
|
}
|
|
|
|
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;
|
|
_selectCellIndexList.Clear();
|
|
|
|
// 初始化checker
|
|
_checker.InitFromCharacterSkill(inSkillHandle);
|
|
|
|
var map = LevelManager.Instance.CurrentLevel.Map;
|
|
var playerCellIndex = unit.transData.cellIndex;
|
|
_lastPlayerCellIndex = playerCellIndex;
|
|
_SetTotalCellIndex();
|
|
_bgAreaColor = CmpAreaColorSettings.instance.m_SkillAreaBgColor;
|
|
// _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 bool EndShow(bool realUse)
|
|
{
|
|
if (!isOnSelecting)
|
|
{
|
|
DebugUtil.LogError("错误的调用: 不在技能预选状态");
|
|
return false;
|
|
}
|
|
if (!skillHandle.canRelease)
|
|
{
|
|
DebugUtil.LogError("技能CD没好,强制取消释放");
|
|
realUse = false;
|
|
}
|
|
_HideAreaBoarderObj();
|
|
var map = LevelManager.Instance.CurrentLevel.Map;
|
|
|
|
if (_skillAreaEffect != null)
|
|
{
|
|
_skillAreaEffect.Destroy();
|
|
_skillAreaEffect = null;
|
|
}
|
|
|
|
isOnSelecting = false;
|
|
|
|
_HideSelectArea();
|
|
map.SetBlocksColor(_totalCellIndexList, false, _bgAreaColor);
|
|
|
|
if (realUse)
|
|
{
|
|
if (!_isCenterCellValid)
|
|
{
|
|
UITipsManager.ShowTips("技能释放点不合法");
|
|
EventManager.Instance.Send(EventManager.EventName.UI_SKILL_CANCEL);
|
|
return false;
|
|
}
|
|
// 从lastCellIndex进行释放
|
|
var eventData = new EventDataUseSkill()
|
|
{
|
|
sender = unit,
|
|
pointCellIndex = _lastCenterCellIndex,
|
|
};
|
|
EventManager.Instance.Send(EventManager.EventName.UI_USE_SKILL, eventData);
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
EventManager.Instance.Send(EventManager.EventName.UI_SKILL_CANCEL);
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private void _ShowSelectArea()
|
|
{
|
|
if (_selectPointList.Count != _selectCellIndexList.Count)
|
|
{
|
|
if (_selectPointList.Count > _selectCellIndexList.Count)
|
|
{
|
|
// 已有的更多, 需要隐藏多余的
|
|
var needRemoveCount = _selectPointList.Count - _selectCellIndexList.Count;
|
|
for (int i = 0; i < needRemoveCount; i++)
|
|
{
|
|
var removeIndex = _selectPointList.Count - 1;
|
|
var removePoint = _selectPointList[removeIndex];
|
|
removePoint.Hide();
|
|
_selectPointList.RemoveAt(removeIndex);
|
|
_pointsStack.Push(removePoint);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// 需要添加新的
|
|
var needAddCount = _selectCellIndexList.Count - _selectPointList.Count;
|
|
for (int i = 0; i < needAddCount; i++)
|
|
{
|
|
var newPoint = _GetOrCreate();
|
|
_selectPointList.Add(newPoint);
|
|
}
|
|
}
|
|
}
|
|
for (int i = 0; i < _selectCellIndexList.Count; i++)
|
|
{
|
|
var cellIndex = _selectCellIndexList[i];
|
|
var point = _selectPointList[i];
|
|
point.SetIndex(cellIndex);
|
|
}
|
|
}
|
|
|
|
private ReadyAreaPoint _GetOrCreate()
|
|
{
|
|
if (_pointsStack.Count > 0)
|
|
{
|
|
return _pointsStack.Pop();
|
|
}
|
|
var newPoint = new ReadyAreaPoint(PathDefine.SkillArea.SELECT_POINT);
|
|
return newPoint;
|
|
}
|
|
|
|
private void _HideSelectArea()
|
|
{
|
|
for (int i = 0; i < _selectPointList.Count; i++)
|
|
{
|
|
var point = _selectPointList[i];
|
|
point.Hide();
|
|
_pointsStack.Push(point);
|
|
}
|
|
_selectPointList.Clear();
|
|
_selectCellIndexList.Clear();
|
|
}
|
|
|
|
public void LogicUpdate(float dt)
|
|
{
|
|
if (!isOnSelecting)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (_totalCellIndexList == null)
|
|
{
|
|
_lastPlayerCellIndex = -1;
|
|
}
|
|
|
|
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();
|
|
if (_totalCellIndexList != null)
|
|
{
|
|
map.SetBlocksColor(_totalCellIndexList, false, _bgAreaColor);
|
|
}
|
|
|
|
// 更新技能影响区域
|
|
_SetTotalCellIndex();
|
|
|
|
_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);
|
|
map.SetBlocksColor(_totalCellIndexList, true, _bgAreaColor);
|
|
_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");
|
|
|
|
_lastCenterCellIndex = cellIndex;
|
|
|
|
// 更新技能影响区域
|
|
_selectCellIndexList.Clear();
|
|
AreaManager.instance.GetCellIndexs(cellIndex, _areaId, _selectCellIndexList);
|
|
_ShowSelectArea();
|
|
|
|
// map.SetBlockColor(cellIndex, true, _isCenterCellValid ? _selectCenterColorY : _selectCenterColorN);
|
|
|
|
var centerWorldPos = map.TGSCellIndex2WorldPosition(cellIndex);
|
|
if (_skillAreaEffect != null)
|
|
{
|
|
_skillAreaEffect.transform.position = centerWorldPos;
|
|
}
|
|
}
|
|
|
|
// 中心点单独设置
|
|
_isCenterCellValid = _CheckCenterAvilable(cellIndex);
|
|
if (GuideManager.Instance.IsGuiding && GuideManager.Instance.IsControlFloor) // 引导释放技能特殊处理
|
|
_isCenterCellValid &= cellIndex == GuideManager.Instance.FloorIndex;
|
|
DebugUtil.LogG("中心点是否合法: " + _isCenterCellValid);
|
|
|
|
if (_isCenterCellValid && skillConfig.ReleaseArea != 0)
|
|
{
|
|
// 需要处理鼠标是否在技能影响区域内
|
|
var isInArea = _selectCellIndexList.Contains(mouseCellIndex);
|
|
if (!isInArea)
|
|
{
|
|
DebugUtil.LogP("技能释放点不在技能可释放区域内");
|
|
_isCenterCellValid = false;
|
|
}
|
|
else
|
|
{
|
|
DebugUtil.LogG("技能释放点在技能可释放区域内");
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool _CheckCenterAvilable(int centerCellIndex)
|
|
{
|
|
return _checker.CheckAvailable(centerCellIndex);
|
|
}
|
|
|
|
}
|
|
}
|