debug skill , 增加renderer的保护,修改房间里civ状态的同步逻辑
This commit is contained in:
parent
32822df303
commit
9bc559cfc0
107
.codex/skills/th1-crashsight-daily/SKILL.md
Normal file
107
.codex/skills/th1-crashsight-daily/SKILL.md
Normal file
@ -0,0 +1,107 @@
|
||||
---
|
||||
name: th1-crashsight-daily
|
||||
description: TH1 project-specific daily CrashSight triage workflow for using the logged-in Chrome session to scan recent versions, inspect every CrashSight error, decode obfuscated Unity C# stacks, classify only direct exceptions or try/catch captured exceptions as blocking, and write Markdown blocking/debug reports under MD/. Use when the user asks for CrashSight daily reports, 最近一天异常扫描, version-scoped crash/error triage, blocking/debug report generation, or recurring production error review.
|
||||
---
|
||||
|
||||
# TH1 CrashSight Daily
|
||||
|
||||
## Core Rule
|
||||
|
||||
Do not over-classify business `LogSystem.LogError` telemetry as blocking.
|
||||
|
||||
Classify an issue as `blocking` only when one of these is true:
|
||||
|
||||
- CrashSight issue type is a real exception, such as `NullReferenceException`, `KeyNotFoundException`, `InvalidOperationException`, `ArgumentNullException`, `MemoryPackSerializationException`, `DllNotFoundException`, etc.
|
||||
- The visible message or detail page contains a try/catch captured exception object or stack, such as `System.*Exception`, `异常类型`, `异常信息`, `调用堆栈`, `error: System...`, `failed: System...`, `ex: Object reference`, or `at Namespace.Type.Method(...)`.
|
||||
- A `UnityLogError` is clearly wrapping an exception caught by code, for example `OnMessageReceived 处理失败, error: System.NullReferenceException...`, `Timer任务执行异常: 异常类型: ...`, or `EventManager Publish<...> listener failed: System...`.
|
||||
|
||||
Classify as `debug` when the issue is only a plain project log or diagnostic state, even if it sounds serious:
|
||||
|
||||
- Player/map/action mismatch logs without an exception object, such as `CompleteExecute Player 不一致`, `Map不一致`, `OnReceivedActionExcute Player 不一致`.
|
||||
- AI/action diagnostics such as `存在相似action`, `不应该出现在...`, `CheckCan No`, `ActionConfirm send failed`, unless a concrete exception stack is present.
|
||||
- Networking/environment/send telemetry such as STS/OSS failures, P2P send/connect failures, lobby failures, ForceUpdate/request logs, player-net mapping failure logs, Steam not logged in.
|
||||
- UI/prefab guard logs such as `CityInfoMono.SetCulture: ... is null` or `FragmentDie: UnitRenderer 为空` when they are plain guard logs, not thrown/caught exceptions.
|
||||
- Save/file/Workshop/local environment logs when they do not include an exception stack.
|
||||
|
||||
When uncertain after quick preview, open the detail page. If the detail still does not contain a concrete exception object/stack, keep it in `debug` and record the code location only.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Use the Chrome skill, not the in-app browser, because CrashSight requires the user's logged-in Chrome session.
|
||||
2. Open the CrashSight errors URL from the user or the previous daily URL.
|
||||
3. Filter scope:
|
||||
- status: open/processing, usually `status=0,2`.
|
||||
- exception category: `ERROR`.
|
||||
- date: last 1 day.
|
||||
- versions: use the two user-specified recent versions; if unspecified, inspect the version dropdown and choose the newest two target release versions only. Avoid broad wildcard ranges unless the user explicitly asks.
|
||||
4. Capture all list pages, increasing `rows` when possible, and dedupe by Issue ID. Store raw captured rows under `Temp/CrashSight/Daily_<yyyy-MM-dd>/`.
|
||||
5. Inspect issues one by one:
|
||||
- Use quick preview when it shows full message and stack.
|
||||
- Open issue detail when preview is truncated, message is `-`, the stack lacks symbols, or classification depends on whether a real exception is present.
|
||||
6. Decode obfuscated online stacks before code search:
|
||||
- Use `Tools/DecodeOnlineError.ps1` or `Tools/ObfuscatedExceptionDecoder.ps1`.
|
||||
- Decode all blocking candidates and any debug rows that need code location from an obfuscated stack.
|
||||
7. Locate code with `rg` and the decoded symbols. Prefer exact method/class names first, then stable message strings.
|
||||
8. Generate Markdown under `MD/CrashSight_<yyyy-MM-dd>_<versions>_1day/`.
|
||||
|
||||
## Output Layout
|
||||
|
||||
Create this structure:
|
||||
|
||||
```text
|
||||
MD/CrashSight_<yyyy-MM-dd>_<versionA>_<versionB>_1day/
|
||||
├── index.md
|
||||
├── debug_summary.md
|
||||
├── report_manifest.json
|
||||
└── blocking/
|
||||
├── 001_issue_<id>.md
|
||||
└── ...
|
||||
```
|
||||
|
||||
Use a filesystem-safe version suffix, for example `0.7.1k_0.7.1j`.
|
||||
|
||||
`index.md` must include:
|
||||
|
||||
- filter scope and capture time.
|
||||
- CrashSight total seen and deduped rows.
|
||||
- blocking issue count/occurrence count.
|
||||
- debug issue count/occurrence count.
|
||||
- blocking family table sorted by occurrence count.
|
||||
- top blocking issues with links to per-issue reports.
|
||||
|
||||
`debug_summary.md` must include:
|
||||
|
||||
- debug category summary with counts, occurrences, code locations, and example Issue IDs.
|
||||
- debug detail table for every debug Issue.
|
||||
- no trigger-cause analysis and no business fix explanation.
|
||||
|
||||
Each `blocking/*.md` must include:
|
||||
|
||||
- Issue ID, CrashSight URL, type, versions, first/last seen, count.
|
||||
- raw message and key stack.
|
||||
- decoded stack or decoded log text.
|
||||
- code location with file paths and line numbers when possible.
|
||||
- trigger reason and why it is blocking.
|
||||
- focused recommendation.
|
||||
|
||||
`report_manifest.json` must mirror the final classification and counts so a later run can audit changes.
|
||||
|
||||
## Classification Audit
|
||||
|
||||
Before finalizing, run a text audit over the generated results:
|
||||
|
||||
- Verify every `blocking` issue either has a non-`UnityLogError` exception type or contains a concrete caught exception/stack in the message/detail.
|
||||
- Search debug rows for `System.*Exception`, `异常类型`, `调用堆栈`, `Object reference`, `KeyNotFoundException`, `ArgumentNullException`; promote only those with real exception context.
|
||||
- Search blocking rows for plain telemetry strings like `Player 不一致`, `Map不一致`, `存在相似action`, `ForceUpdate 玩家网络映射失败`, `安全写入失败`, `P2P message send failed`; demote them unless they also include a real exception object/stack.
|
||||
- Confirm `blocking/*.md` count equals `report_manifest.json.blockingReports.length`.
|
||||
|
||||
## Reporting Back
|
||||
|
||||
In the final response, provide:
|
||||
|
||||
- link to `index.md`.
|
||||
- final blocking/debug counts.
|
||||
- a short note that plain `LogSystem.LogError` diagnostics were kept in debug unless they wrapped an actual exception.
|
||||
- any limitations, such as rows that required detail pages but still had no full stack.
|
||||
|
||||
At the end of Chrome automation, close/finalize browser tabs according to the Chrome skill instructions.
|
||||
4
.codex/skills/th1-crashsight-daily/agents/openai.yaml
Normal file
4
.codex/skills/th1-crashsight-daily/agents/openai.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
interface:
|
||||
display_name: "TH1 CrashSight Daily"
|
||||
short_description: "Daily CrashSight triage for TH1 reports"
|
||||
default_prompt: "Use $th1-crashsight-daily to scan recent CrashSight errors and write blocking/debug reports."
|
||||
@ -114,15 +114,22 @@ namespace RuntimeData
|
||||
// 旧存档兼容:WaterType 字段不存在时默认为 Pangea
|
||||
if (!System.Enum.IsDefined(typeof(Logic.MapWaterType), WaterType))
|
||||
WaterType = Logic.MapWaterType.Pangea;
|
||||
MultiCivs ??= new List<MemberCiv>();
|
||||
PlayerSettlements ??= new List<PlayerSettlementInfo>();
|
||||
MatchLimits ??= new List<MatchLimitType>();
|
||||
RefreshMultiCivsDict();
|
||||
}
|
||||
|
||||
// 根据房间成员信息更新 mapconfig 信息
|
||||
public void UpdateLobbyMember(Dictionary<ulong, MemberInfo> memberInfos)
|
||||
public bool UpdateLobbyMember(Dictionary<ulong, MemberInfo> memberInfos)
|
||||
{
|
||||
if (memberInfos == null) return false;
|
||||
MultiCivs ??= new List<MemberCiv>();
|
||||
var changed = false;
|
||||
// 先剔除已离开 lobby 的成员,避免 MultiCivs 留下幽灵占位:
|
||||
// 旧版只 Add 不 Remove,会导致大厅 nP 跳号(1P/4P/5P/6P),
|
||||
// 以及开战时给离线幽灵创 PlayerData、占用 PlayerCount 名额、AI 补位变少。
|
||||
MultiCivs.RemoveAll(mc => !memberInfos.ContainsKey(mc.MemberId));
|
||||
changed |= MultiCivs.RemoveAll(mc => mc == null || !memberInfos.ContainsKey(mc.MemberId)) > 0;
|
||||
RefreshMultiCivsDict();
|
||||
foreach (var kv in memberInfos)
|
||||
{
|
||||
@ -132,22 +139,31 @@ namespace RuntimeData
|
||||
civ.CivId = 0;
|
||||
civ.ForceId = 0;
|
||||
MultiCivs.Add(civ);
|
||||
changed = true;
|
||||
}
|
||||
RefreshMultiCivsDict();
|
||||
return changed;
|
||||
}
|
||||
|
||||
// 内部刷新
|
||||
private void RefreshMultiCivsDict()
|
||||
{
|
||||
if (_memberCivs.Count == MultiCivs.Count) return;
|
||||
_memberCivs ??= new Dictionary<ulong, MemberCiv>();
|
||||
MultiCivs ??= new List<MemberCiv>();
|
||||
_memberCivs.Clear();
|
||||
foreach (var memberCiv in MultiCivs) _memberCivs[memberCiv.MemberId] = memberCiv;
|
||||
foreach (var memberCiv in MultiCivs)
|
||||
{
|
||||
if (memberCiv == null) continue;
|
||||
_memberCivs[memberCiv.MemberId] = memberCiv;
|
||||
}
|
||||
}
|
||||
|
||||
public MemberCiv GetMemberCiv(ulong memberId)
|
||||
{
|
||||
MultiCivs ??= new List<MemberCiv>();
|
||||
foreach (var memberCiv in MultiCivs)
|
||||
{
|
||||
if (memberCiv == null) continue;
|
||||
if (memberCiv.MemberId == memberId) return memberCiv;
|
||||
}
|
||||
|
||||
@ -155,22 +171,73 @@ namespace RuntimeData
|
||||
}
|
||||
|
||||
// 主从端一致的更新某一个成员信息
|
||||
public void UpdateMemberCiv(MemberCiv civ)
|
||||
public bool UpdateMemberCiv(MemberCiv civ)
|
||||
{
|
||||
if (civ == null) return false;
|
||||
if (LobbyManager.Instance.Lobby.IsInLobby() && !LobbyManager.Instance.Lobby.IsLobbyOwner())
|
||||
{
|
||||
GameNetSender.Instance.ChangeCiv(civ);
|
||||
return;
|
||||
var selfMemberId = LobbyManager.Instance.Lobby.GetSelfMemberId();
|
||||
if (civ.MemberId != selfMemberId)
|
||||
{
|
||||
LogSystem.LogError($"客户端只能修改自己的阵营: self={selfMemberId}, target={civ.MemberId}");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!GameNetSender.Instance.ChangeCiv(civ)) return false;
|
||||
ApplyMemberCivLocal(civ);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (LobbyManager.Instance.Lobby.IsInLobby() && !LobbyManager.Instance.Lobby.IsMemberInLobby(civ.MemberId))
|
||||
{
|
||||
LogSystem.LogError($"不能修改不在房间内的成员阵营: target={civ.MemberId}");
|
||||
return false;
|
||||
}
|
||||
|
||||
return ApplyMemberCivLocal(civ);
|
||||
}
|
||||
|
||||
private bool ApplyMemberCivLocal(MemberCiv civ)
|
||||
{
|
||||
MultiCivs ??= new List<MemberCiv>();
|
||||
foreach (var memberCiv in MultiCivs)
|
||||
{
|
||||
if (memberCiv == null) continue;
|
||||
if (memberCiv.MemberId != civ.MemberId) continue;
|
||||
if (memberCiv.CivId == civ.CivId && memberCiv.ForceId == civ.ForceId) return false;
|
||||
memberCiv.CivId = civ.CivId;
|
||||
memberCiv.ForceId = civ.ForceId;
|
||||
return;
|
||||
memberCiv.PlayerId = civ.PlayerId;
|
||||
RefreshMultiCivsDict();
|
||||
return true;
|
||||
}
|
||||
MultiCivs.Add(civ);
|
||||
|
||||
MultiCivs.Add(new MemberCiv
|
||||
{
|
||||
MemberId = civ.MemberId,
|
||||
CivId = civ.CivId,
|
||||
ForceId = civ.ForceId,
|
||||
PlayerId = civ.PlayerId
|
||||
});
|
||||
RefreshMultiCivsDict();
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool HasSameLobbyMembers(Dictionary<ulong, MemberInfo> memberInfos)
|
||||
{
|
||||
if (memberInfos == null) return false;
|
||||
MultiCivs ??= new List<MemberCiv>();
|
||||
if (MultiCivs.Count != memberInfos.Count) return false;
|
||||
|
||||
var seen = new HashSet<ulong>();
|
||||
foreach (var memberCiv in MultiCivs)
|
||||
{
|
||||
if (memberCiv == null) return false;
|
||||
if (!memberInfos.ContainsKey(memberCiv.MemberId)) return false;
|
||||
if (!seen.Add(memberCiv.MemberId)) return false;
|
||||
}
|
||||
|
||||
return seen.Count == memberInfos.Count;
|
||||
}
|
||||
|
||||
// 主从端一致的本地数据检测
|
||||
|
||||
@ -377,12 +377,18 @@ namespace Logic
|
||||
{
|
||||
if (LobbyManager.Instance.Lobby.IsLobbyOwner())
|
||||
{
|
||||
Main.Instance.MapConfig.UpdateLobbyMember(LobbyManager.Instance.Lobby.GetAllMemberInfo());
|
||||
if (Main.Instance.MapConfig.UpdateLobbyMember(LobbyManager.Instance.Lobby.GetAllMemberInfo()))
|
||||
Main.Instance.MapConfig.CheckMapConfigChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (LobbyManager.Instance.Lobby.GetAllMemberInfo().Count != Main.Instance.MapConfig.MultiCivs.Count)
|
||||
var memberInfos = LobbyManager.Instance.Lobby.GetAllMemberInfo();
|
||||
if (GameNetSender.Instance.NeedsLobbyDataFromHost()
|
||||
|| !Main.Instance.MapConfig.HasSameLobbyMembers(memberInfos))
|
||||
{
|
||||
GameNetSender.Instance.MarkLobbyDataSyncRequired();
|
||||
GameNetSender.Instance.RequestLobbyData();
|
||||
}
|
||||
}
|
||||
|
||||
if (_recordTime > 1f)
|
||||
|
||||
@ -350,8 +350,8 @@ namespace TH1_Logic.Steam
|
||||
}
|
||||
if (!LobbyManager.Instance.Lobby.IsLobbyOwner()) return;
|
||||
if (message.Civ == null) return;
|
||||
Main.Instance.MapConfig.UpdateMemberCiv(message.Civ);
|
||||
Main.Instance.MapConfig.CheckMapConfigChanged();
|
||||
if (Main.Instance.MapConfig.UpdateMemberCiv(message.Civ))
|
||||
Main.Instance.MapConfig.CheckMapConfigChanged();
|
||||
}
|
||||
|
||||
// 只有玩家会收到
|
||||
@ -365,6 +365,15 @@ namespace TH1_Logic.Steam
|
||||
if (LobbyManager.Instance.Lobby.IsLobbyOwner()) return;
|
||||
if (message.Config == null) return;
|
||||
Main.Instance.MapConfig = message.Config;
|
||||
if (Main.Instance.MapConfig.HasSameLobbyMembers(LobbyManager.Instance.Lobby.GetAllMemberInfo()))
|
||||
{
|
||||
GameNetSender.Instance.MarkLobbyDataSyncedFromHost();
|
||||
}
|
||||
else
|
||||
{
|
||||
GameNetSender.Instance.MarkLobbyDataSyncRequired();
|
||||
GameNetSender.Instance.RequestLobbyData();
|
||||
}
|
||||
EventManager.Publish(new UpdateUIOutsideMultiplayRoomSetting());
|
||||
}
|
||||
|
||||
@ -377,6 +386,8 @@ namespace TH1_Logic.Steam
|
||||
return;
|
||||
}
|
||||
if (!LobbyManager.Instance.Lobby.IsLobbyOwner()) return;
|
||||
if (Main.Instance.MapConfig.UpdateLobbyMember(LobbyManager.Instance.Lobby.GetAllMemberInfo()))
|
||||
Main.Instance.MapConfig.CheckMapConfigChanged();
|
||||
GameNetSender.Instance.SendLobbyData(Main.Instance.MapConfig, message.MemberId);
|
||||
}
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@ using Logic.Action;
|
||||
using Logic.AI;
|
||||
using Logic.CrashSight;
|
||||
using RuntimeData;
|
||||
using Steamworks;
|
||||
using TH1_Logic.Chat;
|
||||
using TH1_Logic.Core;
|
||||
using TH1_Logic.Net;
|
||||
@ -26,6 +27,7 @@ namespace TH1_Logic.Steam
|
||||
private const float RequestForceUpdateCooldown = 5f;
|
||||
private float _lastRequestLobbyDataTime = -RequestLobbyDataCooldown;
|
||||
private float _lastRequestForceUpdateTime = -RequestForceUpdateCooldown;
|
||||
private bool _needLobbyDataFromHost;
|
||||
|
||||
// 发送消息给房主
|
||||
public bool SendMessage(BaseMessage message)
|
||||
@ -194,17 +196,19 @@ namespace TH1_Logic.Steam
|
||||
}
|
||||
|
||||
// 修改阵营 (成员 => 房主)
|
||||
public void ChangeCiv(MemberCiv memberCiv)
|
||||
public bool ChangeCiv(MemberCiv memberCiv)
|
||||
{
|
||||
if (memberCiv == null)
|
||||
{
|
||||
LogSystem.LogError($"Get Self MemberCiv Error ");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
var data = new ChangeCivMessage();
|
||||
data.Civ = memberCiv;
|
||||
SendMessage(data);
|
||||
if (!SendMessage(data)) return false;
|
||||
MarkLobbyDataSyncRequired();
|
||||
return true;
|
||||
}
|
||||
|
||||
// 更新房间配置 (房主 => 所有成员)
|
||||
@ -217,15 +221,45 @@ namespace TH1_Logic.Steam
|
||||
}
|
||||
|
||||
// 请求更新房间配置 (单成员 => 房主)
|
||||
public void RequestLobbyData()
|
||||
public bool RequestLobbyData(bool force = false)
|
||||
{
|
||||
if (LobbyManager.Instance.Lobby.IsLobbyOwner()) return false;
|
||||
if (!LobbyManager.Instance.Lobby.IsInLobby()) return false;
|
||||
var hostId = LobbyManager.Instance.Lobby.GetLobbyOwnerId();
|
||||
if (hostId == 0 || !SimpleP2P.Instance.IsConnectedTo(new CSteamID(hostId))) return false;
|
||||
|
||||
var now = UnityEngine.Time.time;
|
||||
if (now - _lastRequestLobbyDataTime < RequestLobbyDataCooldown) return;
|
||||
if (!force && now - _lastRequestLobbyDataTime < RequestLobbyDataCooldown) return false;
|
||||
_lastRequestLobbyDataTime = now;
|
||||
|
||||
var data = new RequestLobbyDataMessage();
|
||||
data.MemberId = LobbyManager.Instance.Lobby.GetSelfMemberId();
|
||||
SendMessage(data);
|
||||
if (SendMessage(data)) return true;
|
||||
|
||||
_lastRequestLobbyDataTime = now - RequestLobbyDataCooldown + 0.2f;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void MarkLobbyDataSyncRequired()
|
||||
{
|
||||
_needLobbyDataFromHost = true;
|
||||
_lastRequestLobbyDataTime = -RequestLobbyDataCooldown;
|
||||
}
|
||||
|
||||
public void MarkLobbyDataSyncedFromHost()
|
||||
{
|
||||
_needLobbyDataFromHost = false;
|
||||
}
|
||||
|
||||
public void ClearLobbyDataSyncState()
|
||||
{
|
||||
_needLobbyDataFromHost = false;
|
||||
_lastRequestLobbyDataTime = -RequestLobbyDataCooldown;
|
||||
}
|
||||
|
||||
public bool NeedsLobbyDataFromHost()
|
||||
{
|
||||
return _needLobbyDataFromHost;
|
||||
}
|
||||
|
||||
// 更新房间配置 (房主 => 单成员)
|
||||
|
||||
@ -510,6 +510,7 @@ namespace TH1_Logic.Steam
|
||||
// 断开所有P2P连接
|
||||
SimpleP2P.Instance.DisconnectAll();
|
||||
SteamMatchmaking.LeaveLobby(CurrentLobby);
|
||||
GameNetSender.Instance.ClearLobbyDataSyncState();
|
||||
ResetLobbyState();
|
||||
OnLobbyLeftEvent?.Invoke(null);
|
||||
}
|
||||
@ -1019,6 +1020,15 @@ namespace TH1_Logic.Steam
|
||||
CheckIfKicked();
|
||||
OnLobbyReadyInternal();
|
||||
OnLobbyMembersChangedInternal();
|
||||
if (IsLobbyOwner())
|
||||
{
|
||||
GameNetSender.Instance.ClearLobbyDataSyncState();
|
||||
}
|
||||
else
|
||||
{
|
||||
GameNetSender.Instance.MarkLobbyDataSyncRequired();
|
||||
GameNetSender.Instance.RequestLobbyData(true);
|
||||
}
|
||||
|
||||
// 触发加入成功事件
|
||||
OnLobbyEnteredEvent?.Invoke(CurrentLobby);
|
||||
@ -1147,7 +1157,18 @@ namespace TH1_Logic.Steam
|
||||
// P2P事件处理
|
||||
private void OnP2PPeerConnected(CSteamID steamID)
|
||||
{
|
||||
if (IsLobbyOwner()) Main.Instance.GameLogic.OnConnectToOtherPlayer(steamID.m_SteamID);
|
||||
if (IsLobbyOwner())
|
||||
{
|
||||
Main.Instance.GameLogic.OnConnectToOtherPlayer(steamID.m_SteamID);
|
||||
if (Main.Instance.GameLogic.GetCurState() == GameState.Menu && Main.Instance.MapConfig != null)
|
||||
{
|
||||
if (Main.Instance.MapConfig.UpdateLobbyMember(GetAllMemberInfo()))
|
||||
Main.Instance.MapConfig.CheckMapConfigChanged();
|
||||
GameNetSender.Instance.SendLobbyData(Main.Instance.MapConfig, steamID.m_SteamID);
|
||||
}
|
||||
}
|
||||
else if (steamID.m_SteamID == GetLobbyOwnerId())
|
||||
GameNetSender.Instance.RequestLobbyData(true);
|
||||
LogSystem.LogInfo($"P2P connection established with: {steamID}");
|
||||
}
|
||||
|
||||
|
||||
@ -435,13 +435,20 @@ namespace TH1Renderer
|
||||
public void RenderUpdateUnitMap()
|
||||
{
|
||||
foreach (var unitData in Main.MapData.UnitMap.UnitList)
|
||||
{
|
||||
if (unitData == null)
|
||||
continue;
|
||||
if(!ROUnitMap.ContainsKey(unitData.Id))
|
||||
{
|
||||
//生成单位图像
|
||||
ROUnitMap[unitData.Id] = new UnitRenderer(_unitPrefab,_unitRenderMap,unitData.Id);
|
||||
var unitRenderer = new UnitRenderer(_unitPrefab,_unitRenderMap,unitData.Id);
|
||||
if (!unitRenderer.IsValid)
|
||||
continue;
|
||||
ROUnitMap[unitData.Id] = unitRenderer;
|
||||
//立刻更新每个unit的视觉
|
||||
ROUnitMap[unitData.Id].InstantUpdateUnit(true);
|
||||
unitRenderer.InstantUpdateUnit(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//当projectileMap出现新的对象时,新建对象
|
||||
@ -486,9 +493,13 @@ namespace TH1Renderer
|
||||
// 2) 补齐缺失:数据层有但 ROUnitMap 没有的
|
||||
foreach (var unitData in mapData.UnitMap.UnitList)
|
||||
{
|
||||
if (unitData == null)
|
||||
continue;
|
||||
if (!ROUnitMap.ContainsKey(unitData.Id))
|
||||
{
|
||||
ROUnitMap[unitData.Id] = new UnitRenderer(_unitPrefab, _unitRenderMap, unitData.Id);
|
||||
var unitRenderer = new UnitRenderer(_unitPrefab, _unitRenderMap, unitData.Id);
|
||||
if (unitRenderer.IsValid)
|
||||
ROUnitMap[unitData.Id] = unitRenderer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -62,6 +62,7 @@ public class UnitMono : MonoBehaviour
|
||||
|
||||
public void UpdateUnitDefense(float defenseBonus)
|
||||
{
|
||||
if (Defense == null || SuperDefense == null || InfoGroup == null) return;
|
||||
bool defense = Defense.activeSelf;
|
||||
bool superdefense = SuperDefense.activeSelf;
|
||||
bool noDefense = !defense && !superdefense;
|
||||
|
||||
@ -23,6 +23,42 @@ namespace TH1_Renderer
|
||||
private GameObject _ROUnit;
|
||||
private UnitMono _unitMono;
|
||||
|
||||
public bool IsValid => _ROUnit != null && _unitMono != null && _unitMono.SpriteRenderer != null && _unitData != null;
|
||||
|
||||
private bool TryRefreshUnitRefs(bool requirePlayer = false, bool requireGrid = false)
|
||||
{
|
||||
var mapData = Main.MapData;
|
||||
if (mapData == null || mapData.UnitMap == null)
|
||||
{
|
||||
_unitData = null;
|
||||
_playerData = null;
|
||||
_gridData = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mapData.UnitMap.GetUnitDataByUnitId(_unitId, out _unitData) || _unitData == null)
|
||||
{
|
||||
_unitData = null;
|
||||
_playerData = null;
|
||||
_gridData = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (requirePlayer && (!mapData.GetPlayerDataByUnitId(_unitId, out _playerData) || _playerData == null))
|
||||
{
|
||||
_playerData = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (requireGrid && (!mapData.GetGridDataByUnitId(_unitId, out _gridData) || _gridData == null))
|
||||
{
|
||||
_gridData = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------- 表现层RenderData ---------//
|
||||
public bool IsAttackHighlight = false;
|
||||
public bool IsSelectHighlight = false;
|
||||
@ -90,15 +126,32 @@ namespace TH1_Renderer
|
||||
public UnitRenderer(GameObject prefab,Transform father, uint uid)
|
||||
{
|
||||
_unitId = uid;
|
||||
Main.MapData.UnitMap.GetUnitDataByUnitId(uid,out _unitData);
|
||||
Main.MapData.GetPlayerDataByUnitId(uid, out _playerData);
|
||||
Main.MapData.GetGridDataByUnitId(uid,out _gridData);
|
||||
|
||||
AnimManager = new UnitAnimManager();
|
||||
|
||||
Vector3 tpos = Table.Instance.GridToWorld(_gridData,"isUnit");
|
||||
var table = Table.Instance;
|
||||
if (!TryRefreshUnitRefs(requirePlayer: true, requireGrid: true) || prefab == null || father == null || table == null)
|
||||
{
|
||||
_unitData = null;
|
||||
_playerData = null;
|
||||
_gridData = null;
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 tpos = table.GridToWorld(_gridData,"isUnit");
|
||||
_ROUnit = GameObject.Instantiate(prefab, tpos, Quaternion.identity, father);
|
||||
_unitMono = _ROUnit?.GetComponent<UnitMono>();
|
||||
_unitMono = _ROUnit != null ? _ROUnit.GetComponent<UnitMono>() : null;
|
||||
if (_unitMono == null || _unitMono.SpriteRenderer == null)
|
||||
{
|
||||
if (_ROUnit != null)
|
||||
GameObject.Destroy(_ROUnit);
|
||||
_ROUnit = null;
|
||||
_unitMono = null;
|
||||
_unitData = null;
|
||||
_playerData = null;
|
||||
_gridData = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// 初始化 StatusArea
|
||||
if (_unitMono?.StatusAreaContainer != null && _unitMono?.StatusIconPrefab != null)
|
||||
@ -121,11 +174,17 @@ namespace TH1_Renderer
|
||||
// 清理状态区域
|
||||
_statusArea?.ClearAllStatus();
|
||||
|
||||
GameObject.Destroy(_ROUnit.gameObject);
|
||||
if (_ROUnit != null)
|
||||
GameObject.Destroy(_ROUnit.gameObject);
|
||||
|
||||
if(MapRenderer.Instance.ROUnitMap.TryGetValue(_unitId,out var _))
|
||||
MapRenderer.Instance.ROUnitMap.Remove(_unitId);
|
||||
var mapRenderer = MapRenderer.Instance;
|
||||
if (mapRenderer?.ROUnitMap != null)
|
||||
mapRenderer.ROUnitMap.Remove(_unitId);
|
||||
_unitData = null;
|
||||
_playerData = null;
|
||||
_gridData = null;
|
||||
_unitMono = null;
|
||||
_statusArea = null;
|
||||
}
|
||||
|
||||
#region [-------------------- Status Area Management --------------------]
|
||||
@ -190,17 +249,20 @@ namespace TH1_Renderer
|
||||
|
||||
public void InstantDisappear()
|
||||
{
|
||||
if (_ROUnit == null) return;
|
||||
_ROUnit.SetActive(false);
|
||||
}
|
||||
|
||||
public void InstantShow()
|
||||
{
|
||||
if (_ROUnit == null) return;
|
||||
_ROUnit.SetActive(true);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
AnimManager?.Update(_unitMono);
|
||||
if (_unitMono != null)
|
||||
AnimManager?.Update(_unitMono);
|
||||
UpdateShenlanTint();
|
||||
}
|
||||
|
||||
@ -208,7 +270,7 @@ namespace TH1_Renderer
|
||||
// 只改 RGB,保留 alpha(HideState 用 alpha 控制半透明)。
|
||||
private void UpdateShenlanTint()
|
||||
{
|
||||
if (_unitMono?.SpriteRenderer == null) return;
|
||||
if (_unitMono == null || _unitMono.SpriteRenderer == null) return;
|
||||
if (_unitData == null || !_unitData.IsAlive())
|
||||
{
|
||||
if (_shenlanTinted)
|
||||
@ -240,13 +302,14 @@ namespace TH1_Renderer
|
||||
|
||||
public void RenderUpdateUnitDefense()
|
||||
{
|
||||
if (_unitData == null || !_unitData.IsAlive()) return;
|
||||
_unitMono.UpdateUnitDefense(_unitData.GetDefenseMultiplicationParamOnlyForDefenseShow(Main.MapData));
|
||||
var mapData = Main.MapData;
|
||||
if (_unitMono == null || mapData == null || !TryRefreshUnitRefs() || !_unitData.IsAlive()) return;
|
||||
_unitMono.UpdateUnitDefense(_unitData.GetDefenseMultiplicationParamOnlyForDefenseShow(mapData));
|
||||
}
|
||||
|
||||
public void RenderUpdateUnitImage()
|
||||
{
|
||||
if (_unitData == null ) return;
|
||||
if (_unitMono == null || Main.MapData == null || !TryRefreshUnitRefs()) return;
|
||||
|
||||
RenderUpdateUnitInfo();
|
||||
|
||||
@ -269,6 +332,7 @@ namespace TH1_Renderer
|
||||
//如果unit死了,不能直接die!!要等动画那边主动凋起才可以die
|
||||
public bool InstantUpdateUnit(bool showoff)
|
||||
{
|
||||
if (_unitMono == null || !TryRefreshUnitRefs()) return false;
|
||||
//如果要做显隐更新,先判断显隐,显的情况下,再更新image
|
||||
//如果不做显隐更新,直接更新image
|
||||
if ((showoff && RenderUpdateUnitShowOff())
|
||||
@ -281,7 +345,7 @@ namespace TH1_Renderer
|
||||
//瞬间更新unit的 die的情况
|
||||
public bool InstantUpdateTryDie()
|
||||
{
|
||||
if (_unitData == null || !_unitData.IsAlive())
|
||||
if (!TryRefreshUnitRefs() || !_unitData.IsAlive())
|
||||
{
|
||||
Die();
|
||||
return true;
|
||||
@ -298,6 +362,7 @@ namespace TH1_Renderer
|
||||
|
||||
public void RenderUpdateUnitInfo()
|
||||
{
|
||||
if (_unitMono == null || !TryRefreshUnitRefs() || Table.Instance?.UnitTypeDataAssets == null) return;
|
||||
if (!_unitMono?.HealthText || !_unitMono?.UnitInfoBG) return;
|
||||
_unitMono.HealthText.text = _unitData.Health.ToString();
|
||||
//处理血量的颜色。如果血量<一半且<5,那么赋予红色,否则白色
|
||||
@ -306,30 +371,33 @@ namespace TH1_Renderer
|
||||
else
|
||||
_unitMono.HealthText.color = Color.white;
|
||||
|
||||
Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(_unitData.UnitFullType, out var unitInfo);
|
||||
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(_unitData.UnitFullType, out var unitInfo))
|
||||
return;
|
||||
var chessType = unitInfo.ChessType;
|
||||
if (chessType == ChessType.None)
|
||||
{
|
||||
if(Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(_unitData.CarryUnitFullType, out var carryUnitInfo))
|
||||
chessType = carryUnitInfo.ChessType;
|
||||
}
|
||||
if (chessType != ChessType.None)
|
||||
if (chessType != ChessType.None && _unitMono.ChessImg != null)
|
||||
{
|
||||
Table.Instance.UnitTypeDataAssets.GetChessTypeInfo(chessType ,out var chessInfo);
|
||||
_unitMono.ChessImg.sprite = chessInfo.ChessSprite;
|
||||
if (Table.Instance.UnitTypeDataAssets.GetChessTypeInfo(chessType ,out var chessInfo))
|
||||
_unitMono.ChessImg.sprite = chessInfo.ChessSprite;
|
||||
}
|
||||
|
||||
|
||||
//根据敌我情况更新infoBG的颜色
|
||||
//_unitInfoBGImg.sprite = (Main.MapData.SameUnion(_playerData.Id , Main.MapData.PlayerMap.SelfPlayerId)) ? ResourceCache.Instance.SpriteCache.UnitInfoSelf :
|
||||
if (Main.MapData == null) return;
|
||||
if (Main.MapData.PlayerMap == null) return;
|
||||
if (!Main.MapData.GetPlayerDataByUnitId(_unitData.Id, out var playerData)) return;
|
||||
var col = _unitMono.UnitBGBlue;
|
||||
if (playerData.Id != Main.MapData.PlayerMap.SelfPlayerId)
|
||||
col =(Main.MapData.SameUnion(playerData.Id, Main.MapData.PlayerMap.SelfPlayerId))
|
||||
? _unitMono.UnitBGGreen
|
||||
: _unitMono.UnitBGRed;
|
||||
_unitMono.ChessBG.color = col;
|
||||
if (_unitMono.ChessBG != null)
|
||||
_unitMono.ChessBG.color = col;
|
||||
_unitMono.UnitInfoBG.color = col;
|
||||
|
||||
|
||||
@ -358,7 +426,9 @@ namespace TH1_Renderer
|
||||
}
|
||||
|
||||
//更改兵种显示文字
|
||||
if(Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(_unitData.UnitType,_unitData.GiantType,_unitData.UnitLevel,out var info))
|
||||
if(_unitMono.UnitInfoName != null
|
||||
&& MultilingualManager.Instance != null
|
||||
&& Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(_unitData.UnitType,_unitData.GiantType,_unitData.UnitLevel,out var info))
|
||||
MultilingualManager.Instance.SetUIText(_unitMono.UnitInfoName,info.Name);
|
||||
|
||||
SyncStatusWithUnitSkills();
|
||||
@ -366,6 +436,7 @@ namespace TH1_Renderer
|
||||
|
||||
public void RenderUpdateDebug()
|
||||
{
|
||||
if (_unitMono == null || !TryRefreshUnitRefs(requirePlayer: true) || _unitMono.RODebugText == null || _unitMono.DebugText == null || Main.MapData?.PlayerMap?.SelfPlayerData == null) return;
|
||||
if (DebugCenter.Instance.DebugMode)
|
||||
{
|
||||
if(!_unitMono.RODebugText.activeSelf)
|
||||
@ -383,20 +454,24 @@ namespace TH1_Renderer
|
||||
//如果不是我方单位,显示军团及unit的战略
|
||||
_unitMono.DebugText.text += $"Lid={_unitData.LegionId}\n";
|
||||
if(!Main.MapData.CheckUnitIdBelongPlayerId(_unitData.Id,Main.MapData.PlayerMap.SelfPlayerData.Id))
|
||||
if (MainEditor.Instance.Data != null)
|
||||
{
|
||||
var mainEditor = MainEditor.Instance;
|
||||
if (mainEditor?.Data != null)
|
||||
{
|
||||
MainEditor.Instance.GetUnitStrategy(_unitId, _unitData.LegionId, _playerData.Id, out var st,
|
||||
mainEditor.GetUnitStrategy(_unitId, _unitData.LegionId, _playerData.Id, out var st,
|
||||
out var tar, out var type);
|
||||
_unitMono.DebugText.text += $"ST:{st} TAR:{tar} TYPE:{type}";
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool RenderUpdateUnitShowOff()
|
||||
{
|
||||
if (_unitData == null || _unitMono == null)
|
||||
var mapData = Main.MapData;
|
||||
if (_unitMono == null || mapData == null || mapData.PlayerMap == null || mapData.PlayerMap.SelfPlayerData == null || !TryRefreshUnitRefs())
|
||||
return false;
|
||||
bool ret = _unitData.InMainSight();
|
||||
//如果在视野内但是敌方隐身单位,对当前玩家不可见
|
||||
if (ret && _unitData.IsHideAndCantSee(Main.MapData, Main.MapData.PlayerMap.SelfPlayerData))
|
||||
if (ret && _unitData.IsHideAndCantSee(mapData, mapData.PlayerMap.SelfPlayerData))
|
||||
ret = false;
|
||||
//由隐转显时,先把 transform 同步到当前 grid,避免显示在过期位置
|
||||
//(敌方隐身单位全程 SetActive(false),RenderUpdateUnitPosition 没机会跑)
|
||||
@ -407,10 +482,14 @@ namespace TH1_Renderer
|
||||
}
|
||||
public void RenderUpdateUnitGlow()
|
||||
{
|
||||
var player = _unitData.Player(Main.MapData);
|
||||
var mapData = Main.MapData;
|
||||
var table = Table.Instance;
|
||||
if (_unitMono == null || _unitMono.SpriteRenderer == null || mapData == null || table == null || table.UnitTypeDataAssets == null || ResourceCache.Instance?.MatCache == null || !TryRefreshUnitRefs())
|
||||
return;
|
||||
var player = _unitData.Player(mapData);
|
||||
if (player == null) return;
|
||||
Sprite sprite;
|
||||
if (!Table.Instance.UnitTypeDataAssets.GetUnitSprite(Main.MapData, _unitData, out sprite))
|
||||
if (!table.UnitTypeDataAssets.GetUnitSprite(mapData, _unitData, out sprite))
|
||||
return;
|
||||
_unitMono.SpriteRenderer.sprite = sprite;
|
||||
_unitMono.SpriteRenderer.material = ResourceCache.Instance.MatCache.TH1URPShaders_Default;
|
||||
@ -419,10 +498,11 @@ namespace TH1_Renderer
|
||||
//首先处理玩家(判断是否置灰或者高亮)
|
||||
if (player.IsSelfPlayer())
|
||||
{
|
||||
var mapRenderer = MapRenderer.Instance;
|
||||
//如果MP>0 或者周围有可以攻击的目标,或者可以移动的目标,或者说可以占领城市
|
||||
if (_unitData.GetActionPoint(ActionPointType.Move) > 0
|
||||
|| MapRenderer.Instance.CheckUnitHasMoveAttackTarget(_unitId)
|
||||
|| MapRenderer.Instance.CheckUnitHasSpecialUnitActionTarget(_unitId))
|
||||
|| (mapRenderer != null && mapRenderer.CheckUnitHasMoveAttackTarget(_unitId))
|
||||
|| (mapRenderer != null && mapRenderer.CheckUnitHasSpecialUnitActionTarget(_unitId)))
|
||||
{
|
||||
_unitMono.SpriteRenderer.material = ResourceCache.Instance.MatCache.TH1URPShaders_Sprite_Glow;
|
||||
_isGlow = true;
|
||||
@ -435,14 +515,14 @@ namespace TH1_Renderer
|
||||
else
|
||||
{
|
||||
//如果是正在行动的AI
|
||||
if (Main.MapData.CurPlayer == player)
|
||||
if (mapData.CurPlayer == player)
|
||||
{
|
||||
if(_unitData.GetActionPoint(ActionPointType.Move) == 0 && _unitData.GetActionPoint(ActionPointType.Capture) == 0 && _unitData.GetActionPoint(ActionPointType.Attack) == 0 && _unitData.GetActionPoint(ActionPointType.Move) == 0)
|
||||
_unitMono.SpriteRenderer.material = ResourceCache.Instance.MatCache.TH1URPShaders_Sprite_WhiteOverlay;
|
||||
}
|
||||
else
|
||||
//如果是还没行动的AI
|
||||
if(Main.MapData.GetPlayerHasActedInBigTurn(player))
|
||||
if(mapData.GetPlayerHasActedInBigTurn(player))
|
||||
{
|
||||
//啥都不做
|
||||
}
|
||||
@ -459,8 +539,12 @@ namespace TH1_Renderer
|
||||
|
||||
public void RenderUpdateHideState()
|
||||
{
|
||||
bool hideState = _unitData.IsHideState(Main.MapData);
|
||||
bool isSelfOrAlly = Main.MapData.SameUnion(_playerData.Id, Main.MapData.PlayerMap.SelfPlayerId);
|
||||
var mapData = Main.MapData;
|
||||
if (_unitMono == null || _unitMono.SpriteRenderer == null || mapData == null || mapData.PlayerMap == null || !TryRefreshUnitRefs(requirePlayer: true))
|
||||
return;
|
||||
|
||||
bool hideState = _unitData.IsHideState(mapData);
|
||||
bool isSelfOrAlly = mapData.SameUnion(_playerData.Id, mapData.PlayerMap.SelfPlayerId);
|
||||
|
||||
// 状态未变时的处理:确保显示状态正确
|
||||
if (hideState == _isHideState)
|
||||
@ -516,22 +600,23 @@ namespace TH1_Renderer
|
||||
|
||||
public void RenderUpdateHideAround()
|
||||
{
|
||||
if (_unitMono.HideAround == null) return;
|
||||
var mapData = Main.MapData;
|
||||
if (_unitMono == null || _unitMono.HideAround == null || mapData?.GridMap == null || !TryRefreshUnitRefs(requirePlayer: true)) return;
|
||||
bool show = false;
|
||||
//只对当前玩家自己的单位显示
|
||||
var curGrid = _unitData.Grid(Main.MapData);
|
||||
var curGrid = _unitData.Grid(mapData);
|
||||
if (_playerData != null && _playerData.IsSelfPlayer() && curGrid != null)
|
||||
{
|
||||
_aroundBuf ??= new List<GridData>();
|
||||
_aroundBuf.Clear();
|
||||
Main.MapData.GridMap.GetAroundGridData(1, 1, curGrid, _aroundBuf);
|
||||
mapData.GridMap.GetAroundGridData(1, 1, curGrid, _aroundBuf);
|
||||
foreach (var around in _aroundBuf)
|
||||
{
|
||||
if (around == curGrid) continue;
|
||||
if (!around.RealUnit(Main.MapData, out var nearUnit)) continue;
|
||||
if (!nearUnit.IsHideState(Main.MapData)) continue;
|
||||
if (!around.RealUnit(mapData, out var nearUnit)) continue;
|
||||
if (!nearUnit.IsHideState(mapData)) continue;
|
||||
//排除自己的单位和同盟单位
|
||||
if (Main.MapData.SameUnionByUnitId(_unitData.Id, nearUnit.Id)) continue;
|
||||
if (mapData.SameUnionByUnitId(_unitData.Id, nearUnit.Id)) continue;
|
||||
show = true;
|
||||
break;
|
||||
}
|
||||
@ -559,9 +644,13 @@ namespace TH1_Renderer
|
||||
|
||||
public void RenderUpdataHighlight()
|
||||
{
|
||||
_unitMono.AttackHighlight.SetActive(IsAttackHighlight);
|
||||
_unitMono.SelectHighlight.SetActive(IsSelectHighlight);
|
||||
_unitMono.AllyHighlight.SetActive(IsAllyHighlight);
|
||||
if (_unitMono == null) return;
|
||||
if (_unitMono.AttackHighlight != null)
|
||||
_unitMono.AttackHighlight.SetActive(IsAttackHighlight);
|
||||
if (_unitMono.SelectHighlight != null)
|
||||
_unitMono.SelectHighlight.SetActive(IsSelectHighlight);
|
||||
if (_unitMono.AllyHighlight != null)
|
||||
_unitMono.AllyHighlight.SetActive(IsAllyHighlight);
|
||||
}
|
||||
|
||||
public void SetSelectHighlight(bool v)
|
||||
@ -569,8 +658,10 @@ namespace TH1_Renderer
|
||||
if (IsSelectHighlight == v)
|
||||
return;
|
||||
IsSelectHighlight = v;
|
||||
MapRenderer.Instance.HighlightUnitIdSet.Add(_unitId);
|
||||
MapRenderer.Instance.HighlightUnitIdSetRenderMark = true;
|
||||
var mapRenderer = MapRenderer.Instance;
|
||||
if (mapRenderer?.HighlightUnitIdSet == null) return;
|
||||
mapRenderer.HighlightUnitIdSet.Add(_unitId);
|
||||
mapRenderer.HighlightUnitIdSetRenderMark = true;
|
||||
}
|
||||
|
||||
public void SetAttackHighlight(bool v)
|
||||
@ -578,8 +669,10 @@ namespace TH1_Renderer
|
||||
if (IsAttackHighlight == v)
|
||||
return;
|
||||
IsAttackHighlight = v;
|
||||
MapRenderer.Instance.HighlightUnitIdSet.Add(_unitId);
|
||||
MapRenderer.Instance.HighlightUnitIdSetRenderMark = true;
|
||||
var mapRenderer = MapRenderer.Instance;
|
||||
if (mapRenderer?.HighlightUnitIdSet == null) return;
|
||||
mapRenderer.HighlightUnitIdSet.Add(_unitId);
|
||||
mapRenderer.HighlightUnitIdSetRenderMark = true;
|
||||
}
|
||||
|
||||
public void SetAllyHighlight(bool v)
|
||||
@ -587,13 +680,20 @@ namespace TH1_Renderer
|
||||
if (IsAllyHighlight == v)
|
||||
return;
|
||||
IsAllyHighlight = v;
|
||||
MapRenderer.Instance.HighlightUnitIdSet.Add(_unitId);
|
||||
MapRenderer.Instance.HighlightUnitIdSetRenderMark = true;
|
||||
var mapRenderer = MapRenderer.Instance;
|
||||
if (mapRenderer?.HighlightUnitIdSet == null) return;
|
||||
mapRenderer.HighlightUnitIdSet.Add(_unitId);
|
||||
mapRenderer.HighlightUnitIdSetRenderMark = true;
|
||||
}
|
||||
|
||||
public void RenderUpdateUnitSprite()
|
||||
{
|
||||
if (!Table.Instance.UnitTypeDataAssets.GetUnitSprite(Main.MapData, _unitData, out var sprite))
|
||||
var mapData = Main.MapData;
|
||||
var table = Table.Instance;
|
||||
if (_unitMono == null || _unitMono.SpriteRenderer == null || mapData == null || table == null || table.UnitTypeDataAssets == null || !TryRefreshUnitRefs())
|
||||
return;
|
||||
|
||||
if (!table.UnitTypeDataAssets.GetUnitSprite(mapData, _unitData, out var sprite) || sprite == null)
|
||||
return;
|
||||
_unitMono.SpriteRenderer.sprite = sprite;
|
||||
//RenderUpdateUnitSpecialSprite();
|
||||
@ -603,14 +703,19 @@ namespace TH1_Renderer
|
||||
|
||||
public void RenderUpdateUnitPosition()
|
||||
{
|
||||
var t = _unitData.Grid(Main.MapData)?.Pos;
|
||||
var mapData = Main.MapData;
|
||||
var table = Table.Instance;
|
||||
if (_unitMono == null || mapData == null || table == null || !TryRefreshUnitRefs(requireGrid: true))
|
||||
return;
|
||||
|
||||
var t = _unitData.Grid(mapData)?.Pos;
|
||||
if (t == null) return;
|
||||
_unitMono.transform.position = Table.Instance.GridPosToWorld(new Vector2Int(t.X,t.Y),"isUnit");
|
||||
_unitMono.transform.position = table.GridPosToWorld(new Vector2Int(t.X,t.Y),"isUnit");
|
||||
}
|
||||
|
||||
public Vector3 GetPosition()
|
||||
{
|
||||
return _ROUnit.transform.position;
|
||||
return _ROUnit != null ? _ROUnit.transform.position : Vector3.zero;
|
||||
}
|
||||
|
||||
public bool isGlow()
|
||||
@ -619,4 +724,4 @@ namespace TH1_Renderer
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Logic.Multilingual;
|
||||
using RuntimeData;
|
||||
using TH1_Logic.Core;
|
||||
using TH1_Logic.Net;
|
||||
using TH1_Logic.Steam;
|
||||
@ -113,16 +114,22 @@ public class UIOutsideMultiplayMemberRowMono : MonoBehaviour
|
||||
|
||||
}
|
||||
|
||||
public void UpdatePlayerInfoData(CivEnum civ,ForceEnum force)
|
||||
public bool UpdatePlayerInfoData(CivEnum civ,ForceEnum force)
|
||||
{
|
||||
//修改mapConfig
|
||||
var t = Main.Instance.MapConfig.GetMemberCiv(_lobby.GetSelfMemberId());
|
||||
if(t != null){
|
||||
t.CivId = Table.Instance.TransCivEnumToCivId(civ);
|
||||
t.ForceId = Table.Instance.TransForceEnumToForceId(force);
|
||||
Main.Instance.MapConfig.UpdateMemberCiv(t);
|
||||
Main.Instance.MapConfig.CheckMapConfigChanged();
|
||||
}
|
||||
var selfMemberId = _lobby.GetSelfMemberId();
|
||||
var t = Main.Instance.MapConfig.GetMemberCiv(selfMemberId);
|
||||
if (t == null) return false;
|
||||
|
||||
var next = new MemberCiv
|
||||
{
|
||||
MemberId = selfMemberId,
|
||||
CivId = Table.Instance.TransCivEnumToCivId(civ),
|
||||
ForceId = Table.Instance.TransForceEnumToForceId(force)
|
||||
};
|
||||
|
||||
var accepted = Main.Instance.MapConfig.UpdateMemberCiv(next);
|
||||
if (accepted) Main.Instance.MapConfig.CheckMapConfigChanged();
|
||||
return accepted;
|
||||
}
|
||||
|
||||
public void OnClickForces()
|
||||
@ -132,23 +139,23 @@ public class UIOutsideMultiplayMemberRowMono : MonoBehaviour
|
||||
_forceNameOverride = null;
|
||||
if (_civ == CivEnum.Egyptian)
|
||||
{
|
||||
UpdatePlayerInfoData(CivEnum.French,ForceEnum.Kaguya);
|
||||
UpdatePlayerInfoView(CivEnum.French,ForceEnum.Kaguya);
|
||||
if (UpdatePlayerInfoData(CivEnum.French,ForceEnum.Kaguya))
|
||||
UpdatePlayerInfoView(CivEnum.French,ForceEnum.Kaguya);
|
||||
}
|
||||
else if (_civ == CivEnum.French)
|
||||
{
|
||||
UpdatePlayerInfoData(CivEnum.Germany,ForceEnum.Kanako);
|
||||
UpdatePlayerInfoView(CivEnum.Germany,ForceEnum.Kanako);
|
||||
if (UpdatePlayerInfoData(CivEnum.Germany,ForceEnum.Kanako))
|
||||
UpdatePlayerInfoView(CivEnum.Germany,ForceEnum.Kanako);
|
||||
}
|
||||
else if (_civ == CivEnum.Germany)
|
||||
{
|
||||
UpdatePlayerInfoData(CivEnum.Indian,ForceEnum.Satori);
|
||||
UpdatePlayerInfoView(CivEnum.Indian,ForceEnum.Satori);
|
||||
if (UpdatePlayerInfoData(CivEnum.Indian,ForceEnum.Satori))
|
||||
UpdatePlayerInfoView(CivEnum.Indian,ForceEnum.Satori);
|
||||
}
|
||||
else if (_civ == CivEnum.Indian)
|
||||
{
|
||||
UpdatePlayerInfoData(CivEnum.Egyptian,ForceEnum.Remilia);
|
||||
UpdatePlayerInfoView(CivEnum.Egyptian,ForceEnum.Remilia);
|
||||
if (UpdatePlayerInfoData(CivEnum.Egyptian,ForceEnum.Remilia))
|
||||
UpdatePlayerInfoView(CivEnum.Egyptian,ForceEnum.Remilia);
|
||||
}
|
||||
}
|
||||
void Start()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user