Decompiled source of FlagSurvival v0.1.2
plugins/FlagSurvival.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Peak.Afflictions; using Photon.Pun; using Photon.Realtime; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.InputSystem.UI; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.UI; using Zorro.Core; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("FlagSurvival")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("FlagSurvival")] [assembly: AssemblyTitle("FlagSurvival")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace FlagSurvival { [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.sol.peak.flagsurvival.characteriddiag", "Character ID Diag", "1.0.0")] public class FlagCharacterIdDiagPlugin : BaseUnityPlugin { private void Awake() { ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogInfo((object)"[CharIdDiag] F10 → 본 캐릭터 GameObject 진단"); } } private void Update() { try { if (Keyboard.current != null && ((ButtonControl)Keyboard.current.f10Key).wasPressedThisFrame) { DumpCharacter(); } } catch { } } private void DumpCharacter() { //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null) { ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogWarning((object)"[CharIdDiag] Character.localCharacter == null"); } return; } ManualLogSource log2 = FlagSurvivalPlugin.Log; if (log2 != null) { log2.LogWarning((object)"===== F10 CHARACTER ID DIAG START ====="); } ManualLogSource log3 = FlagSurvivalPlugin.Log; if (log3 != null) { log3.LogWarning((object)"[CharIdDiag] === 본 캐릭터 GameObject ==="); } ManualLogSource log4 = FlagSurvivalPlugin.Log; if (log4 != null) { log4.LogWarning((object)("[CharIdDiag] Name: '" + ((Object)((Component)localCharacter).gameObject).name + "'")); } ManualLogSource log5 = FlagSurvivalPlugin.Log; if (log5 != null) { log5.LogWarning((object)$"[CharIdDiag] InstanceID: {((Object)((Component)localCharacter).gameObject).GetInstanceID()}"); } ManualLogSource log6 = FlagSurvivalPlugin.Log; if (log6 != null) { log6.LogWarning((object)$"[CharIdDiag] Active(self/hier): {((Component)localCharacter).gameObject.activeSelf}/{((Component)localCharacter).gameObject.activeInHierarchy}"); } Vector3 position = ((Component)localCharacter).transform.position; ManualLogSource log7 = FlagSurvivalPlugin.Log; if (log7 != null) { log7.LogWarning((object)$"[CharIdDiag] Position: ({position.x:F2}, {position.y:F2}, {position.z:F2})"); } ManualLogSource log8 = FlagSurvivalPlugin.Log; if (log8 != null) { log8.LogWarning((object)$"[CharIdDiag] Layer: {LayerMask.LayerToName(((Component)localCharacter).gameObject.layer)} ({((Component)localCharacter).gameObject.layer})"); } ManualLogSource log9 = FlagSurvivalPlugin.Log; if (log9 != null) { log9.LogWarning((object)("[CharIdDiag] Tag: '" + ((Component)localCharacter).gameObject.tag + "'")); } try { ManualLogSource log10 = FlagSurvivalPlugin.Log; if (log10 != null) { log10.LogWarning((object)("[CharIdDiag] PhotonViewID: " + (((Object)(object)((MonoBehaviourPun)localCharacter).photonView != (Object)null) ? ((MonoBehaviourPun)localCharacter).photonView.ViewID.ToString() : "null"))); } ManualLogSource log11 = FlagSurvivalPlugin.Log; if (log11 != null) { log11.LogWarning((object)$"[CharIdDiag] IsLocal: {localCharacter.IsLocal}"); } } catch (Exception ex) { ManualLogSource log12 = FlagSurvivalPlugin.Log; if (log12 != null) { log12.LogError((object)("[CharIdDiag] Photon 진단 예외: " + ex.Message)); } } ManualLogSource log13 = FlagSurvivalPlugin.Log; if (log13 != null) { log13.LogWarning((object)"[CharIdDiag] === 부모 체인 (root까지) ==="); } Transform parent = ((Component)localCharacter).transform.parent; int num = 0; while ((Object)(object)parent != (Object)null && num < 10) { ManualLogSource log14 = FlagSurvivalPlugin.Log; if (log14 != null) { log14.LogInfo((object)$"[CharIdDiag] parent[{num}]: '{((Object)parent).name}'"); } parent = parent.parent; num++; } if (num == 0) { ManualLogSource log15 = FlagSurvivalPlugin.Log; if (log15 != null) { log15.LogInfo((object)"[CharIdDiag] (root GameObject - 부모 없음)"); } } ManualLogSource log16 = FlagSurvivalPlugin.Log; if (log16 != null) { log16.LogWarning((object)"[CharIdDiag] === 자식 hierarchy (depth ≤ 3) ==="); } DumpChildren(((Component)localCharacter).transform, 0, 3); ManualLogSource log17 = FlagSurvivalPlugin.Log; if (log17 != null) { log17.LogWarning((object)"[CharIdDiag] === 본 캐릭터 컴포넌트 ==="); } Component[] components = ((Component)localCharacter).gameObject.GetComponents<Component>(); foreach (Component val in components) { if (!((Object)(object)val == (Object)null)) { ManualLogSource log18 = FlagSurvivalPlugin.Log; if (log18 != null) { log18.LogInfo((object)("[CharIdDiag] - " + ((object)val).GetType().Name)); } } } ManualLogSource log19 = FlagSurvivalPlugin.Log; if (log19 != null) { log19.LogWarning((object)"[CharIdDiag] === local.refs 진단 ==="); } try { if (localCharacter.refs != null) { FieldInfo[] fields = ((object)localCharacter.refs).GetType().GetFields(); foreach (FieldInfo fieldInfo in fields) { try { object value = fieldInfo.GetValue(localCharacter.refs); if (value != null) { GameObject val2 = (GameObject)((value is GameObject) ? value : null); string text; if (val2 != null) { text = $"GameObject '{((Object)val2).name}' (active={val2.activeInHierarchy})"; } else { Component val3 = (Component)((value is Component) ? value : null); text = ((val3 == null) ? value.GetType().Name : $"{((object)val3).GetType().Name} on '{((Object)val3.gameObject).name}' (active={val3.gameObject.activeInHierarchy})"); } ManualLogSource log20 = FlagSurvivalPlugin.Log; if (log20 != null) { log20.LogInfo((object)("[CharIdDiag] refs." + fieldInfo.Name + " = " + text)); } } } catch { } } } } catch (Exception ex2) { ManualLogSource log21 = FlagSurvivalPlugin.Log; if (log21 != null) { log21.LogError((object)("[CharIdDiag] refs 진단 예외: " + ex2.Message)); } } ManualLogSource log22 = FlagSurvivalPlugin.Log; if (log22 != null) { log22.LogWarning((object)"===== F10 CHARACTER ID DIAG END ====="); } } private void DumpChildren(Transform parent, int depth, int maxDepth) { if (depth > maxDepth) { return; } for (int i = 0; i < parent.childCount; i++) { Transform child = parent.GetChild(i); string text = new string(' ', depth * 2); string text2 = (((Component)child).gameObject.activeSelf ? "✓" : "✗"); string text3 = ""; Component[] components = ((Component)child).GetComponents<Component>(); int num = 0; Component[] array = components; foreach (Component val in array) { if ((Object)(object)val == (Object)null || val is Transform) { continue; } num++; if (num <= 5) { if (text3.Length > 0) { text3 += ", "; } text3 += ((object)val).GetType().Name; } } if (num > 5) { text3 += $", +{num - 5}"; } ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogInfo((object)("[CharIdDiag] " + text + "[" + text2 + "] " + ((Object)child).name + " | " + text3)); } if (depth < maxDepth) { DumpChildren(child, depth + 1, maxDepth); } } } } public static class FlagCOOPHUD { private static readonly Dictionary<string, TextMeshProUGUI> _cachedColumnTmps = new Dictionary<string, TextMeshProUGUI>(); public static void BuildFixedHUDTexts(bool isKorean, out string leaderInfo, out string myDistText, out string myRankText, out string pointsText) { leaderInfo = ExtractCurrentBiomeColumn("Pct"); myDistText = ExtractCurrentBiomeColumn("Star"); string text = FlagSurvivalMulti.GetCurrentBiomeTitle() ?? ""; string text2 = FlagSurvivalMulti.GetCurrentBiome() ?? ""; if (isKorean) { if (!string.IsNullOrEmpty(text)) { myRankText = text; } else if (!string.IsNullOrEmpty(text2)) { myRankText = text2; } else { myRankText = "???"; } } else if (!string.IsNullOrEmpty(text2)) { myRankText = text2; } else if (!string.IsNullOrEmpty(text)) { myRankText = text; } else { myRankText = "???"; } pointsText = ExtractCurrentBiomeColumn("Count"); } public static string ExtractCurrentBiomeColumn(string suffix) { try { if (string.IsNullOrEmpty(suffix)) { return ""; } _cachedColumnTmps.TryGetValue(suffix, out var value); if ((Object)(object)value == (Object)null) { string text = "FlagSurvival_FlagCountText_" + suffix; TextMeshProUGUI[] array = Object.FindObjectsOfType<TextMeshProUGUI>(true); if (array == null) { return ""; } TextMeshProUGUI[] array2 = array; foreach (TextMeshProUGUI val in array2) { if (!((Object)(object)val == (Object)null) && ((Object)((Component)val).gameObject).name == text) { value = val; _cachedColumnTmps[suffix] = val; break; } } if ((Object)(object)value == (Object)null) { return ""; } } string text2 = ((TMP_Text)value).text; if (string.IsNullOrEmpty(text2)) { return ""; } int num = FlagSurvivalMulti.GetCurrentSegmentIndex(); if (num < 0) { return ""; } if (num > 4) { num = 4; } string[] array3 = text2.Split('\n'); if (num >= array3.Length) { return ""; } string text3 = array3[num]; if (text3.StartsWith("<voffset=")) { int num2 = text3.IndexOf('>'); if (num2 > 0 && num2 + 1 < text3.Length) { text3 = text3.Substring(num2 + 1); } } return text3; } catch (Exception ex) { ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogError((object)("[FlagCOOPHUD][v3] ExtractCurrentBiomeColumn(" + suffix + ") 예외: " + ex.Message)); } return ""; } } public static string ExtractScoreRow(string suffix, int rowIndex) { try { if (string.IsNullOrEmpty(suffix)) { return ""; } if (rowIndex < 0) { return ""; } _cachedColumnTmps.TryGetValue(suffix, out var value); if ((Object)(object)value == (Object)null) { string text = "FlagSurvival_FlagCountText_" + suffix; TextMeshProUGUI[] array = Object.FindObjectsOfType<TextMeshProUGUI>(true); if (array == null) { return ""; } TextMeshProUGUI[] array2 = array; foreach (TextMeshProUGUI val in array2) { if (!((Object)(object)val == (Object)null) && ((Object)((Component)val).gameObject).name == text) { value = val; _cachedColumnTmps[suffix] = val; break; } } if ((Object)(object)value == (Object)null) { return ""; } } string text2 = ((TMP_Text)value).text; if (string.IsNullOrEmpty(text2)) { return ""; } string[] array3 = text2.Split('\n'); if (rowIndex >= array3.Length) { return ""; } string text3 = array3[rowIndex]; if (text3.StartsWith("<voffset=")) { int num = text3.IndexOf('>'); if (num > 0 && num + 1 < text3.Length) { text3 = text3.Substring(num + 1); } } return text3; } catch (Exception ex) { ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogError((object)$"[FlagCOOPHUD][v4] ExtractScoreRow({suffix},{rowIndex}) 예외: {ex.Message}"); } return ""; } } public static int GetCoopLeaderboardRowCount() { try { _cachedColumnTmps.TryGetValue("ScoreName", out var value); if ((Object)(object)value == (Object)null) { ExtractScoreRow("ScoreName", 0); _cachedColumnTmps.TryGetValue("ScoreName", out value); if ((Object)(object)value == (Object)null) { return 0; } } string text = ((TMP_Text)value).text; if (string.IsNullOrEmpty(text)) { return 0; } return text.Split('\n').Length; } catch { return 0; } } public static bool BuildCoopLeaderboardRow(int rowIndex, bool isKorean, out string nick, out string scoreText) { nick = ""; scoreText = ""; try { string text = ExtractScoreRow("ScoreName", rowIndex); if (string.IsNullOrEmpty(text)) { return false; } nick = StripSizeTags(text); int num = ParseCountFromScoreCell(ExtractScoreRow("ScoreCount", rowIndex)); int num2 = SumAllScoreCounts(); int num3 = ((num2 > 0) ? Mathf.Clamp(Mathf.RoundToInt((float)num * 100f / (float)num2), 0, 100) : 0); string arg = (isKorean ? $"{num}개" : $"{num}ea"); scoreText = $"{arg} {num3}%"; return true; } catch (Exception ex) { ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogError((object)$"[FlagCOOPHUD][v5] BuildCoopLeaderboardRow({rowIndex}) 예외: {ex.Message}"); } return false; } } private static int ParseCountFromScoreCell(string countRaw) { if (string.IsNullOrEmpty(countRaw)) { return 0; } int num = countRaw.IndexOf('개'); if (!int.TryParse(((num > 0) ? countRaw.Substring(0, num) : countRaw).Trim(), out var result)) { return 0; } return result; } private static int SumAllScoreCounts() { try { _cachedColumnTmps.TryGetValue("ScoreCount", out var value); if ((Object)(object)value == (Object)null) { ExtractScoreRow("ScoreCount", 0); _cachedColumnTmps.TryGetValue("ScoreCount", out value); if ((Object)(object)value == (Object)null) { return 0; } } string text = ((TMP_Text)value).text; if (string.IsNullOrEmpty(text)) { return 0; } int num = 0; string[] array = text.Split('\n'); foreach (string countRaw in array) { num += ParseCountFromScoreCell(countRaw); } return num; } catch { return 0; } } private static string StripSizeTags(string text) { if (string.IsNullOrEmpty(text)) { return text; } while (true) { int num = text.IndexOf("<size=", StringComparison.OrdinalIgnoreCase); if (num < 0) { break; } int num2 = text.IndexOf('>', num); if (num2 < 0) { break; } text = text.Remove(num, num2 - num + 1); } text = text.Replace("</size>", "").Replace("</SIZE>", ""); return text; } public static bool ShouldShowLeaderboard() { return true; } } [HarmonyPatch(typeof(Campfire), "Light_Rpc")] public static class Patch_Campfire_Light_CoopStarReward { private const float FALLBACK_HEIGHT_OFFSET = 1.5f; [HarmonyPostfix] public static void Postfix(Campfire __instance) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) try { if (!PhotonNetwork.IsMasterClient || FlagSurvivalNetwork.CurrentMultiplayerMode == FlagSurvivalNetwork.MultiplayerMode.PvP || (Object)(object)__instance == (Object)null || (Object)(object)((Component)__instance).transform == (Object)null) { return; } int num = ComputeCurrentBiomePctCoop(); int num2 = ComputeStarCount(num); if (num2 < 3) { ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogInfo((object)$"[v172.coop1] 모닥불 점화 — pct={num}%, 별={num2}개 (★★★ 미달, 보석 미지급)"); } return; } Vector3 val = ((Component)__instance).transform.position + Vector3.up * 1.5f; try { if ((Object)(object)PhotonNetwork.Instantiate("0_Items/Strange Gem", val, Quaternion.identity, (byte)0, (object[])null) != (Object)null) { ManualLogSource log2 = FlagSurvivalPlugin.Log; if (log2 != null) { log2.LogInfo((object)$"[v172.coop1] ★★★ 보상! pct={num}% — 보석 스폰 @ {val}"); } } else { ManualLogSource log3 = FlagSurvivalPlugin.Log; if (log3 != null) { log3.LogWarning((object)"[v172.coop1] PhotonNetwork.Instantiate 결과 null — prefab 경로 확인 필요"); } } } catch (Exception ex) { ManualLogSource log4 = FlagSurvivalPlugin.Log; if (log4 != null) { log4.LogError((object)("[v172.coop1] 보석 스폰 실패: " + ex.Message)); } } } catch (Exception ex2) { ManualLogSource log5 = FlagSurvivalPlugin.Log; if (log5 != null) { log5.LogError((object)("[v172.coop1] Patch_Campfire_Light_CoopStarReward 예외: " + ex2.Message)); } } } private static int ComputeCurrentBiomePctCoop() { try { int totalFlagCount = FlagSurvivalMulti.GetTotalFlagCount(); if (totalFlagCount <= 0) { return 0; } int num = 0; Dictionary<int, int> flagCounts = FlagSurvivalMulti.GetFlagCounts(); if (flagCounts != null) { foreach (int value in flagCounts.Values) { num += value; } } if (num <= 0) { return 0; } int playerCount = 1; try { Player[] playerList = PhotonNetwork.PlayerList; if (playerList != null && playerList.Length != 0) { playerCount = playerList.Length; } } catch { } float coopTargetRatio = FlagSurvivalMulti.GetCoopTargetRatio(playerCount); float num2 = Mathf.Clamp(196f / ((float)totalFlagCount + 200f), 0.25f, 1f); int num3 = ApplyTargetBonus(Mathf.Max(1, Mathf.RoundToInt((float)totalFlagCount * coopTargetRatio * num2))); return Mathf.Clamp(Mathf.RoundToInt((float)num / (float)num3 * 100f), 0, 100); } catch { return 0; } } private static int ApplyTargetBonus(int targetCount) { if (targetCount <= 10) { return targetCount + 1; } if (targetCount <= 20) { return targetCount + 3; } if (targetCount <= 30) { return targetCount + 2; } if (targetCount <= 50) { return targetCount + 1; } return targetCount; } private static int ComputeStarCount(int pct) { if (pct >= 100) { return 3; } if (pct >= 67) { return 2; } if (pct >= 34) { return 1; } return 0; } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.sol.peak.flagsurvival.coordsrowthrottle", "Coords Row Throttle", "1.0.0")] public class FlagCoordsRowThrottlePlugin : BaseUnityPlugin { private void Awake() { ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogInfo((object)"[CoordsThrottle] v2 활성: CoordsRunner.Update 0.05초 throttle (60Hz → 20Hz, 3배 절감)"); } } } [HarmonyPatch] public static class Patch_CoordsRunner_Update_Throttle { private const float THROTTLE_INTERVAL = 0.05f; private static float _lastTime = -1f; public static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("FlagSurvival.FlagPlayerCoordsRowPlugin+CoordsRunner"); if (type == null) { ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogWarning((object)"[CoordsThrottle] CoordsRunner 타입 못 찾음 — FlagPlayerCoordsRow 모듈 누락? 패치 skip."); } return null; } MethodInfo methodInfo = AccessTools.Method(type, "Update", (Type[])null, (Type[])null); if (methodInfo == null) { ManualLogSource log2 = FlagSurvivalPlugin.Log; if (log2 != null) { log2.LogError((object)"[CoordsThrottle] Update 메서드 못 찾음 — CoordsRunner 시그니처 변경?"); } return null; } return methodInfo; } [HarmonyPrefix] public static bool Prefix() { float realtimeSinceStartup = Time.realtimeSinceStartup; if (_lastTime > 0f && realtimeSinceStartup - _lastTime < 0.05f) { return false; } _lastTime = realtimeSinceStartup; return true; } } public static class FlagCountUI { private class UITick : MonoBehaviour { private float _nextUpdate; private void Update() { try { bool num = Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305); bool key = Input.GetKey((KeyCode)289); bool flag = num && key; if (flag != _uiTabHeld) { _uiTabHeld = flag; ApplyTabVisibility(); } } catch { } if (Time.realtimeSinceStartup < _nextUpdate) { return; } _nextUpdate = Time.realtimeSinceStartup + 0.5f; try { FlagSegmentScoring.HostUpdate(); } catch (Exception ex) { ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogError((object)("[FlagCountUI.Tick] [v172.s1] FlagSegmentScoring.HostUpdate 예외: " + ex.Message)); } } try { FlagTowingSystem.HostUpdate(); } catch (Exception ex2) { ManualLogSource log2 = FlagSurvivalPlugin.Log; if (log2 != null) { log2.LogError((object)("[FlagCountUI.Tick] [v172.t1] FlagTowingSystem.HostUpdate 예외: " + ex2.Message)); } } try { FlagFixedHUD.Update(); } catch (Exception ex3) { ManualLogSource log3 = FlagSurvivalPlugin.Log; if (log3 != null) { log3.LogError((object)("[FlagCountUI.Tick] [v172.hud1] FlagFixedHUD.Update 예외: " + ex3.Message)); } } if ((Object)(object)_uiObject == (Object)null || (Object)(object)_textName == (Object)null) { Transform val = null; if ((Object)(object)_ownCanvas != (Object)null) { val = ((Component)_ownCanvas).transform; } else if ((Object)(object)_lastGuiManagerTransform != (Object)null) { val = _lastGuiManagerTransform; } if ((Object)(object)val != (Object)null) { ManualLogSource log4 = FlagSurvivalPlugin.Log; if (log4 != null) { log4.LogWarning((object)"[FlagCountUI.Tick] UI destroy됨 — 재생성"); } CreateUI(val); } } else { Refresh(); } } } private const float UPDATE_INTERVAL = 0.5f; private const float FONT_SIZE = 33f; private const float FONT_SIZE_STAR = 27f; private const float FONT_SIZE_KR = 30f; private const float ANCHOR_X = -20f; private const float OFFSET_Y = 80f; private const float BOX_WIDTH = 900f; private const float BOX_HEIGHT = 240f; private const float BOX_GAP = 50f; private const float SCORE_BOX_HEIGHT = 240f; private const float SCORE_BOX_WIDTH = 1300f; private const float COL_X_SCORE_NAME = 0f; private const float COL_X_SCORE_COUNT = 280f; private const float COL_X_SCORE_PCT = 480f; private const float COL_X_SCORE_STAR = 600f; private const float COL_X_SCORE_MYDIST = 700f; private const float COL_X_SCORE_LEADGAP = 850f; private const float COL_X_SCORE_TOTAL = 1000f; private const float COL_X_SCORE_BONUS = 1150f; private const float COL_X_NAME = 0f; private const float COL_X_TOP = 200f; private const float COL_X_COUNT = 480f; private const float COL_X_PCT = 600f; private const float COL_X_STAR = 680f; private const float COL_X_DEBUG = 800f; private static GameObject _uiObject; private static GameObject _scoreObject; private static bool _uiAllowedByTrigger = false; private static bool _uiTabHeld = false; private static TextMeshProUGUI _textName; private static TextMeshProUGUI _textCount; private static TextMeshProUGUI _textPct; private static TextMeshProUGUI _textStar; private static TextMeshProUGUI _textTop; private static TextMeshProUGUI _textDebug; private static TextMeshProUGUI _scoreName; private static TextMeshProUGUI _scoreCount; private static TextMeshProUGUI _scorePct; private static TextMeshProUGUI _scoreStar; private static TextMeshProUGUI _scoreMyDist; private static TextMeshProUGUI _scoreLeadGap; private static TextMeshProUGUI _scoreTotal; private static TextMeshProUGUI _scoreBonus; private static bool _segmentRankHandlerRegistered = false; private static int _lastTrackedSegmentForReset = -1; private static UITick _tickInstance; private static int _lastSig = -1; private static Transform _lastGuiManagerTransform; private static Canvas _ownCanvas; private static readonly Vector3 PEAK_SUMMIT_POSITION = new Vector3(19.5f, 1228.7f, 2242.5f); public static void OnGUIManagerStarted(MonoBehaviour guiManager) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) try { Scene activeScene = SceneManager.GetActiveScene(); string name = ((Scene)(ref activeScene)).name; if (name == "Airport") { FlagEndCutsceneState.IsActive = false; ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogInfo((object)"[FlagCountUI] Airport 씬 — UI 그대로 유지 (1등 결과 보존) + 엔드 컷씬 UI 숨김 해제"); } } else { if ((Object)(object)guiManager == (Object)null) { return; } ManualLogSource log2 = FlagSurvivalPlugin.Log; if (log2 != null) { log2.LogWarning((object)("[FlagCountUI] OnGUIManagerStarted 진입 — scene=" + name + " (트리거 발동까지 UI 숨김 유지)")); } try { FlagSurvivalMulti.ResetFlagRegistry(); } catch (Exception ex) { ManualLogSource log3 = FlagSurvivalPlugin.Log; if (log3 != null) { log3.LogError((object)("[FlagCountUI] [v83] FlagSurvivalMulti.ResetFlagRegistry 실패: " + ex.Message)); } } try { FlagSegmentScoring.ResetAllScores(); FlagTowingSystem.ResetAllBonuses(); FlagWinnerCalculator.ClearCachedWinners(); FlagWinnerCalculator.ClearCachedLoserSlots(); FlagDeathRespawn.ResetAll(); ManualLogSource log4 = FlagSurvivalPlugin.Log; if (log4 != null) { log4.LogInfo((object)"[FlagCountUI] [v172.s4] 새 게임 진입 — 점수/winner/loser/부활 캐시 강제 리셋"); } } catch (Exception ex2) { ManualLogSource log5 = FlagSurvivalPlugin.Log; if (log5 != null) { log5.LogError((object)("[FlagCountUI] [v172.s4] 점수 리셋 실패: " + ex2.Message)); } } try { FlagSurvivalNetwork.ResetShoreState(); ManualLogSource log6 = FlagSurvivalPlugin.Log; if (log6 != null) { log6.LogInfo((object)"[FlagCountUI] [v172] 해안 게이팅 상태 리셋 (ResetShoreState 호출) — 다음 게임 ready 신호 정상 수신 보장"); } } catch (Exception ex3) { ManualLogSource log7 = FlagSurvivalPlugin.Log; if (log7 != null) { log7.LogError((object)("[FlagCountUI] [v172] FlagSurvivalNetwork.ResetShoreState 실패: " + ex3.Message)); } } if (!_segmentRankHandlerRegistered) { try { FlagSurvivalNetwork.OnSegmentRankReceived = (Action<int, int, int>)Delegate.Combine(FlagSurvivalNetwork.OnSegmentRankReceived, (Action<int, int, int>)delegate(int seg, int actor, int rank) { FlagSegmentScoring.SetSegmentRank(seg, actor, rank); }); _segmentRankHandlerRegistered = true; ManualLogSource log8 = FlagSurvivalPlugin.Log; if (log8 != null) { log8.LogInfo((object)"[FlagCountUI] [v172.s1] OnSegmentRankReceived 핸들러 등록 완료"); } } catch (Exception ex4) { ManualLogSource log9 = FlagSurvivalPlugin.Log; if (log9 != null) { log9.LogError((object)("[FlagCountUI] [v172.s1] OnSegmentRankReceived 핸들러 등록 실패: " + ex4.Message)); } } } _lastGuiManagerTransform = ((Component)guiManager).transform; SetUIVisible(visible: false); } } catch (Exception ex5) { ManualLogSource log10 = FlagSurvivalPlugin.Log; if (log10 != null) { log10.LogError((object)("[FlagCountUI] OnGUIManagerStarted 실패: " + ex5.Message + "\n" + ex5.StackTrace)); } } } public static void OnTriggerReachedShowUI() { try { _uiAllowedByTrigger = true; if ((Object)(object)_uiObject == (Object)null) { if ((Object)(object)_lastGuiManagerTransform == (Object)null) { ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogWarning((object)"[FlagCountUI] OnTriggerReachedShowUI — _lastGuiManagerTransform 없음 (자체 캔버스로 생성)"); } } CreateUI(_lastGuiManagerTransform); EnsureTickInstance(); ApplyTabVisibility(); ManualLogSource log2 = FlagSurvivalPlugin.Log; if (log2 != null) { log2.LogWarning((object)"[FlagCountUI] 첫 트리거 — UI 생성 (Tab 누름 시 표시)"); } } else { ApplyTabVisibility(); ManualLogSource log3 = FlagSurvivalPlugin.Log; if (log3 != null) { log3.LogWarning((object)"[FlagCountUI] 트리거 — UI 재사용 (Tab 누름 시 표시)"); } } } catch (Exception ex) { ManualLogSource log4 = FlagSurvivalPlugin.Log; if (log4 != null) { log4.LogError((object)("[FlagCountUI] OnTriggerReachedShowUI 실패: " + ex.Message)); } } } public static void SetUIHidden() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) try { Scene activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).name == "Airport") { ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogInfo((object)"[FlagCountUI] Airport 씬 — SetUIHidden 무시 (UI 유지, 1등 결과 보존)"); } return; } } catch { } SetUIVisible(visible: false); ManualLogSource log2 = FlagSurvivalPlugin.Log; if (log2 != null) { log2.LogInfo((object)"[FlagCountUI] 시작 저주 부여 — UI 숨김"); } } private static void SetUIVisible(bool visible) { if ((Object)(object)_uiObject != (Object)null) { _uiObject.SetActive(visible); } if ((Object)(object)_scoreObject != (Object)null) { _scoreObject.SetActive(visible); } } private static void ApplyTabVisibility() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_uiObject == (Object)null) || !((Object)(object)_scoreObject == (Object)null)) { bool flag; try { Scene activeScene = SceneManager.GetActiveScene(); flag = ((((Scene)(ref activeScene)).name == "Airport") ? _uiTabHeld : (_uiAllowedByTrigger && _uiTabHeld)); } catch { flag = _uiTabHeld; } if ((Object)(object)_uiObject != (Object)null && _uiObject.activeSelf != flag) { _uiObject.SetActive(flag); } if ((Object)(object)_scoreObject != (Object)null && _scoreObject.activeSelf != flag) { _scoreObject.SetActive(flag); } } } private static TextMeshProUGUI FindEnglishTextTMP() { TextMeshProUGUI[] array = Object.FindObjectsOfType<TextMeshProUGUI>(); if (array == null || array.Length == 0) { return null; } TextMeshProUGUI val = null; TextMeshProUGUI[] array2 = array; foreach (TextMeshProUGUI val2 in array2) { if ((Object)(object)val2 == (Object)null || (Object)(object)((TMP_Text)val2).font == (Object)null) { continue; } string text = ((TMP_Text)val2).text; if (string.IsNullOrEmpty(text)) { if ((Object)(object)val == (Object)null) { val = val2; } continue; } bool flag = true; string text2 = text; for (int j = 0; j < text2.Length; j++) { if (text2[j] > '\u007f') { flag = false; break; } } if (flag) { return val2; } if ((Object)(object)val == (Object)null) { val = val2; } } return val; } private static void CreateUI(Transform parent) { //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Expected O, but got Unknown //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Expected O, but got Unknown //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_034d: Expected O, but got Unknown //IL_0381: Unknown result type (might be due to invalid IL or missing references) //IL_0397: Unknown result type (might be due to invalid IL or missing references) //IL_03ad: Unknown result type (might be due to invalid IL or missing references) //IL_03c3: Unknown result type (might be due to invalid IL or missing references) //IL_03d9: Unknown result type (might be due to invalid IL or missing references) //IL_03e5: Unknown result type (might be due to invalid IL or missing references) //IL_03f1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_uiObject != (Object)null) { Object.Destroy((Object)(object)_uiObject); _uiObject = null; } if ((Object)(object)_scoreObject != (Object)null) { Object.Destroy((Object)(object)_scoreObject); _scoreObject = null; } _textName = (_textCount = (_textPct = (_textStar = null))); _textTop = (_textDebug = null); TextMeshProUGUI val = FindEnglishTextTMP(); if ((Object)(object)val == (Object)null) { val = Object.FindObjectOfType<TextMeshProUGUI>(); } if ((Object)(object)val == (Object)null || (Object)(object)((TMP_Text)val).font == (Object)null) { ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogWarning((object)"[FlagCountUI] 폰트 빌려올 TMP 없음"); } return; } ManualLogSource log2 = FlagSurvivalPlugin.Log; if (log2 != null) { log2.LogWarning((object)("[FlagCountUI] 폰트 빌려옴: " + ((Object)((TMP_Text)val).font).name + " (from " + ((Object)val).name + ", text='" + ((TMP_Text)val).text + "')")); } Canvas componentInParent = ((Component)parent).GetComponentInParent<Canvas>(); Transform val2; int layer; if ((Object)(object)componentInParent != (Object)null) { val2 = parent; layer = ((Component)componentInParent).gameObject.layer; } else { if ((Object)(object)_ownCanvas == (Object)null) { GameObject val3 = new GameObject("FlagSurvival_FlagCountCanvas"); Object.DontDestroyOnLoad((Object)val3); _ownCanvas = val3.AddComponent<Canvas>(); _ownCanvas.renderMode = (RenderMode)0; _ownCanvas.sortingOrder = 100; val3.AddComponent<CanvasScaler>(); val3.AddComponent<GraphicRaycaster>(); int num = LayerMask.NameToLayer("UI"); val3.layer = ((num >= 0) ? num : 5); } val2 = ((Component)_ownCanvas).transform; layer = ((Component)_ownCanvas).gameObject.layer; } _uiObject = new GameObject("FlagSurvival_FlagCountContainer", new Type[1] { typeof(RectTransform) }); _uiObject.transform.SetParent(val2, false); _uiObject.layer = layer; RectTransform component = _uiObject.GetComponent<RectTransform>(); component.anchorMin = new Vector2(1f, 1f); component.anchorMax = new Vector2(1f, 1f); component.pivot = new Vector2(1f, 1f); component.anchoredPosition = new Vector2(-20f, -80f); component.sizeDelta = new Vector2(900f, 240f); ((Transform)component).localScale = Vector3.one; ((Transform)component).localRotation = Quaternion.identity; CreateBoxBorder(component, layer, "BiomeBoxBorder"); _textName = CreateColumnTMP("Name", component, val, layer, 0f, 30f); _textCount = CreateColumnTMP("Count", component, val, layer, 480f, 33f); _textPct = CreateColumnTMP("Pct", component, val, layer, 600f, 33f); _textStar = CreateColumnTMP("Star", component, val, layer, 680f, 27f); _textTop = CreateColumnTMP("Top", component, val, layer, 200f, 30f); _textDebug = CreateColumnTMP("Debug", component, val, layer, 800f, 33f); _scoreObject = new GameObject("FlagSurvival_ScoreContainer", new Type[1] { typeof(RectTransform) }); _scoreObject.transform.SetParent(val2, false); _scoreObject.layer = layer; RectTransform component2 = _scoreObject.GetComponent<RectTransform>(); component2.anchorMin = new Vector2(1f, 1f); component2.anchorMax = new Vector2(1f, 1f); component2.pivot = new Vector2(1f, 1f); component2.anchoredPosition = new Vector2(-20f, -370f); component2.sizeDelta = new Vector2(1300f, 240f); ((Transform)component2).localScale = Vector3.one; ((Transform)component2).localRotation = Quaternion.identity; CreateBoxBorder(component2, layer, "ScoreBoxBorder"); _scoreName = CreateColumnTMP("ScoreName", component2, val, layer, 0f, 30f); _scoreCount = CreateColumnTMP("ScoreCount", component2, val, layer, 280f, 33f); _scorePct = CreateColumnTMP("ScorePct", component2, val, layer, 480f, 33f); _scoreStar = CreateColumnTMP("ScoreStar", component2, val, layer, 600f, 27f); _scoreMyDist = CreateColumnTMP("ScoreMyDist", component2, val, layer, 700f, 33f); _scoreLeadGap = CreateColumnTMP("ScoreLeadGap", component2, val, layer, 850f, 33f); _scoreTotal = CreateColumnTMP("ScoreTotal", component2, val, layer, 1000f, 33f); _scoreBonus = CreateColumnTMP("ScoreBonus", component2, val, layer, 1150f, 33f); _lastSig = -1; ManualLogSource log3 = FlagSurvivalPlugin.Log; if (log3 != null) { log3.LogWarning((object)$"[FlagCountUI] UI 생성 완료 — 박스1(바이옴)={900f}×{240f}, 박스2(스코어)={1300f}×{240f}, parent={((Object)val2).name}"); } try { FlagFixedHUD.OnGUIManagerStarted(val); } catch (Exception ex) { ManualLogSource log4 = FlagSurvivalPlugin.Log; if (log4 != null) { log4.LogError((object)("[FlagCountUI] [v172.hud1] FlagFixedHUD 초기화 실패: " + ex.Message)); } } } private static void CreateBoxBorder(RectTransform parent, int layer, string nameSuffix) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) Color color = default(Color); ((Color)(ref color))..ctor(1f, 1f, 1f, 0.6f); CreateBorderEdge(parent, layer, nameSuffix + "_Top", new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0.5f, 1f), 0f, 2f, color); CreateBorderEdge(parent, layer, nameSuffix + "_Bottom", new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(0.5f, 0f), 0f, 2f, color); CreateBorderEdge(parent, layer, nameSuffix + "_Left", new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(0f, 0.5f), 2f, 0f, color); CreateBorderEdge(parent, layer, nameSuffix + "_Right", new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(1f, 0.5f), 2f, 0f, color); } private static void CreateBorderEdge(RectTransform parent, int layer, string name, Vector2 anchorMin, Vector2 anchorMax, Vector2 pivot, float widthPx, float heightPx, Color color) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); val.transform.SetParent((Transform)(object)parent, false); val.layer = layer; RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = anchorMin; component.anchorMax = anchorMax; component.pivot = pivot; component.anchoredPosition = Vector2.zero; component.sizeDelta = new Vector2(widthPx, heightPx); ((Transform)component).localScale = Vector3.one; Image component2 = val.GetComponent<Image>(); ((Graphic)component2).color = color; ((Graphic)component2).raycastTarget = false; } private static TextMeshProUGUI CreateColumnTMP(string suffix, RectTransform parent, TextMeshProUGUI sourceTmp, int layer, float xOffset, float fontSize) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_035c: Unknown result type (might be due to invalid IL or missing references) //IL_0361: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0485: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_0402: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("FlagSurvival_FlagCountText_" + suffix, new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(TextMeshProUGUI) }); val.transform.SetParent((Transform)(object)parent, false); val.layer = layer; RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0f, 1f); component.anchorMax = new Vector2(0f, 1f); component.pivot = new Vector2(0f, 1f); component.anchoredPosition = new Vector2(xOffset, 0f); component.sizeDelta = new Vector2(900f, 240f); ((Transform)component).localScale = Vector3.one; ((Transform)component).localRotation = Quaternion.identity; TextMeshProUGUI component2 = val.GetComponent<TextMeshProUGUI>(); ((TMP_Text)component2).font = ((TMP_Text)sourceTmp).font; ((TMP_Text)component2).fontSize = fontSize; ((TMP_Text)component2).alignment = (TextAlignmentOptions)513; ((Graphic)component2).color = ((Graphic)sourceTmp).color; try { Material fontMaterial = ((TMP_Text)sourceTmp).fontMaterial; if ((Object)(object)fontMaterial != (Object)null) { if (suffix == "Name") { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("[FlagCountUI] 머티리얼='" + ((Object)fontMaterial).name + "', shader='" + ((Object)fontMaterial.shader).name + "'\n"); if (fontMaterial.HasProperty("_OutlineColor")) { stringBuilder.Append(string.Format(" _OutlineColor={0}\n", fontMaterial.GetColor("_OutlineColor"))); } if (fontMaterial.HasProperty("_OutlineWidth")) { stringBuilder.Append(string.Format(" _OutlineWidth={0}\n", fontMaterial.GetFloat("_OutlineWidth"))); } if (fontMaterial.HasProperty("_UnderlayColor")) { stringBuilder.Append(string.Format(" _UnderlayColor={0}\n", fontMaterial.GetColor("_UnderlayColor"))); } if (fontMaterial.HasProperty("_UnderlayOffsetX")) { stringBuilder.Append(string.Format(" _UnderlayOffsetX={0}\n", fontMaterial.GetFloat("_UnderlayOffsetX"))); } if (fontMaterial.HasProperty("_UnderlayOffsetY")) { stringBuilder.Append(string.Format(" _UnderlayOffsetY={0}\n", fontMaterial.GetFloat("_UnderlayOffsetY"))); } if (fontMaterial.HasProperty("_UnderlayDilate")) { stringBuilder.Append(string.Format(" _UnderlayDilate={0}\n", fontMaterial.GetFloat("_UnderlayDilate"))); } if (fontMaterial.HasProperty("_UnderlaySoftness")) { stringBuilder.Append(string.Format(" _UnderlaySoftness={0}\n", fontMaterial.GetFloat("_UnderlaySoftness"))); } if (fontMaterial.HasProperty("_Bevel")) { stringBuilder.Append(string.Format(" _Bevel={0}\n", fontMaterial.GetFloat("_Bevel"))); } if (fontMaterial.HasProperty("_GlowColor")) { stringBuilder.Append(string.Format(" _GlowColor={0}\n", fontMaterial.GetColor("_GlowColor"))); } stringBuilder.Append(" shaderKeywords=[" + string.Join(", ", fontMaterial.shaderKeywords) + "]"); ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogWarning((object)stringBuilder.ToString()); } } ((TMP_Text)component2).outlineColor = Color32.op_Implicit(new Color(0.596f, 0.58f, 0.549f, 1f)); ((TMP_Text)component2).outlineWidth = 0.05f; if ((Object)(object)((TMP_Text)component2).font != (Object)null && ((TMP_Text)component2).font.fallbackFontAssetTable != null) { foreach (TMP_FontAsset item in ((TMP_Text)component2).font.fallbackFontAssetTable) { if (!((Object)(object)item == (Object)null) && !((Object)(object)((TMP_Asset)item).material == (Object)null)) { if (((TMP_Asset)item).material.HasProperty("_OutlineColor")) { ((TMP_Asset)item).material.SetColor("_OutlineColor", new Color(0.596f, 0.58f, 0.549f, 1f)); } if (((TMP_Asset)item).material.HasProperty("_OutlineWidth")) { ((TMP_Asset)item).material.SetFloat("_OutlineWidth", 0.1f); } } } } if (((TMP_Text)component2).fontMaterial.HasProperty("_UnderlayColor")) { ((TMP_Text)component2).fontMaterial.SetColor("_UnderlayColor", new Color(0f, 0f, 0f, 0.4f)); ((TMP_Text)component2).fontMaterial.SetFloat("_UnderlayOffsetX", 0f); ((TMP_Text)component2).fontMaterial.SetFloat("_UnderlayOffsetY", 0f); ((TMP_Text)component2).fontMaterial.SetFloat("_UnderlayDilate", 0.1f); ((TMP_Text)component2).fontMaterial.SetFloat("_UnderlaySoftness", 0.4f); ((TMP_Text)component2).fontMaterial.EnableKeyword("UNDERLAY_ON"); ManualLogSource log2 = FlagSurvivalPlugin.Log; if (log2 != null) { log2.LogInfo((object)("[FlagCountUI.Col-" + suffix + "] underlay 적용 (PEAK 중앙 발산 스타일)")); } } else { ManualLogSource log3 = FlagSurvivalPlugin.Log; if (log3 != null) { log3.LogWarning((object)("[FlagCountUI.Col-" + suffix + "] 머티리얼이 underlay 미지원 — 그림자 효과 X")); } } } } catch (Exception ex) { ManualLogSource log4 = FlagSurvivalPlugin.Log; if (log4 != null) { log4.LogWarning((object)("[FlagCountUI.Col-" + suffix + "] outline 추출 실패: " + ex.Message)); } } ((TMP_Text)component2).text = ""; ((Graphic)component2).raycastTarget = false; ((TMP_Text)component2).enableWordWrapping = false; ((TMP_Text)component2).enableAutoSizing = false; ((TMP_Text)component2).autoSizeTextContainer = false; ((TMP_Text)component2).paragraphSpacing = 0f; ((TMP_Text)component2).lineSpacing = 0f; return component2; } private static void EnsureTickInstance() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown if ((Object)(object)_tickInstance != (Object)null) { return; } try { GameObject val = new GameObject("FlagSurvival_FlagCountUI_Tick"); Object.DontDestroyOnLoad((Object)val); _tickInstance = val.AddComponent<UITick>(); } catch (Exception ex) { ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogError((object)("[FlagCountUI] Tick 생성 실패: " + ex.Message)); } } } private static void Refresh() { if ((Object)(object)_textName == (Object)null || (Object)(object)_textCount == (Object)null || (Object)(object)_textPct == (Object)null || (Object)(object)_textStar == (Object)null || (Object)(object)_textTop == (Object)null || (Object)(object)_uiObject == (Object)null) { return; } string[] array = new string[5] { "해안", "뿌리숲/열대", "메사/고산", "칼데라", "가마" }; Dictionary<int, FlagSurvivalMulti.BiomeStats> dictionary = new Dictionary<int, FlagSurvivalMulti.BiomeStats>(); foreach (FlagSurvivalMulti.BiomeStats allBiomeStat in FlagSurvivalMulti.GetAllBiomeStats()) { dictionary[allBiomeStat.segmentIndex] = allBiomeStat; } int currentSegmentIndex = FlagSurvivalMulti.GetCurrentSegmentIndex(); string currentBiome = FlagSurvivalMulti.GetCurrentBiome(); string currentBiomeTitle = FlagSurvivalMulti.GetCurrentBiomeTitle(); int totalFlagCount = FlagSurvivalMulti.GetTotalFlagCount(); int reachableFlagCount = FlagSurvivalMulti.GetReachableFlagCount(); Dictionary<int, int> flagCounts = FlagSurvivalMulti.GetFlagCounts(); int num = 0; foreach (KeyValuePair<int, int> item3 in flagCounts) { num += item3.Value; } List<(string, int)> list = new List<(string, int)>(); try { Player[] playerList = PhotonNetwork.PlayerList; if (playerList != null && playerList.Length != 0) { Player[] array2 = playerList; foreach (Player val in array2) { if (val != null) { flagCounts.TryGetValue(val.ActorNumber, out var value); string item = (string.IsNullOrEmpty(val.NickName) ? $"P{val.ActorNumber}" : val.NickName); list.Add((item, value)); } } } else { int key = ((PhotonNetwork.LocalPlayer == null) ? 1 : PhotonNetwork.LocalPlayer.ActorNumber); flagCounts.TryGetValue(key, out var value2); string item2 = ((PhotonNetwork.LocalPlayer != null && !string.IsNullOrEmpty(PhotonNetwork.LocalPlayer.NickName)) ? PhotonNetwork.LocalPlayer.NickName : "나"); list.Add((item2, value2)); } } catch (Exception ex) { ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogError((object)("[FlagCountUI] 플레이어 데이터 수집 실패: " + ex.Message)); } } list.Sort(delegate((string name, int count) a, (string name, int count) b) { int num18 = b.count.CompareTo(a.count); return (num18 != 0) ? num18 : string.Compare(a.name, b.name, StringComparison.Ordinal); }); string text = ""; int num2 = 0; if (flagCounts.Count > 0) { int num3 = 0; List<int> list2 = new List<int>(); foreach (KeyValuePair<int, int> item4 in flagCounts) { if (item4.Value > num3) { num3 = item4.Value; list2.Clear(); list2.Add(item4.Key); } else if (item4.Value == num3 && num3 > 0) { list2.Add(item4.Key); } } num2 = num3; if (num3 > 0) { List<string> list3 = new List<string>(); try { Player[] playerList2 = PhotonNetwork.PlayerList; if (playerList2 != null) { foreach (int item5 in list2) { Player[] array2 = playerList2; foreach (Player val2 in array2) { if (val2 != null && val2.ActorNumber == item5) { list3.Add(string.IsNullOrEmpty(val2.NickName) ? $"P{item5}" : val2.NickName); break; } } } } } catch { } text = string.Join(",", list3); } } int num4 = 17; num4 = num4 * 31 + currentSegmentIndex; num4 = num4 * 31 + totalFlagCount; num4 = num4 * 31 + reachableFlagCount; num4 = num4 * 31 + num; num4 = num4 * 31 + text.GetHashCode(); num4 = num4 * 31 + num2; num4 = num4 * 31 + currentBiomeTitle.GetHashCode(); num4 = (int)(num4 * 31 + FlagSurvivalNetwork.CurrentMultiplayerMode); int num5 = 1; try { Player[] playerList3 = PhotonNetwork.PlayerList; if (playerList3 != null) { num5 = playerList3.Length; } } catch { } num4 = num4 * 31 + num5; foreach (KeyValuePair<int, FlagSurvivalMulti.BiomeStats> item6 in dictionary) { num4 = num4 * 31 + item6.Key + item6.Value.totalConsumed; } foreach (var item7 in list) { num4 = num4 * 31 + item7.Item1.GetHashCode() + item7.Item2; } try { Dictionary<int, float> dictionary2 = ComputeCampfireDistances(); if (dictionary2 != null) { foreach (float value10 in dictionary2.Values) { num4 = num4 * 31 + (int)(value10 * 10f); } } } catch { } try { if (PhotonNetwork.PlayerList != null) { Player[] array2 = PhotonNetwork.PlayerList; foreach (Player val3 in array2) { if (val3 != null) { num4 = num4 * 31 + (int)(FlagSegmentScoring.GetTotalScoreFloat(val3.ActorNumber) * 10f); num4 = num4 * 31 + (int)(FlagTowingSystem.GetAppliedBonusPercent(val3.ActorNumber) * 10f); } } } } catch { } if (num4 == _lastSig) { return; } _lastSig = num4; StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder2 = new StringBuilder(); StringBuilder stringBuilder3 = new StringBuilder(); StringBuilder stringBuilder4 = new StringBuilder(); StringBuilder stringBuilder5 = new StringBuilder(); StringBuilder stringBuilder6 = new StringBuilder(); for (int j = 0; j < 5; j++) { if (j > 0) { stringBuilder.Append('\n'); stringBuilder2.Append('\n'); stringBuilder3.Append('\n'); stringBuilder4.Append('\n'); stringBuilder5.Append('\n'); stringBuilder6.Append('\n'); } stringBuilder4.Append("<voffset=").Append(((float)(-(j - 1)) * 2.67f).ToString("F2")).Append(">"); int num6 = 0; string text2 = ""; int num7 = 0; bool flag = false; int pct = 0; string text3; int num8; int num9; if (j == currentSegmentIndex) { text3 = ((!string.IsNullOrEmpty(currentBiomeTitle)) ? currentBiomeTitle : ((!string.IsNullOrEmpty(currentBiome)) ? currentBiome : array[j])); num8 = totalFlagCount; num9 = num; text2 = text; num6 = num2; if (num8 > 0) { int num10 = Mathf.Max(1, Mathf.RoundToInt((float)num8 * 0.2f)); pct = Mathf.Clamp(Mathf.RoundToInt((float)num2 / (float)num10 * 100f), 0, 100); } } else { if (!dictionary.TryGetValue(j, out var value3)) { stringBuilder.Append("???"); stringBuilder2.Append("0/??"); stringBuilder3.Append("0%"); stringBuilder4.Append(GetStars(0)); stringBuilder5.Append("???"); stringBuilder6.Append("?"); continue; } text3 = ((!string.IsNullOrEmpty(value3.title)) ? value3.title : ((!string.IsNullOrEmpty(value3.biomeName)) ? value3.biomeName : array[j])); num8 = value3.totalFlags; num9 = value3.totalConsumed; text2 = value3.topPlayerName ?? ""; num7 = value3.pctAtBackup; flag = true; if (value3.playerCounts != null && value3.playerCounts.Count > 0) { int num11 = 0; foreach (int value11 in value3.playerCounts.Values) { if (value11 > num11) { num11 = value11; } } num6 = num11; if (value3.playerPctsAtBackup != null) { int num12 = -1; foreach (KeyValuePair<int, int> playerCount in value3.playerCounts) { if (playerCount.Value == num11) { num12 = playerCount.Key; break; } } if (num12 >= 0 && value3.playerPctsAtBackup.TryGetValue(num12, out var value4)) { pct = value4; } } } } bool num13 = FlagSurvivalNetwork.CurrentMultiplayerMode == FlagSurvivalNetwork.MultiplayerMode.PvP; if (!flag) { num7 = ComputeBiomePct(num9, num8, num6); } stringBuilder.Append(WrapByLang(text3)); if (num13) { stringBuilder2.Append(num6).Append('개'); stringBuilder4.Append(GetStars(pct)); } else { int value6; if (flag && dictionary.TryGetValue(j, out var value5)) { value6 = value5.targetCountAtBackup; } else { float num14 = ComputeWeightRatio(num8); float coopBaseRatio = GetCoopBaseRatio(); value6 = ApplyTargetBonus(Mathf.Max(1, Mathf.RoundToInt((float)num8 * coopBaseRatio * num14))); } stringBuilder2.Append(num9).Append('/').Append(value6); stringBuilder4.Append(GetStars(num7)); } stringBuilder3.Append(num7).Append('%'); string text4 = (string.IsNullOrEmpty(text2) ? "???" : text2); stringBuilder5.Append(WrapByLang(text4)); stringBuilder6.Append(num8); } StringBuilder stringBuilder7 = new StringBuilder(64); StringBuilder stringBuilder8 = new StringBuilder(64); StringBuilder stringBuilder9 = new StringBuilder(64); StringBuilder stringBuilder10 = new StringBuilder(64); StringBuilder stringBuilder11 = new StringBuilder(64); StringBuilder stringBuilder12 = new StringBuilder(64); StringBuilder stringBuilder13 = new StringBuilder(64); StringBuilder stringBuilder14 = new StringBuilder(64); Dictionary<int, float> dictionary3 = ComputeCampfireDistances(); float num15 = 0f; bool flag2 = dictionary3.Count > 0; if (flag2) { num15 = float.MaxValue; foreach (float value12 in dictionary3.Values) { if (value12 < num15) { num15 = value12; } } } Dictionary<string, int> dictionary4 = new Dictionary<string, int>(); try { if (PhotonNetwork.PlayerList != null) { Player[] array2 = PhotonNetwork.PlayerList; foreach (Player val4 in array2) { if (val4 != null) { string key2 = (string.IsNullOrEmpty(val4.NickName) ? $"P{val4.ActorNumber}" : val4.NickName); dictionary4[key2] = val4.ActorNumber; } } } } catch { } for (int k = 0; k < list.Count; k++) { if (k > 0) { stringBuilder7.Append('\n'); stringBuilder8.Append('\n'); stringBuilder9.Append('\n'); stringBuilder10.Append('\n'); stringBuilder11.Append('\n'); stringBuilder12.Append('\n'); stringBuilder13.Append('\n'); stringBuilder14.Append('\n'); } stringBuilder10.Append("<voffset=").Append(((float)(-k) * 2.67f).ToString("F2")).Append(">"); int num16 = ComputePlayerPct(list[k].Item2, totalFlagCount); stringBuilder7.Append(WrapByLang(list[k].Item1)); stringBuilder8.Append(list[k].Item2).Append('개'); stringBuilder9.Append(num16).Append('%'); stringBuilder10.Append(GetStars(num16)); if (flag2 && dictionary4.TryGetValue(list[k].Item1, out var value7) && dictionary3.TryGetValue(value7, out var value8)) { float num17 = num15 - value8; stringBuilder11.Append(value8.ToString("F1")).Append('m'); if (Mathf.Abs(num17) < 0.05f) { stringBuilder12.Append('0'); } else { stringBuilder12.Append(num17.ToString("F1")).Append('m'); } stringBuilder13.Append(FlagSegmentScoring.GetTotalScoreFloat(value7).ToString("F1")); float appliedBonusPercent = FlagTowingSystem.GetAppliedBonusPercent(value7); if (appliedBonusPercent < 0.05f) { stringBuilder14.Append('0'); } else { stringBuilder14.Append('+').Append(appliedBonusPercent.ToString("F1")).Append('%'); } continue; } stringBuilder11.Append('-'); stringBuilder12.Append('-'); if (dictionary4.TryGetValue(list[k].Item1, out var value9)) { stringBuilder13.Append(FlagSegmentScoring.GetTotalScoreFloat(value9).ToString("F1")); float appliedBonusPercent2 = FlagTowingSystem.GetAppliedBonusPercent(value9); if (appliedBonusPercent2 < 0.05f) { stringBuilder14.Append('0'); } else { stringBuilder14.Append('+').Append(appliedBonusPercent2.ToString("F1")).Append('%'); } } else { stringBuilder13.Append('-'); stringBuilder14.Append('-'); } } ((TMP_Text)_textName).text = stringBuilder.ToString(); ((TMP_Text)_textCount).text = stringBuilder2.ToString(); ((TMP_Text)_textPct).text = stringBuilder3.ToString(); ((TMP_Text)_textStar).text = stringBuilder4.ToString(); ((TMP_Text)_textTop).text = stringBuilder5.ToString(); ((TMP_Text)_textDebug).text = stringBuilder6.ToString(); ((TMP_Text)_scoreName).text = stringBuilder7.ToString(); ((TMP_Text)_scoreCount).text = stringBuilder8.ToString(); ((TMP_Text)_scorePct).text = stringBuilder9.ToString(); ((TMP_Text)_scoreStar).text = stringBuilder10.ToString(); if ((Object)(object)_scoreMyDist != (Object)null) { ((TMP_Text)_scoreMyDist).text = stringBuilder11.ToString(); } if ((Object)(object)_scoreLeadGap != (Object)null) { ((TMP_Text)_scoreLeadGap).text = stringBuilder12.ToString(); } if ((Object)(object)_scoreTotal != (Object)null) { ((TMP_Text)_scoreTotal).text = stringBuilder13.ToString(); } if ((Object)(object)_scoreBonus != (Object)null) { ((TMP_Text)_scoreBonus).text = stringBuilder14.ToString(); } ApplyDynamicColumnLayout(80f); ApplyScoreColumnLayout(80f); ManualLogSource log2 = FlagSurvivalPlugin.Log; if (log2 != null) { log2.LogWarning((object)$"[FlagCountUI.Refresh] 박스1(바이옴5행) + 박스2(스코어{list.Count}행) 갱신: currentSeg={currentSegmentIndex}({currentBiome}), top={text}"); } } private static void ApplyDynamicColumnLayout(float gap) { if ((Object)(object)_textName == (Object)null || (Object)(object)_textTop == (Object)null || (Object)(object)_textCount == (Object)null || (Object)(object)_textPct == (Object)null || (Object)(object)_textStar == (Object)null) { return; } try { ((TMP_Text)_textName).ForceMeshUpdate(false, false); ((TMP_Text)_textTop).ForceMeshUpdate(false, false); ((TMP_Text)_textCount).ForceMeshUpdate(false, false); ((TMP_Text)_textPct).ForceMeshUpdate(false, false); if ((Object)(object)_textStar != (Object)null) { ((TMP_Text)_textStar).ForceMeshUpdate(false, false); } float num = 0f; float num2 = num + ((TMP_Text)_textName).preferredWidth + gap; float num3 = num2 + ((TMP_Text)_textTop).preferredWidth + gap; float num4 = num3 + ((TMP_Text)_textCount).preferredWidth + gap; float num5 = num4 + ((TMP_Text)_textPct).preferredWidth + gap; float x = num5 + (((Object)(object)_textStar != (Object)null) ? ((TMP_Text)_textStar).preferredWidth : 0f) + gap; SetColumnX(_textName, num, 900f, 240f); SetColumnX(_textTop, num2, 900f, 240f); SetColumnX(_textCount, num3, 900f, 240f); SetColumnX(_textPct, num4, 900f, 240f); SetColumnX(_textStar, num5, 900f, 240f); if ((Object)(object)_textDebug != (Object)null) { SetColumnX(_textDebug, x, 900f, 240f); } } catch (Exception ex) { ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogError((object)("[FlagCountUI] 동적 컬럼 레이아웃 실패: " + ex.Message)); } } } private static void ApplyScoreColumnLayout(float gap) { if ((Object)(object)_scoreName == (Object)null || (Object)(object)_scoreCount == (Object)null || (Object)(object)_scorePct == (Object)null || (Object)(object)_scoreStar == (Object)null) { return; } try { ((TMP_Text)_scoreName).ForceMeshUpdate(false, false); ((TMP_Text)_scoreCount).ForceMeshUpdate(false, false); ((TMP_Text)_scorePct).ForceMeshUpdate(false, false); float num = 0f; float num2 = num + ((TMP_Text)_scoreName).preferredWidth + gap; float num3 = num2 + ((TMP_Text)_scoreCount).preferredWidth + gap; float num4 = num3 + ((TMP_Text)_scorePct).preferredWidth + gap; SetColumnX(_scoreName, num, 1300f, 240f); SetColumnX(_scoreCount, num2, 1300f, 240f); SetColumnX(_scorePct, num3, 1300f, 240f); SetColumnX(_scoreStar, num4, 1300f, 240f); if (!((Object)(object)_scoreMyDist != (Object)null) || !((Object)(object)_scoreLeadGap != (Object)null)) { return; } ((TMP_Text)_scoreStar).ForceMeshUpdate(false, false); ((TMP_Text)_scoreMyDist).ForceMeshUpdate(false, false); float num5 = num4 + ((TMP_Text)_scoreStar).preferredWidth + gap; float num6 = num5 + ((TMP_Text)_scoreMyDist).preferredWidth + gap; SetColumnX(_scoreMyDist, num5, 1300f, 240f); SetColumnX(_scoreLeadGap, num6, 1300f, 240f); if ((Object)(object)_scoreTotal != (Object)null) { ((TMP_Text)_scoreLeadGap).ForceMeshUpdate(false, false); float num7 = num6 + ((TMP_Text)_scoreLeadGap).preferredWidth + gap; SetColumnX(_scoreTotal, num7, 1300f, 240f); if ((Object)(object)_scoreBonus != (Object)null) { ((TMP_Text)_scoreTotal).ForceMeshUpdate(false, false); float x = num7 + ((TMP_Text)_scoreTotal).preferredWidth + gap; SetColumnX(_scoreBonus, x, 1300f, 240f); } } } catch (Exception ex) { ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogError((object)("[FlagCountUI] 스코어보드 컬럼 레이아웃 실패: " + ex.Message)); } } } private static Dictionary<int, float> ComputeCampfireDistances() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) Dictionary<int, float> dictionary = new Dictionary<int, float>(); try { Campfire val = null; try { val = MapHandler.CurrentCampfire; } catch { val = null; } Vector3 val2 = ((!((Object)(object)val != (Object)null) || !((Object)(object)((Component)val).transform != (Object)null)) ? PEAK_SUMMIT_POSITION : ((Component)val).transform.position); List<Character> allCharacters = Character.AllCharacters; if (allCharacters == null) { return dictionary; } foreach (Character item in allCharacters) { if (!((Object)(object)item == (Object)null) && !((Object)(object)((MonoBehaviourPun)item).photonView == (Object)null) && ((MonoBehaviourPun)item).photonView.Owner != null) { int actorNumber = ((MonoBehaviourPun)item).photonView.Owner.ActorNumber; float value = Vector3.Distance(val2, item.Center) * CharacterStats.unitsToMeters; dictionary[actorNumber] = value; } } } catch (Exception ex) { ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogError((object)("[FlagCountUI] [v172] 모닥불 거리 산출 실패: " + ex.Message)); } } return dictionary; } private static void SetColumnX(TextMeshProUGUI tmp, float x, float boxWidth, float boxHeight) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)tmp == (Object)null)) { RectTransform rectTransform = ((TMP_Text)tmp).rectTransform; if (!((Object)(object)rectTransform == (Object)null)) { rectTransform.anchoredPosition = new Vector2(x, 0f); rectTransform.sizeDelta = new Vector2(boxWidth, boxHeight); } } } private static string GetStars(int pct) { if (pct >= 100) { return "★★★"; } if (pct >= 67) { return "★★☆"; } if (pct >= 34) { return "★☆☆"; } return "☆☆☆"; } private static string WrapByLang(string text) { if (string.IsNullOrEmpty(text)) { return text; } bool flag = false; foreach (char c in text) { if ((c >= '가' && c <= '힣') || (c >= 'ᄀ' && c <= 'ᇿ') || (c >= '\u3130' && c <= '\u318f')) { flag = true; break; } } if (flag) { return text; } return "<size=33>" + text + "</size>"; } private static float ComputeWeightRatio(int totalFlags) { if (totalFlags <= 0) { return 1f; } return Mathf.Clamp(196f / ((float)totalFlags + 200f), 0.25f, 1f); } private static int ApplyTargetBonus(int targetCount) { if (targetCount <= 10) { return targetCount + 1; } if (targetCount <= 20) { return targetCount + 3; } if (targetCount <= 30) { return targetCount + 2; } if (targetCount <= 50) { return targetCount + 1; } return targetCount; } private static float GetCoopBaseRatio() { int playerCount = 1; try { Player[] playerList = PhotonNetwork.PlayerList; if (playerList != null && playerList.Length != 0) { playerCount = playerList.Length; } } catch { } return FlagSurvivalMulti.GetCoopTargetRatio(playerCount); } private static int ComputeBiomePct(int consumed, int totalFlags, int topCount = 0) { if (totalFlags <= 0) { return 0; } if (FlagSurvivalNetwork.CurrentMultiplayerMode == FlagSurvivalNetwork.MultiplayerMode.PvP) { if (consumed <= 0) { return 0; } return Mathf.Clamp(Mathf.RoundToInt((float)topCount / (float)consumed * 100f), 0, 100); } float num = ComputeWeightRatio(totalFlags); float coopBaseRatio = GetCoopBaseRatio(); int num2 = ApplyTargetBonus(Mathf.Max(1, Mathf.RoundToInt((float)totalFlags * coopBaseRatio * num))); return Mathf.Clamp(Mathf.RoundToInt((float)consumed / (float)num2 * 100f), 0, 100); } private static int ComputePlayerPct(int playerConsumed, int totalFlags) { if (totalFlags <= 0) { return 0; } float num = ComputeWeightRatio(totalFlags); int num2 = ApplyTargetBonus(Mathf.Max(1, Mathf.RoundToInt((float)totalFlags * 0.2f * num))); return Mathf.Clamp(Mathf.RoundToInt((float)playerConsumed / (float)num2 * 100f), 0, 100); } } [HarmonyPatch(typeof(GUIManager), "Start")] public class GUIManagerStartPatcher { [HarmonyPostfix] public static void Postfix(GUIManager __instance) { FlagCountUI.OnGUIManagerStarted((MonoBehaviour)(object)__instance); } } [HarmonyPatch(typeof(PeakHandler), "SummonHelicopter")] public static class Patch_SummonHelicopter_BackupKiln { [HarmonyPrefix] public static void Prefix() { try { int currentSegmentIndex = FlagSurvivalMulti.GetCurrentSegmentIndex(); if (currentSegmentIndex != 4) { ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogInfo((object)$"[가마백업] SummonHelicopter Prefix — curSeg={currentSegmentIndex} (가마/정상 아님, SKIP)"); } return; } string arg = FlagSurvivalMulti.GetCurrentBiome() ?? ""; string arg2 = FlagSurvivalMulti.GetCurrentBiomeTitle() ?? ""; FlagSurvivalMulti.BackupBiomeStats(4, "TheKiln", "가마"); ManualLogSource log2 = FlagSurvivalPlugin.Log; if (log2 != null) { log2.LogWarning((object)("[가마백업] SummonHelicopter Prefix — 가마 데이터 강제 백업 완료 " + $"(curSeg={currentSegmentIndex}, GetCurrentBiome='{arg}', GetCurrentBiomeTitle='{arg2}', " + "백업 라벨=가마/TheKiln)")); } } catch (Exception ex) { ManualLogSource log3 = FlagSurvivalPlugin.Log; if (log3 != null) { log3.LogError((object)("[가마백업] SummonHelicopter Prefix 예외: " + ex.Message + "\n" + ex.StackTrace)); } } } } [HarmonyPatch(typeof(PeakHandler), "EndCutscene")] public static class Patch_EndCutscene_HideUI { [HarmonyPrefix] public static void Prefix() { try { FlagEndCutsceneState.IsActive = true; ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogWarning((object)"[v_cs2] EndCutscene Prefix — 엔드 컷씬 시작, FixedHUD/LeaderboardHUD 숨김 플래그 set (헬기 로프 잡고 컷씬 진입 시점, Airport 도착 시 자동 해제)"); } } catch (Exception ex) { ManualLogSource log2 = FlagSurvivalPlugin.Log; if (log2 != null) { log2.LogError((object)("[v_cs2] EndCutscene Prefix 예외: " + ex.Message)); } } } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.sol.peak.flagsurvival.animatorprotect", "Cutscene Animator Protect", "1.0.0")] public class FlagCutsceneAnimatorProtectPlugin : BaseUnityPlugin { [HarmonyPatch(typeof(PeakHandler), "EndCutscene")] public static class Patch_EndCutscene_ProtectLocalAnimator { [HarmonyPostfix] public static void Postfix() { //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Expected O, but got Unknown if (FlagSurvivalNetwork.CurrentMultiplayerMode != FlagSurvivalNetwork.MultiplayerMode.PvP) { return; } try { Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null || localCharacter.refs == null) { return; } FieldInfo field = ((object)localCharacter.refs).GetType().GetField("animator"); if (field == null) { return; } object? value = field.GetValue(localCharacter.refs); Component val = (Component)((value is Component) ? value : null); if ((Object)(object)val == (Object)null) { return; } GameObject gameObject = val.gameObject; Transform parent = gameObject.transform.parent; string text = (((Object)(object)parent != (Object)null) ? ((Object)parent).name : "null"); if ((Object)(object)parent != (Object)(object)((Component)localCharacter).transform) { gameObject.transform.SetParent(((Component)localCharacter).transform, true); ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogWarning((object)("[AnimatorProtect] [v19] Scout.parent 복원: " + text + " → " + (((Object)(object)gameObject.transform.parent != (Object)null) ? ((Object)gameObject.transform.parent).name : "null"))); } } gameObject.SetActive(true); Behaviour val2 = (Behaviour)(object)((val is Behaviour) ? val : null); if ((Object)(object)val2 != (Object)null && !val2.enabled) { val2.enabled = true; } try { MethodInfo method = ((object)val).GetType().GetMethod("Rebind", Type.EmptyTypes); if (method != null) { method.Invoke(val, null); ManualLogSource log2 = FlagSurvivalPlugin.Log; if (log2 != null) { log2.LogWarning((object)"[AnimatorProtect] [v119] Animator.Rebind() — PlayableGraph 재초기화 (정상 모션 복원)"); } } else { ManualLogSource log3 = FlagSurvivalPlugin.Log; if (log3 != null) { log3.LogWarning((object)"[AnimatorProtect] [v119] Animator.Rebind 메서드 못 찾음"); } } } catch (Exception ex) { ManualLogSource log4 = FlagSurvivalPlugin.Log; if (log4 != null) { log4.LogError((object)("[AnimatorProtect] [v119] Rebind 예외: " + ex.Message)); } } int num = 0; foreach (Transform item in gameObject.transform) { Transform val3 = item; if ((Object)(object)val3 != (Object)null && (Object)(object)((Component)val3).gameObject != (Object)null && !((Component)val3).gameObject.activeSelf) { ((Component)val3).gameObject.SetActive(true); num++; } } SkinnedMeshRenderer[] componentsInChildren = gameObject.GetComponentsInChildren<SkinnedMeshRenderer>(true); int num2 = 0; int num3 = 0; SkinnedMeshRenderer[] array = componentsInChildren; foreach (SkinnedMeshRenderer val4 in array) { if ((Object)(object)val4 != (Object)null && !((Renderer)val4).enabled) { ((Renderer)val4).enabled = true; num2++; } if (!((Object)(object)val4 != (Object)null) || ((Renderer)val4).materials == null) { continue; } Material[] materials = ((Renderer)val4).materials; foreach (Material val5 in materials) { if ((Object)(object)val5 != (Object)null && val5.HasProperty("_VertexGhost")) { val5.SetFloat("_VertexGhost", 0f); num3++; } } } ManualLogSource log5 = FlagSurvivalPlugin.Log; if (log5 != null) { log5.LogWarning((object)($"[AnimatorProtect] EndCutscene Postfix — Scout 활성, 자식 {num}개 활성, " + $"SkinnedMeshRenderer {num2}/{componentsInChildren.Length}개 enabled=true, " + $"_VertexGhost=0 {num3}개 강제")); } try { CharacterRagdoll componentInChildren = ((Component)localCharacter).GetComponentInChildren<CharacterRagdoll>(true); if (!((Object)(object)componentInChildren != (Object)null)) { return; } componentInChildren.ToggleKinematic(false); int num4 = 0; if (componentInChildren.partList != null) { foreach (Bodypart part in componentInChildren.partList) { if ((Object)(object)part != (Object)null && (Object)(object)part.Rig != (Object)null) { part.Rig.useGravity = true; num4++; } } } ManualLogSource log6 = FlagSurvivalPlugin.Log; if (log6 != null) { log6.LogWarning((object)$"[AnimatorProtect] [v16] ToggleKinematic(false) + useGravity=true {num4}개 강제 — 정상 물리 복원"); } } catch (Exception ex2) { ManualLogSource log7 = FlagSurvivalPlugin.Log; if (log7 != null) { log7.LogError((object)("[AnimatorProtect] v16 예외: " + ex2.Message)); } } } catch (Exception ex3) { ManualLogSource log8 = FlagSurvivalPlugin.Log; if (log8 != null) { log8.LogError((object)("[AnimatorProtect] Postfix 예외: " + ex3.Message + "\n" + ex3.StackTrace)); } } } } [HarmonyPatch(typeof(PeakHandler), "EndCutscene")] public static class Patch_EndCutscene_Diag { [CompilerGenerated] private sealed class <DiagAfterCutscene>d__1 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; private PeakHandler <ph>5__2; private int <totalTicks>5__3; private int <tick>5__4; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DiagAfterCutscene>d__1(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <ph>5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_03ae: Unknown result type (might be due to invalid IL or missing references) //IL_03b8: Expected O, but got Unknown //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_02e4: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Unknown result type (might be due to invalid IL or missing references) //IL_032d: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSecondsRealtime(0.5f); <>1__state = 1; return true; case 1: <>1__state = -1; <ph>5__2 = Singleton<PeakHandler>.Instance; <totalTicks>5__3 = 150; <tick>5__4 = 0; break; case 2: <>1__state = -1; <tick>5__4++; break; } if (<tick>5__4 < <totalTicks>5__3) { float num = (float)<tick>5__4 * 0.2f; Character localCharacter = Character.localCharacter; if ((Object)(object)<ph>5__2 != (Object)null) { string text = ""; if ((Object)(object)<ph>5__2.peakSequence != (Object)null) { Vector3 position = <ph>5__2.peakSequence.transform.position; text += $"peakSeq=({position.x:F1},{position.y:F1},{position.z:F1}) "; } if ((Object)(object)<ph>5__2.endCutscene != (Object)null) { Vector3 position2 = <ph>5__2.endCutscene.transform.position; text += $"endCut=({position2.x:F1},{position2.y:F1},{position2.z:F1}) "; } if ((Object)(object)<ph>5__2.firstCutsceneScout != (Object)null) { Vector3 position3 = ((Component)<ph>5__2.firstCutsceneScout).transform.position; text += $"fakeScout=({position3.x:F1},{position3.y:F1},{position3.z:F1})"; } if (!string.IsNullOrEmpty(text)) { ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogInfo((object)$"[Diag t={num:F1}s] {text}"); } } } if ((Object)(object)localCharacter != (Object)null && (Object)(object)((Component)localCharacter).transform != (Object)null) { Transform transform = ((Component)localCharacter).transform; ManualLogSource log2 = FlagSurvivalPlugin.Log; if (log2 != null) { log2.LogInfo((object)$"[Diag t={num:F1}s] localChar pos=({transform.position.x:F1},{transform.position.y:F1},{transform.position.z:F1})"); } try { CharacterRagdoll componentInChildren = ((Component)localCharacter).GetComponentInChildren<CharacterRagdoll>(true); if ((Object)(object)componentInChildren != (Object)null && componentInChildren.partDict != null && componentInChildren.partDict.TryGetValue((BodypartType)0, out var value) && (Object)(object)value != (Object)null && (Object)(object)value.Rig != (Object)null) { Transform transform2 = ((Component)value).transform; ManualLogSource log3 = FlagSurvivalPlugin.Log; if (log3 != null) { log3.LogInfo((object)($"[Diag t={num:F1}s] hip pos=({transform2.position.x:F1},{transform2.position.y:F1},{transform2.position.z:F1}) " + $"vel=({value.Rig.linearVelocity.x:F1},{value.Rig.linearVelocity.y:F1},{value.Rig.linearVelocity.z:F1}) " + $"kinematic={value.Rig.isKinematic} gravity={value.Rig.useGravity}")); } } } catch { } } <>2__current = (object)new WaitForSecondsRealtime(0.2f); <>1__state = 2; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [HarmonyPostfix] public static void Postfix(PeakHandler __instance) { if (!((Object)(object)__instance == (Object)null) && FlagSurvivalNetwork.CurrentMultiplayerMode == FlagSurvivalNetwork.MultiplayerMode.PvP) { ((MonoBehaviour)__instance).StartCoroutine(DiagAfterCutscene()); } } [IteratorStateMachine(typeof(<DiagAfterCutscene>d__1))] private static IEnumerator DiagAfterCutscene() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DiagAfterCutscene>d__1(0); } } [HarmonyPatch(typeof(CharacterRagdoll), "FixedUpdate")] public static class Patch_CharacterRagdoll_FixedUpdate { private static FieldInfo _firstFrameField; private static FieldInfo _characterField; private static MethodInfo _setPhysicsMats; private static MethodInfo _rotateCharacter; private static MethodInfo _saveAdditional; private static MethodInfo _resetRotation; private static FieldInfo _ikRigBuilderField; private static MethodInfo _ikSyncLayers; private static MethodInfo _ikEvaluate; private static FieldInfo _animationsField; private static MethodInfo _prepIK; private static MethodInfo _configureIK; [HarmonyPrefix] public static bool Prefix(CharacterRagdoll __instance) { if (FlagSurvivalNetwork.CurrentMultiplayerMode != FlagSurvivalNetwork.MultiplayerMode.PvP) { return true; } PeakHandler instance = Singleton<PeakHandler>.Instance; if ((Object)(object)instance != (Object)null && instance.isPlayingCinematic && (Object)(object)__instance != (Object)null) { if (_characterField == null) { _characterField = typeof(CharacterRagdoll).GetField("character", BindingFlags.Instance | BindingFlags.NonPublic); } object? obj = _characterField?.GetValue(__instance); Character val = (Character)((obj is Character) ? obj : null); if ((Object)(object)val != (Object)null && (Object)(object)val == (Object)(object)Character.localCharacter) { return true; } } PeakHandler instance2 = Singleton<PeakHandler>.Instance; if ((Object)(object)instance2 == (Object)null || !instance2.isPlayingCinematic) { return true; } if ((Object)(object)__instance == (Object)null) { return true; } try { if (_firstFrameField == null) { Type typeFromHandle = typeof(CharacterRagdoll); _firstFrameField = typeFromHandle.GetField("firstFrame", BindingFlags.Instance | BindingFlags.NonPublic); _characterField = typeFromHandle.GetField("character", BindingFlags.Instance | BindingFlags.NonPublic); _setPhysicsMats = typeFromHandle.GetMethod("SetPhysicsMats", BindingFlags.Instance | BindingFlags.NonPublic); _rotateCharacter = typeFromHandle.GetMethod("RotateCharacter", BindingFlags.Instance | BindingFlags.NonPublic); _saveAdditional = typeFromHandle.GetMethod("SaveAdditionalTransformPositions", BindingFlags.Instance | BindingFlags.NonPublic); _resetRotation = typeFromHandle.GetMethod("ResetRotation", BindingFlags.Instance | BindingFlags.NonPublic); } object? obj2 = _characterField?.GetValue(__instance); Character val2 = (Character)((obj2 is Character) ? obj2 : null); if ((Object)(object)val2 == (Object)null || (Object)(object)val2 != (Object)(object)Character.localCharacter) { return true; } _setPhysicsMats?.Invoke(__instance, null); if ((bool)(_firstFrameField?.GetValue(__instance) ?? ((object)false))) { _firstFrameField?.SetValue(__instance, false); return false; } if (val2.refs != null && (Object)(object)val2.data != (Object)null && (Object)(object)val2.data.currentItem != (Object)null) { if (_animationsField == null) { _animationsField = ((object)val2.refs).GetType().GetField("animations"); } object obj3 = _animationsField?.GetValue(val2.refs); if (obj3 != null) { if (_prepIK == null) { _prepIK = obj3.GetType().GetMethod("PrepIK"); } _prepIK?.Invoke(obj3, null); } } _rotateCharacter?.Invoke(__instance, null); if (val2.refs != null) { if (_ikRigBuilderField == null) { _ikRigBuilderField = ((object)val2.refs).GetType().GetField("ikRigBuilder"); } object obj4 = _ikRigBuilderField?.GetValue(val2.refs); if (obj4 != null) { if (_ikSyncLayers == null) { _ikSyncLayers = obj4.GetType().GetMethod("SyncLayers"); _ikEvaluate = obj4.GetType().GetMethod("Evaluate", new Type[1] { typeof(float) }); } _ikSyncLayers?.Invoke(obj4, null); _ikEvaluate?.Invoke(obj4, new object[1] { Time.fixedDeltaTime }); } } if (_animationsField != null && val2.refs != null) { object value = _animationsField.GetValue(val2.refs); if (value != null) { if (_configureIK == null) { _configureIK = value.GetType().GetMethod("ConfigureIK"); } _configureIK?.Invoke(value, null); } } if (__instance.partList != null) { for (int i = 0; i < __instance.partList.Count; i++) { if ((Object)(object)__instance.partList[i] != (Object)null) { __instance.partList[i].SaveAnimationData(); } } } _saveAdditional?.Invoke(__instance, null); _resetRotation?.Invoke(__instance, null); if (__instance.partList != null) { for (int j = 0; j < __instance.partList.Count; j++) { if ((Object)(object)__instance.partList[j] != (Object)null) { __instance.partList[j].ResetTransform(); } } } return false; } catch (Exception ex) { ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogError((object)("[Patch_CharacterRagdoll_FixedUpdate] 예외 → 원본 fallback: " + ex.GetType().Name + ": " + ex.Message)); } return true; } } } [HarmonyPatch(typeof(CharacterMovement), "FixedUpdate")] public static class Patch_CharacterMovement_FixedUpdate { private static FieldInfo _charField; [HarmonyPostfix] public static void Postfix(CharacterMovement __instance) { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || FlagSurvivalNetwork.CurrentMultiplayerMode != FlagSurvivalNetwork.MultiplayerMode.PvP) { return; } PeakHandler instance = Singleton<PeakHandler>.Instance; if ((Object)(object)instance == (Object)null || !instance.isPlayingCinematic) { return; } try { if (_charField == null) { _charField = typeof(CharacterMovement).GetField("character", BindingFlags.Instance | BindingFlags.NonPublic); } object? obj = _charField?.GetValue(__instance); Character val = (Character)((obj is Character) ? obj : null); if ((Object)(object)val == (Object)null || (Object)(object)val != (Object)(object)Character.localCharacter || val.refs == null || (Object)(object)val.refs.ragdoll == (Object)null || val.refs.ragdoll.partList == null) { return; } Vector3 val2 = Physics.gravity / 2f; foreach (Bodypart part in val.refs.ragdoll.partList) { if (!((Object)(object)part == (Object)null) && !((Object)(object)part.Rig == (Object)null) && !part.Rig.isKinematic) { part.Rig.useGravity = false; part.Rig.AddForce(val2, (ForceMode)5); } } } catch { } } } public class TransformProtectTick : MonoBehaviour { private static TransformProtectTick _instance; private FieldInfo _animatorField; private int _parentFixCount; private int _scoutParentFixCount; private int _velocityClampCount; private float _logTimer; public static void EnsureInstance() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if (!((Object)(object)_instance != (Object)null)) { GameObject val = new GameObject("FlagSurvival_TransformProtect"); Object.DontDestroyOnLoad((Object)val); _instance = val.AddComponent<TransformProtectTick>(); ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogInfo((object)"[TransformProtect] v24 활성 — 매 프레임 상속 끊기 + velocity.y 양수 차단"); } } } private void LateUpdate() { PeakHandler instance = Singleton<PeakHandler>.Instance; if ((Object)(object)instance == (Object)null || !instance.isPlayingCinematic) { return; } List<Character> allCharacters = Character.AllCharacters; if (allCharacters == null) { return; } try { foreach (Character item in allCharacters) { if ((Object)(object)item == (Object)null || (Object)(object)((Component)item).transform == (Object)null) { continue; } if ((Object)(object)((Component)item).transform.parent != (Object)null) { ((Component)item).transform.SetParent((Transform)null, true); _parentFixCount++; } if (item.refs != null) { if (_animatorField == null) { _animatorField = ((object)item.refs).GetType().GetField("animator"); } object? obj = _animatorField?.GetValue(item.refs); Component val = (Component)((obj is Component) ? obj : null); if ((Object)(object)val != (Object)null && (Object)(object)val.transform.parent != (Object)(object)((Component)item).transform) { val.transform.SetParent(((Component)item).transform, true); _scoutParentFixCount++; } } } _logTimer += Time.unscaledDeltaTime; if (!(_logTimer >= 1f)) { return; } if (_parentFixCount > 0 || _scoutParentFixCount > 0 || _velocityClampCount > 0) { ManualLogSource log = FlagSurvivalPlugin.Log; if (log != null) { log.LogWarning((object)($"[TransformProtect] 1초 누적: parent끊기 {_parentFixCount}회, " + $"Scout.parent복원 {_scoutParentFixCount}회, velocity.y차단 {_velocityClampCount}회")); } } _parentFixCount = 0; _scoutParentFixCount = 0; _velocityClampCount = 0; _logTimer = 0f; } catch (Exception ex) { ManualLogSource log2 = FlagSurvivalPlugin.Log; if (log2 != null) { log2.LogError((object)("[TransformProtect] 예외: " + ex.Message)); } } } } [HarmonyPatch(typeof(Pe