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 _selectCellIndexList; private int _lastCenterCellIndex; private Stack _pointsStack; private List _selectPointList; private List _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 selectCellIndexList => _selectCellIndexList; public SkillAreaSelecter() { _checker = new AreaChecker(); _raycastHits = new RaycastHit[10]; _selectCellIndexList = new List(); _pointsStack = new Stack(); _selectPointList = new List(); _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().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().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); } } }