TH1/Unity/Assets/Scripts/TH1_Logic/Map/MapInteraction.cs
2026-05-21 02:00:00 +08:00

356 lines
17 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* @Author: 白哉
* @Description: 地图交互逻辑
* @Date: 2025年04月01日 星期二 11:04:00
* @Modify:
*/
using System.Runtime.InteropServices;
using Logic.Action;
using Logic.Audio;
using UnityEngine;
using RuntimeData;
using TH1_Anim.UnitAtomAnim;
using TH1_Core.Events;
using TH1_Core.Managers;
using TH1_Logic.Core;
using TH1_Presentation.Sequencer.Task;
using TH1_Renderer;
using TH1_Renderer.UnitAtomAnim;
using TH1Renderer;
using UI;
namespace Logic
{
public class MapInteraction
{
//private MapData _mapData;
private Main _main;
private MapData _mapData;
//public MapRenderer mapRenderer; // 关联到 Tilemap
//public UIManager uiManager;
public MapInteraction(Main main,MapData mapData)
{
_main = main;
_mapData = mapData;
}
// 当前被半透的城市格 Id(0 = 无),用来保底恢复
private uint _fadeCityGridId = 0;
// 保底:把上一次半透处理过的城市恢复正常透明度。任何状态切换前都应调用
private void ClearCityFadeIfAny()
{
if (_fadeCityGridId == 0) return;
if (MapRenderer.Instance != null
&& MapRenderer.Instance.ROGridMap.TryGetValue(_fadeCityGridId, out var roGrid))
{
roGrid.ClearCityBuildingFade();
}
_fadeCityGridId = 0;
}
// 检测 clickedGrid 是否正好在某城市的"正上方 1/2 格"(城市在 clickedGrid 的 -1-1 / -2-2 位置),
// 命中则对该城市应用 fade。z >= h 的房子半透
private void TryApplyCityFadeForClickedGrid(GridData clickedGrid)
{
if (clickedGrid == null) return;
int cx = clickedGrid.Pos.X;
int cy = clickedGrid.Pos.Y;
//距离 1 上方:城市在 (cx-1, cy-1) → z>=2 半透
if (TryFadeCityAt(cx - 1, cy - 1, 2)) return;
//距离 2 上方:城市在 (cx-2, cy-2) → z>=5 半透
TryFadeCityAt(cx - 2, cy - 2, 5);
}
private bool TryFadeCityAt(int x, int y, int fadeHeight)
{
if (!_mapData.GridMap.GetGridDataByPos(x, y, out var targetGrid)) return false;
if (!targetGrid.CityOnGrid(_mapData, out _)) return false;
if (!MapRenderer.Instance.ROGridMap.TryGetValue(targetGrid.Id, out var roGrid)) return false;
roGrid.SetCityBuildingFadeAboveHeight(fadeHeight);
_fadeCityGridId = targetGrid.Id;
return true;
}
public void CancelAllHighlight() //专门用来应对BottomInfoUI的CloseButton的函数点击close的时候先调用这个函数通知interaction处理好信息再关闭bottominfo
{
//保底:恢复所有被半透的城市
ClearCityFadeIfAny();
foreach (var gridData in Main.MapData.GridMap.GridList)
{
gridData.CityBorderRenderMark = false;
var gridRenderer = MapRenderer.Instance.ROGridMap[gridData.Id];
gridRenderer.GridVFXManager.SetStop(GridVFXType.DieHint);
gridRenderer.GridVFXManager.SetStop(GridVFXType.CounterDieHint);
gridRenderer.SetSelectHighlight(false);
gridRenderer.SetMoveHighlight(false);
gridRenderer.SetAttackHighlight(false);
}
foreach (var unitData in Main.MapData.UnitMap.UnitList)
{
if (!MapRenderer.Instance.ROUnitMap.ContainsKey(unitData.Id)) continue;
var unitRenderer = MapRenderer.Instance.ROUnitMap[unitData.Id];
unitRenderer.SetSelectHighlight(false);
unitRenderer.SetAttackHighlight(false);
unitRenderer.SetAllyHighlight(false);
}
MapRenderer.Instance.ClearDamagePreview();
}
/// <summary>
/// 观战模式下的地块点击:仅显示信息面板+聚焦相机,不产生任何高亮、弹跳、选中等视觉效果
/// </summary>
private void OnTileClickedObservation(MapData mapData, GridData gridData)
{
//不在视野内则静默return不播放雾VFX
if (!mapData.PlayerMap.SelfPlayerData.Sight.CheckIsInSight(gridData.Id))
return;
//聚焦相机到点击的格子
MapRenderer.Instance.CameraController.CameraFocusOnGrid(gridData);
bool hasUnit = gridData.MainSelfPlayerVisibleUnit( out var unitData);
if (hasUnit)
{
EventManager.Publish(new ShowUIInfoGridInfo() { type = UIGridInfoType.unit, id = unitData.Id });
}
else
{
EventManager.Publish(new ShowUIInfoGridInfo() { type = UIGridInfoType.grid, id = gridData.Id });
}
}
public void OnTileClicked(MapData mapData,GridData gridData)
{
MapRecordManager.Instance.RecordGridData = gridData;
AudioManager.Instance.PlayAudio("SFX/UNIT_click",0,0,false);
//如果当前是AI正在进行进入观战模式仅允许查看信息不产生任何视觉变化
if (mapData.CurPlayer != mapData.PlayerMap.SelfPlayerData)
{
OnTileClickedObservation(mapData, gridData);
return;
}
//如果没有视野播放一个动画后直接returnUtsuhoBase的移动高亮格子除外
if (!mapData.PlayerMap.SelfPlayerData.Sight.CheckIsInSight(gridData.Id))
{
bool utsuhoBaseMove = MapRenderer.Instance.SelectUnitData != null
&& MapRenderer.Instance.SelectUnitData.GetSkill(SkillType.UtsuhoBase, out var _)
&& MapRenderer.Instance.ROGridMap[gridData.Id].IsMoveHighlight;
if (!utsuhoBaseMove)
{
MapRenderer.Instance.ROGridMap[gridData.Id].SetBounceAnim();
MapRenderer.Instance.ROGridMap[gridData.Id].PlayVFXForce(new GridVFXParams(GridVFXType.Fog));
CancelAllHighlight();
EventManager.Publish(new HideUIInfoGridInfo() { });
return;
}
}
bool hasUnit = gridData.MainSelfPlayerVisibleUnit(out var unitData);
var roGrid = MapRenderer.Instance.ROGridMap[gridData.Id];
//如果这次点击有unit
if (hasUnit)
{
_mapData.GetPlayerDataByUnitId(unitData.Id, out var player);
var tt = _mapData.PlayerMap.SelfPlayerData;
var roUnit = MapRenderer.Instance.ROUnitMap[unitData.Id];
//如果是由选择人切为选择地块
if (roUnit.IsSelectHighlight)
{
//切换相机镜头
MapRenderer.Instance.CameraController.CameraFocusOnGrid(gridData);
CancelAllHighlight();
MapRenderer.Instance.ROGridMap[gridData.Id].SetSelectHighlight(true);
//检测点击格"下方 1/2 格"是否有城市,有则对其建筑应用 fade
TryApplyCityFadeForClickedGrid(gridData);
//如果点击格属于某城市领土,对应城市中心播放弹跳动画
if (_mapData.GetCityDataByTerritoryGid(gridData.Id, out var city))
{
if(_mapData.GetGridDataByCityId(city.Id,out var gridTmp)
&& Main.MapData.PlayerMap.SelfPlayerData.Sight.CheckIsInSight(gridTmp.Id))
MapRenderer.Instance.ROGridMap[gridTmp.Id].SetBounceAnim();
}
//UIManager.Instance.BottomInfoUI.SetBottomInfoShowGrid(gridData.Id);
EventManager.Publish(new ShowUIInfoGridInfo() {type = UIGridInfoType.grid,id = gridData.Id });
}
//如果是攻击
else if (roUnit.IsAttackHighlight)
{
CancelAllHighlight();
// 攻击行为切换成 Action 驱动
var attackID = new CommonActionId { ActionType = CommonActionType.UnitAttack };
var attackAction = new UnitAttackAction(attackID);
var param = new CommonActionParams(Main.MapData, playerData:Main.MapData.PlayerMap.SelfPlayerData,unitData:MapRenderer.Instance.SelectUnitData, targetUnit:unitData);
param.RefreshParams();
attackAction.CompleteExecute(param);
EventManager.Publish(new HideUIInfoGridInfo() { });
//攻击后判定是否连续行动
if (MapRenderer.Instance.SelectUnitData.IsAlive() &&
MapRenderer.Instance.CheckUnitHasMoveAttackTarget(MapRenderer.Instance.SelectUnitData.Id))
PresentationManager.EnqueueTask(new InputSequencerTask(MapRenderer.Instance.SelectUnitData.Grid(Main.MapData)));
}
//如果是Ally
else if (roUnit.IsAllyHighlight)
{
CancelAllHighlight();
var attackAllyID = new CommonActionId { ActionType = CommonActionType.UnitAttackAlly };
var attackAllyAction = new UnitAttackAllyAction(attackAllyID);
var param = new CommonActionParams(Main.MapData, playerData:Main.MapData.PlayerMap.SelfPlayerData,unitData:MapRenderer.Instance.SelectUnitData, targetUnit:unitData);
param.RefreshParams();
attackAllyAction.CompleteExecute(param);
//Main.UnitLogic.AttackAlly(Main.MapData,MapRenderer.Instance.SelectUnitData, unitData);
//UIManager.Instance.BottomInfoUI.UIBottomInfoStatus = false;
EventManager.Publish(new HideUIInfoGridInfo() { });
//攻击后判定是否连续行动
if (MapRenderer.Instance.SelectUnitData.IsAlive() &&
MapRenderer.Instance.CheckUnitHasMoveAttackTarget(MapRenderer.Instance.SelectUnitData.Id))
PresentationManager.EnqueueTask(new InputSequencerTask(MapRenderer.Instance.SelectUnitData.Grid(Main.MapData)));
}
// UtsuhoBase特殊处理移动范围内有单位的格子也可以移动
else if (roGrid.IsMoveHighlight && MapRenderer.Instance.SelectUnitData != null
&& MapRenderer.Instance.SelectUnitData.GetSkill(SkillType.UtsuhoBase, out var _)
&& MapRenderer.Instance.SelectUnitData.GetActionPoint(ActionPointType.Move) > 0)
{
var selectUnit = MapRenderer.Instance.SelectUnitData;
CancelAllHighlight();
Main.UnitLogic.MoveTo(Main.MapData, Main.MapData.PlayerMap.SelfPlayerData, selectUnit, gridData);
MapRenderer.Instance.CameraController.CameraFocusOnGrid(gridData);
EventManager.Publish(new HideUIInfoGridInfo() { });
if (selectUnit.IsAlive() &&
MapRenderer.Instance.CheckUnitHasMoveAttackTarget(selectUnit.Id))
{
Timer.Instance.TimerRegister(this, () =>
{
OnTileClicked(mapData,gridData);
},Table.Instance.AnimDataAssets.MoveAnimTime,"MapInteraction_OnTileClicked_Move");
}
}
//如果是选择角色
else if (!roGrid.IsSelectHighlight)
{
//播放弹动动画
roUnit.AnimManager.EnqueueAnim(UnitAtomAnimType.Bounce,UnitAtomAnimDataFactory.Create(UnitAtomAnimType.Bounce));
//切换相机镜头
MapRenderer.Instance.CameraController.CameraFocusOnGrid(gridData);
CancelAllHighlight();
MapRenderer.Instance.ROUnitMap[unitData.Id].SetSelectHighlight(true);
MapRenderer.Instance.SelectUnitData = unitData;
EventManager.Publish(new ShowUIInfoGridInfo() {type = UIGridInfoType.unit,id = unitData.Id });
// ---------------------------------------------别找了 在这里!!!-----------------------------------------------------------------------------------------------------------------------------------------
//如果是selfplayer的unit显示可操作区域
if (Main.UnitLogic.CheckIsSelfPlayer(Main.MapData, unitData.Id))
MapRenderer.Instance.SetUnitAllMoveAttackTargetHighlight(unitData.Id);
}
//如果是取消选择角色
else
{
CancelAllHighlight();
//UIManager.Instance.BottomInfoUI.UIBottomInfoStatus = false;
EventManager.Publish(new HideUIInfoGridInfo() { });
}
}
//如果点击的是地块
//如果是移动
else if (roGrid.IsMoveHighlight)
{
CancelAllHighlight();
Main.UnitLogic.MoveTo(Main.MapData,Main.MapData.PlayerMap.SelfPlayerData, MapRenderer.Instance.SelectUnitData, gridData);
//切换相机镜头
MapRenderer.Instance.CameraController.CameraFocusOnGrid(gridData);
EventManager.Publish(new HideUIInfoGridInfo() { });
if (MapRenderer.Instance.SelectUnitData.IsAlive() &&
MapRenderer.Instance.CheckUnitHasMoveAttackTarget(MapRenderer.Instance.SelectUnitData.Id))
{
Timer.Instance.TimerRegister(this, () =>
{
OnTileClicked(mapData,gridData);
},Table.Instance.AnimDataAssets.MoveAnimTime,"MapInteraction_OnTileClicked_Move");
}
}
//如果是攻击地块
else if (roGrid.IsAttackHighlight)
{
CancelAllHighlight();
var attackGroundID = new CommonActionId { ActionType = CommonActionType.UnitAttackGround };
var attackGroundAction = new UnitAttackGroundAction(attackGroundID);
var param = new CommonActionParams(Main.MapData, playerData:Main.MapData.PlayerMap.SelfPlayerData,unitData:MapRenderer.Instance.SelectUnitData, gridData:gridData);
param.RefreshParams();
attackGroundAction.CompleteExecute(param);
EventManager.Publish(new HideUIInfoGridInfo() { });
//攻击后判定是否连续行动
if (MapRenderer.Instance.SelectUnitData.IsAlive() &&
MapRenderer.Instance.CheckUnitHasMoveAttackTarget(MapRenderer.Instance.SelectUnitData.Id))
PresentationManager.EnqueueTask(new InputSequencerTask(MapRenderer.Instance.SelectUnitData.Grid(Main.MapData)));
}
//如果是地块点击
else if (!roGrid.IsSelectHighlight)
{
//切换相机镜头
MapRenderer.Instance.CameraController.CameraFocusOnGrid(gridData);
CancelAllHighlight();
MapRenderer.Instance.ROGridMap[gridData.Id].SetSelectHighlight(true);
//检测点击格"下方 1/2 格"是否有城市,有则对其建筑应用 fade
TryApplyCityFadeForClickedGrid(gridData);
if (_mapData.GetCityDataByTerritoryGid(gridData.Id, out var city))
{
if(_mapData.GetGridDataByCityId(city.Id,out var gridTmp)
&& Main.MapData.PlayerMap.SelfPlayerData.Sight.CheckIsInSight(gridTmp.Id))
MapRenderer.Instance.ROGridMap[gridTmp.Id].SetBounceAnim();
}
//UIManager.Instance.BottomInfoUI.UIBottomInfoHideFirst = UIManager.Instance.BottomInfoUI.UIBottomInfoStatus;
//UIManager.Instance.BottomInfoUI.UIBottomInfoStatus = true;
EventManager.Publish(new ShowUIInfoGridInfo() { type = UIGridInfoType.grid,id = gridData.Id });
//UIManager.Instance.BottomInfoUI.UIBottomInfoIsGrid = true;
//UIManager.Instance.BottomInfoUI.UIBottomInfoStatusObjectId = gridData.Id;
}
//如果是取消地块点击
else
{
CancelAllHighlight();
EventManager.Publish(new HideUIInfoGridInfo() { });
}
}
}
}