356 lines
17 KiB
C#
356 lines
17 KiB
C#
/*
|
||
* @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;
|
||
}
|
||
//如果没有视野,播放一个动画后直接return(UtsuhoBase的移动高亮格子除外)
|
||
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() { });
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|