using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using cfg.SkillCfg; using Gameplay.Common; namespace Gameplay.Area { using Framework; using Character; using Effect; using Level; using Skill; using TMPro; 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 _cacheCellIndexList; private int _lastCenterCellIndex; private List _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 EffectPlayingData _skillAreaEffect; private static readonly int Color1 = Shader.PropertyToID("_Color"); private static readonly int SecondColor = Shader.PropertyToID("_SecondColor"); public SkillAreaSelecter() { _raycastHits = new RaycastHit[10]; _cacheCellIndexList = new List(); _totalCellIndexList = new List(); _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(); 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().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 && _isCenterCellValid) { // 从lastCellIndex进行释放 var eventData = new EventDataUseSkill() { sender = unit, pointCellIndex = _lastCenterCellIndex, }; EventManager.Instance.Send(EventManager.EventName.UI_USE_SKILL, eventData); } } public void LogicUpdate(float dt) { if (!isOnSelecting) { return; } var mousePos = InputManager.Instance.GetTouchPosition(); var camera = Camera.main; if (camera == null) return; var map = LevelManager.Instance.CurrentLevel.Map; var playerNowCellIndex = unit.transData.cellIndex; if (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().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 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) { 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); } private bool _CheckCenterAvilable(int centerCellIndex) { var skillConfig = skillHandle.runtimeData.configData; switch (skillConfig.ReleaseCheckType) { // 常规 case EReleaseCheckType.None: return true; case EReleaseCheckType.CenterIsEnemy: return _CheckCenterIsEnemy(centerCellIndex); case EReleaseCheckType.CenterIsSelfSide: return _CheckCenterIsSelfSide(centerCellIndex); case EReleaseCheckType.CenterIsEmpty: return _CheckCenterIsEmpty(centerCellIndex); case EReleaseCheckType.AreaContainsEnemy: return _CheckAreaContainsEnemy(centerCellIndex); case EReleaseCheckType.AreaContainsSelfSide: return _CheckAreaContainsSelfSide(centerCellIndex); default: DebugUtil.LogError("暂未处理的检查类型:{0}", skillConfig.ReleaseCheckType); return false; } } private bool _CheckAreaContainsSelfSide(int centerCellIndex) { var influenceAreaId = skillHandle.runtimeData.configData.InfluenceAreaId; var areaIndexs = AreaManager.instance.GetCellIndexs(centerCellIndex, influenceAreaId); // 查找所有友军 for (var i = 0; i < areaIndexs.Count; ++i) { var searchCellIndex = areaIndexs[i]; var isSelf = _CheckCenterIsSelfSide(searchCellIndex); if (isSelf) return true; } return false; } private bool _CheckAreaContainsEnemy(int centerCellIndex) { var influenceAreaId = skillHandle.runtimeData.configData.InfluenceAreaId; var areaIndexs = AreaManager.instance.GetCellIndexs(centerCellIndex, influenceAreaId); // 查找所有敌人 for (var i = 0; i < areaIndexs.Count; ++i) { var searchCellIndex = areaIndexs[i]; var isEnemy = _CheckCenterIsEnemy(searchCellIndex); if (isEnemy) return true; } return false; } private bool _CheckCenterIsEmpty(int centerCellIndex) { var units = AreaManager.instance.GetUnitsByCellIndex(centerCellIndex); var isEmpty = units.Count == 0; return isEmpty; } private bool _CheckCenterIsSelfSide(int centerCellIndex) { var units = AreaManager.instance.GetUnitsByCellIndex(centerCellIndex); var senderTroopId = unit.commonData.troopId; var isSelf = false; for (var i = 0; i < units.Count; ++i) { var u = units[i]; if (u.gameunitType != EGameUnitType.Character) continue; if (u.commonData.troopId == senderTroopId) { isSelf = true; break; } } return isSelf; } private bool _CheckCenterIsEnemy(int centerCellIndex) { var units = AreaManager.instance.GetUnitsByCellIndex(centerCellIndex); var senderTroopId = unit.commonData.troopId; var isEnemy = false; for (var i = 0; i < units.Count; ++i) { var u = units[i]; if (u.gameunitType != EGameUnitType.Character) continue; if (u.commonData.troopId != senderTroopId) { isEnemy = true; break; } } return isEnemy; } } }