using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; 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 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; var seletRange = inSkillHandle.runtimeData.configData.ReleaseArea; _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 _HideAreaBoarder() { 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; } _HideAreaBoarder(); 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 ray = camera.ScreenPointToRay(mousePos); var layerMask = LayerMask.GetMask("Ground"); var raycast = Physics.RaycastNonAlloc(ray, _raycastHits, 1000, layerMask); var map = LevelManager.Instance.CurrentLevel.Map; 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.SkillActionId) { // 常规 case 1: return _CheckSkillAction1(centerCellIndex); case 2: return _CheckSkillAction2(centerCellIndex); default: DebugUtil.LogError("暂未处理的技能类型:{0}", skillConfig.SkillActionId); return false; } } private bool _CheckSkillAction2(int centerCellIndex) { var skillConfig = skillHandle.runtimeData.configData; var onwerTroopId = unit.commonData.troopId; // 查找所有敌人 var units = GameUnitMapper.Inst.unitList; var map = LevelManager.Instance.CurrentLevel.Map; for (int i = 0; i < units.Count; i++) { var searchUnit = units[i]; if (searchUnit.statusData.isDead) continue; if (searchUnit.commonData.troopId != onwerTroopId) { var distance = map.TerrainGridSystem.CellGetHexagonDistance(centerCellIndex, searchUnit.transData.cellIndex); if (distance== -1) continue; if (distance <= skillConfig.ReleaseArea) { return true; } } } return false; } private bool _CheckSkillAction1(int centerCellIndex) { var units = AreaManager.instance.GetUnitsByCellIndex(centerCellIndex); var targetType = skillHandle.runtimeData.configData.TargetType; switch (targetType) { case cfg.SkillCfg.ETargetType.EnemySide: { var isEnemy = false; for (var i = 0; i < units.Count; ++i) { var u = units[i]; if (u.commonData.troopId != unit.commonData.troopId) { isEnemy = true; break; } } return isEnemy; } case cfg.SkillCfg.ETargetType.Self: { var isSelf = false; for (var i = 0; i < units.Count; ++i) { var u = units[i]; if (u == unit) { isSelf = true; break; } } return isSelf; } case cfg.SkillCfg.ETargetType.EmptyCell: { var isEmpty = units.Count == 0; return isEmpty; } case cfg.SkillCfg.ETargetType.AnyCell: { return true; } } DebugUtil.LogError($"暂未处理的targetType:{targetType}"); return false; } } }