using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using Splatform; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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 Captain_territorial { public static class SimpleVFX { private class AutoCleanup : MonoBehaviour { private float _delay; public static void Schedule(GameObject target, float delay) { if (!((Object)(object)target == (Object)null)) { target.AddComponent()._delay = delay; } } private void Start() { ((MonoBehaviour)this).StartCoroutine(Run()); } private IEnumerator Run() { yield return (object)new WaitForSeconds(_delay); ((Component)this).gameObject.SetActive(false); Object.Destroy((Object)(object)((Component)this).gameObject); } } private static GameObject _cachedAuraPrefab; private static bool _initialized; public static void Initialize() { if (!_initialized) { _initialized = true; _cachedAuraPrefab = LoadEmbeddedPrefab("buff_03a_aura"); } } private static GameObject LoadEmbeddedPrefab(string vfxName) { try { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = null; string[] manifestResourceNames = executingAssembly.GetManifestResourceNames(); foreach (string text2 in manifestResourceNames) { if (text2.EndsWith("." + vfxName)) { text = text2; break; } } if (text == null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[SimpleVFX] '" + vfxName + "' 리소스 없음")); } return null; } AssetBundle val; using (Stream stream = executingAssembly.GetManifestResourceStream(text)) { if (stream == null) { return null; } val = AssetBundle.LoadFromStream(stream); } GameObject[] array = (((Object)(object)val != (Object)null) ? val.LoadAllAssets() : null); return (array != null && array.Length != 0) ? array[0] : null; } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogError((object)("[SimpleVFX] '" + vfxName + "' 로드 실패: " + ex.Message)); } return null; } } public static GameObject PlayAura(Vector3 position, float duration) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_cachedAuraPrefab == (Object)null) { return null; } GameObject val = InstantiateWithoutNetworking(_cachedAuraPrefab, position); AutoCleanup.Schedule(val, duration); return val; } public static void PlaySound(string sfxName, Vector3 position, float duration) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) PlayZNetScenePrefab(sfxName, position, duration, "sfx"); } public static void PlayVFX(string vfxName, Vector3 position, float duration) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) PlayZNetScenePrefab(vfxName, position, duration, "vfx"); } private static void PlayZNetScenePrefab(string prefabName, Vector3 position, float duration, string logTag) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(prefabName) || (Object)(object)ZNetScene.instance == (Object)null) { return; } GameObject prefab = ZNetScene.instance.GetPrefab(prefabName); if ((Object)(object)prefab == (Object)null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[SimpleVFX] " + logTag + " '" + prefabName + "' 프리팹 없음")); } } else { GameObject target = InstantiateWithoutNetworking(prefab, position); AutoCleanup.Schedule(target, duration); } } private static GameObject InstantiateWithoutNetworking(GameObject prefab, Vector3 position) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) bool activeSelf = prefab.activeSelf; prefab.SetActive(false); GameObject val = Object.Instantiate(prefab, position, Quaternion.identity); prefab.SetActive(activeSelf); ZNetView component = val.GetComponent(); if ((Object)(object)component != (Object)null) { Object.DestroyImmediate((Object)(object)component); } ZSyncTransform component2 = val.GetComponent(); if ((Object)(object)component2 != (Object)null) { Object.DestroyImmediate((Object)(object)component2); } val.SetActive(true); return val; } } public static class VFXManager { public static bool VFX_ENABLED = true; private static readonly Vector3[] ConsumeAuraOffsets = (Vector3[])(object)new Vector3[3] { new Vector3(-0.3f, 1.5f, 0f), new Vector3(0f, 1.8f, 0f), new Vector3(0.3f, 1.5f, 0f) }; private const float ConsumeEffectDuration = 3f; private const float UpgradeEffectDuration = 3f; public static void Initialize() { SimpleVFX.Initialize(); } public static void PlayVFXMultiplayer(string vfxName, string soundName, Vector3 position, float destroyAfter = 3f) { //IL_001c: 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) if (VFX_ENABLED) { if (!string.IsNullOrEmpty(vfxName)) { SimpleVFX.PlayAura(position, destroyAfter); } if (!string.IsNullOrEmpty(soundName)) { SimpleVFX.PlaySound(soundName, position, destroyAfter); } } } public static void PlayIntrusionAlert(Vector3 position) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (VFX_ENABLED) { SimpleVFX.PlaySound("sfx_morgen_alert", position, 2f); } } public static void PlayWardConsumeEffect(Transform wardTransform) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) if (VFX_ENABLED && !((Object)(object)wardTransform == (Object)null)) { Vector3[] consumeAuraOffsets = ConsumeAuraOffsets; foreach (Vector3 val in consumeAuraOffsets) { SimpleVFX.PlayAura(wardTransform.TransformPoint(val), 3f); } SimpleVFX.PlaySound("sfx_dverger_heal_finish", wardTransform.position, 3f); } } public static void PlayUpgradeEffect(Vector3 position) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (VFX_ENABLED) { SimpleVFX.PlayVFX("vfx_shieldgenerator_refuel", position, 3f); SimpleVFX.PlaySound("sfx_fader_bell", position, 3f); } } } [HarmonyPatch(typeof(Player), "TryPlacePiece")] public static class Patch_Player_TryPlacePiece { private static readonly string[] s_alwaysAllowedPieces = new string[7] { "piece_workbench", "portal_wood", "Cart", "Raft", "Karve", "VikingShip", "VikingShip_Ashlands" }; private static bool Prefix(Player __instance, ref bool __result) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) GameObject placementGhost = __instance.m_placementGhost; if ((Object)(object)placementGhost == (Object)null) { return true; } Vector3 position = placementGhost.transform.position; string name = ((Object)placementGhost).name; string[] array = s_alwaysAllowedPieces; foreach (string value in array) { if (name.Contains(value)) { return true; } } if (name.Contains("territoryward")) { if (!TerritoryConfig.Enabled.Value) { ((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_disabled", 0, (Sprite)null); __result = false; return false; } if (!TerritoryConfig.AdminBypass.Value && CountPlayerWards() >= TerritoryConfig.WardLimit.Value) { ((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_limit_reached", 0, (Sprite)null); __result = false; return false; } if (TerritoryWard.IsInsideActiveWard(position)) { ((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_no_overlap", 0, (Sprite)null); __result = false; return false; } return true; } if (!TerritoryWard.IsInsideActiveWard(position)) { string text = (TerritoryWard.IsInsideDeactivatedWard(position) ? "$territoryward_must_activate" : "$territoryward_no_build"); ((Character)Player.m_localPlayer).Message((MessageType)2, text, 0, (Sprite)null); __result = false; return false; } return true; } private static int CountPlayerWards() { if ((Object)(object)Player.m_localPlayer == (Object)null) { return 0; } long playerID = Player.m_localPlayer.GetPlayerID(); int num = 0; foreach (PrivateArea s_ward in TerritoryWard.s_wards) { if (!((Object)(object)s_ward == (Object)null)) { ZNetView component = ((Component)s_ward).GetComponent(); if ((Object)(object)component != (Object)null && component.IsValid() && component.GetZDO().GetLong("creator", 0L) == playerID) { num++; } } } return num; } } public static class TerritoryConfig { public struct FuelTier { public int Level; public string ItemA; public int AmountA; public string ItemB; public int AmountB; public string ItemC; public int AmountC; public float IntervalSeconds; } public struct UpgradeCostInfo { public string ItemA; public int ItemAAmount; public string ItemB; public int ItemBAmount; public int Coins; } public static ConfigEntry AdminBypass; public static ConfigEntry Enabled; public static ConfigEntry WardLimit; public static ConfigEntry UpgradeKey; public static ConfigEntry ShieldKey; public static ConfigEntry RangeRingKey; public static ConfigEntry FuelStorageKey; public static ConfigEntry Lv1Radius; public static ConfigEntry Lv1FuelA; public static ConfigEntry Lv1FuelAAmount; public static ConfigEntry Lv1FuelB; public static ConfigEntry Lv1FuelBAmount; public static ConfigEntry Lv1IntervalMinutes; public static ConfigEntry Lv2Radius; public static ConfigEntry Lv2FuelA; public static ConfigEntry Lv2FuelAAmount; public static ConfigEntry Lv2FuelB; public static ConfigEntry Lv2FuelBAmount; public static ConfigEntry Lv2IntervalMinutes; public static ConfigEntry Lv3Radius; public static ConfigEntry Lv3FuelA; public static ConfigEntry Lv3FuelAAmount; public static ConfigEntry Lv3FuelB; public static ConfigEntry Lv3FuelBAmount; public static ConfigEntry Lv3IntervalMinutes; public static ConfigEntry Lv4Radius; public static ConfigEntry Lv4FuelA; public static ConfigEntry Lv4FuelAAmount; public static ConfigEntry Lv4FuelB; public static ConfigEntry Lv4FuelBAmount; public static ConfigEntry Lv4IntervalMinutes; public static ConfigEntry Lv5Radius; public static ConfigEntry Lv5FuelA; public static ConfigEntry Lv5FuelAAmount; public static ConfigEntry Lv5FuelB; public static ConfigEntry Lv5FuelBAmount; public static ConfigEntry Lv5IntervalMinutes; public static ConfigEntry Lv6Radius; public static ConfigEntry Lv6FuelA; public static ConfigEntry Lv6FuelAAmount; public static ConfigEntry Lv6FuelB; public static ConfigEntry Lv6FuelBAmount; public static ConfigEntry Lv6FuelC; public static ConfigEntry Lv6FuelCAmount; public static ConfigEntry Lv6IntervalMinutes; public static ConfigEntry Lv7Radius; public static ConfigEntry Lv7FuelA; public static ConfigEntry Lv7FuelAAmount; public static ConfigEntry Lv7FuelB; public static ConfigEntry Lv7FuelBAmount; public static ConfigEntry Lv7IntervalMinutes; public static ConfigEntry Lv8Radius; public static ConfigEntry Lv8FuelA; public static ConfigEntry Lv8FuelAAmount; public static ConfigEntry Lv8FuelB; public static ConfigEntry Lv8FuelBAmount; public static ConfigEntry Lv8FuelC; public static ConfigEntry Lv8FuelCAmount; public static ConfigEntry Lv8IntervalMinutes; public static ConfigEntry Lv2UpgradeItemA; public static ConfigEntry Lv2UpgradeItemAAmount; public static ConfigEntry Lv2UpgradeItemB; public static ConfigEntry Lv2UpgradeItemBAmount; public static ConfigEntry Lv2UpgradeCoins; public static ConfigEntry Lv3UpgradeItemA; public static ConfigEntry Lv3UpgradeItemAAmount; public static ConfigEntry Lv3UpgradeItemB; public static ConfigEntry Lv3UpgradeItemBAmount; public static ConfigEntry Lv3UpgradeCoins; public static ConfigEntry Lv4UpgradeItemA; public static ConfigEntry Lv4UpgradeItemAAmount; public static ConfigEntry Lv4UpgradeItemB; public static ConfigEntry Lv4UpgradeItemBAmount; public static ConfigEntry Lv4UpgradeCoins; public static ConfigEntry Lv5UpgradeItemA; public static ConfigEntry Lv5UpgradeItemAAmount; public static ConfigEntry Lv5UpgradeItemB; public static ConfigEntry Lv5UpgradeItemBAmount; public static ConfigEntry Lv5UpgradeCoins; public static ConfigEntry Lv6UpgradeItemA; public static ConfigEntry Lv6UpgradeItemAAmount; public static ConfigEntry Lv6UpgradeItemB; public static ConfigEntry Lv6UpgradeItemBAmount; public static ConfigEntry Lv6UpgradeCoins; public static ConfigEntry Lv7UpgradeItemA; public static ConfigEntry Lv7UpgradeItemAAmount; public static ConfigEntry Lv7UpgradeItemB; public static ConfigEntry Lv7UpgradeItemBAmount; public static ConfigEntry Lv7UpgradeCoins; public static ConfigEntry Lv8UpgradeItemA; public static ConfigEntry Lv8UpgradeItemAAmount; public static ConfigEntry Lv8UpgradeItemB; public static ConfigEntry Lv8UpgradeItemBAmount; public static ConfigEntry Lv8UpgradeCoins; public static ConfigEntry DoorAutoCloseEnabled; public static ConfigEntry DoorAutoCloseDelay; public static ConfigEntry ShieldItemName; public static void Init(ConfigFile cfg) { AdminBypass = B("General", "admin_bypass", def: false, "관리자 전용: 켜면 설치 개수 제한·설치 재료비·업그레이드 재료/골드 비용을 모두 무시하고 즉시 설치·업그레이드할 수 있습니다 (연료 유지비는 그대로 적용됩니다).", 200); Enabled = B("General", "territorial_ward", def: true, "영토 와드 시스템 활성화 여부 (false = 비활성화)", 190); WardLimit = B("General", "ward_limit", 2, "캐릭터 1명당 설치 가능한 영토 와드 수", 180); DoorAutoCloseEnabled = B("General", "door_auto_close", def: true, "와드 구역 내 문 자동 닫힘 활성화", 170); DoorAutoCloseDelay = B("General", "door_auto_close_delay", 5f, "문 자동 닫힘 대기 시간 (초)", 160); ShieldItemName = B("General", "shield_item", "SurtlingCore", "Lv5+ 데미지 보호 소모 아이템 (프리팹명)", 150); UpgradeKey = B("General", "upgrade_key", (KeyCode)117, "영토 와드 업그레이드 키", 140); ShieldKey = B("General", "shield_key", (KeyCode)107, "Lv5+ 영토 보호 실드 활성화/비활성화 키", 130); RangeRingKey = B("General", "range_ring_key", (KeyCode)114, "범위 링 수동 토글 키", 120); FuelStorageKey = B("General", "fuel_storage_key", (KeyCode)113, "연료 창고 열기 키", 110); Lv1Radius = B("Level 1 - 초원", "radius", 10f, "레벨 1 반경 (미터)", 100); Lv1FuelA = B("Level 1 - 초원", "fuel_primary", "Wood", "레벨 1 주 연료 — 나무 (프리팹명)", 90); Lv1FuelAAmount = B("Level 1 - 초원", "fuel_primary_amount", 1, "레벨 1 주 연료 소모량", 89); Lv1FuelB = B("Level 1 - 초원", "fuel_secondary", "Resin", "레벨 1 보조 연료 — 수지 (프리팹명)", 88); Lv1FuelBAmount = B("Level 1 - 초원", "fuel_secondary_amount", 1, "레벨 1 보조 연료 소모량", 87); Lv1IntervalMinutes = B("Level 1 - 초원", "fuel_interval_minutes", 3f, "레벨 1 연료 소모 간격 (분)", 80); Lv1Radius.SettingChanged += delegate { TerritoryLocalization.RefreshWardDescription(); }; Lv1FuelA.SettingChanged += delegate { TerritoryLocalization.RefreshWardDescription(); }; Lv1FuelAAmount.SettingChanged += delegate { TerritoryLocalization.RefreshWardDescription(); }; Lv1FuelB.SettingChanged += delegate { TerritoryLocalization.RefreshWardDescription(); }; Lv1FuelBAmount.SettingChanged += delegate { TerritoryLocalization.RefreshWardDescription(); }; Lv1IntervalMinutes.SettingChanged += delegate { TerritoryLocalization.RefreshWardDescription(); }; Lv2Radius = B("Level 2 - 검은숲", "radius", 13f, "레벨 2 반경 (미터)", 100); Lv2FuelA = B("Level 2 - 검은숲", "fuel_primary", "RoundLog", "레벨 2 주 연료 — 원목 (프리팹명)", 90); Lv2FuelAAmount = B("Level 2 - 검은숲", "fuel_primary_amount", 1, "레벨 2 주 연료 소모량", 89); Lv2FuelB = B("Level 2 - 검은숲", "fuel_secondary", "Resin", "레벨 2 보조 연료 — 수지 (프리팹명)", 88); Lv2FuelBAmount = B("Level 2 - 검은숲", "fuel_secondary_amount", 1, "레벨 2 보조 연료 소모량", 87); Lv2IntervalMinutes = B("Level 2 - 검은숲", "fuel_interval_minutes", 4f, "레벨 2 연료 소모 간격 (분)", 80); Lv2UpgradeItemA = B("Level 2 - 검은숲", "upgrade_item_primary", "RoundLog", "Lv2 업그레이드 주 재료 (원목)", 70); Lv2UpgradeItemAAmount = B("Level 2 - 검은숲", "upgrade_item_primary_amount", 10, "Lv2 업그레이드 주 재료 수량", 69); Lv2UpgradeItemB = B("Level 2 - 검은숲", "upgrade_item_secondary", "GreydwarfEye", "Lv2 업그레이드 보조 재료 (그레이드워프 눈)", 68); Lv2UpgradeItemBAmount = B("Level 2 - 검은숲", "upgrade_item_secondary_amount", 5, "Lv2 업그레이드 보조 재료 수량", 67); Lv2UpgradeCoins = B("Level 2 - 검은숲", "upgrade_coins", 0, "Lv2 업그레이드 골드(Coins) 비용", 60); Lv3Radius = B("Level 3 - 늪지", "radius", 16f, "레벨 3 반경 (미터)", 100); Lv3FuelA = B("Level 3 - 늪지", "fuel_primary", "ElderBark", "레벨 3 주 연료 — 고대나무껍질 (프리팹명)", 90); Lv3FuelAAmount = B("Level 3 - 늪지", "fuel_primary_amount", 2, "레벨 3 주 연료 소모량", 89); Lv3FuelB = B("Level 3 - 늪지", "fuel_secondary", "Resin", "레벨 3 보조 연료 — 수지 (프리팹명)", 88); Lv3FuelBAmount = B("Level 3 - 늪지", "fuel_secondary_amount", 1, "레벨 3 보조 연료 소모량", 87); Lv3IntervalMinutes = B("Level 3 - 늪지", "fuel_interval_minutes", 5f, "레벨 3 연료 소모 간격 (분)", 80); Lv3UpgradeItemA = B("Level 3 - 늪지", "upgrade_item_primary", "ElderBark", "Lv3 업그레이드 주 재료 (고대나무껍질)", 70); Lv3UpgradeItemAAmount = B("Level 3 - 늪지", "upgrade_item_primary_amount", 15, "Lv3 업그레이드 주 재료 수량", 69); Lv3UpgradeItemB = B("Level 3 - 늪지", "upgrade_item_secondary", "Entrails", "Lv3 업그레이드 보조 재료 (창자)", 68); Lv3UpgradeItemBAmount = B("Level 3 - 늪지", "upgrade_item_secondary_amount", 8, "Lv3 업그레이드 보조 재료 수량", 67); Lv3UpgradeCoins = B("Level 3 - 늪지", "upgrade_coins", 1000, "Lv3 업그레이드 골드(Coins) 비용", 60); Lv4Radius = B("Level 4 - 산", "radius", 19f, "레벨 4 반경 (미터)", 100); Lv4FuelA = B("Level 4 - 산", "fuel_primary", "Obsidian", "레벨 4 주 연료 — 흑요석 (산에는 지역 나무가 없어 대체) (프리팹명)", 90); Lv4FuelAAmount = B("Level 4 - 산", "fuel_primary_amount", 2, "레벨 4 주 연료 소모량", 89); Lv4FuelB = B("Level 4 - 산", "fuel_secondary", "Resin", "레벨 4 보조 연료 — 수지 (프리팹명)", 88); Lv4FuelBAmount = B("Level 4 - 산", "fuel_secondary_amount", 1, "레벨 4 보조 연료 소모량", 87); Lv4IntervalMinutes = B("Level 4 - 산", "fuel_interval_minutes", 6f, "레벨 4 연료 소모 간격 (분)", 80); Lv4UpgradeItemA = B("Level 4 - 산", "upgrade_item_primary", "FreezeGland", "Lv4 업그레이드 주 재료 (얼음 분비선)", 70); Lv4UpgradeItemAAmount = B("Level 4 - 산", "upgrade_item_primary_amount", 20, "Lv4 업그레이드 주 재료 수량", 69); Lv4UpgradeItemB = B("Level 4 - 산", "upgrade_item_secondary", "Obsidian", "Lv4 업그레이드 보조 재료 (흑요석)", 68); Lv4UpgradeItemBAmount = B("Level 4 - 산", "upgrade_item_secondary_amount", 11, "Lv4 업그레이드 보조 재료 수량", 67); Lv4UpgradeCoins = B("Level 4 - 산", "upgrade_coins", 2000, "Lv4 업그레이드 골드(Coins) 비용", 60); Lv5Radius = B("Level 5 - 평원", "radius", 22f, "레벨 5 반경 (미터)", 100); Lv5FuelA = B("Level 5 - 평원", "fuel_primary", "FineWood", "레벨 5 주 연료 — 경목 (프리팹명)", 90); Lv5FuelAAmount = B("Level 5 - 평원", "fuel_primary_amount", 3, "레벨 5 주 연료 소모량", 89); Lv5FuelB = B("Level 5 - 평원", "fuel_secondary", "Resin", "레벨 5 보조 연료 — 수지 (프리팹명)", 88); Lv5FuelBAmount = B("Level 5 - 평원", "fuel_secondary_amount", 1, "레벨 5 보조 연료 소모량", 87); Lv5IntervalMinutes = B("Level 5 - 평원", "fuel_interval_minutes", 7f, "레벨 5 연료 소모 간격 (분)", 80); Lv5UpgradeItemA = B("Level 5 - 평원", "upgrade_item_primary", "Barley", "Lv5 업그레이드 주 재료 (보리)", 70); Lv5UpgradeItemAAmount = B("Level 5 - 평원", "upgrade_item_primary_amount", 25, "Lv5 업그레이드 주 재료 수량", 69); Lv5UpgradeItemB = B("Level 5 - 평원", "upgrade_item_secondary", "Tar", "Lv5 업그레이드 보조 재료 (타르)", 68); Lv5UpgradeItemBAmount = B("Level 5 - 평원", "upgrade_item_secondary_amount", 14, "Lv5 업그레이드 보조 재료 수량", 67); Lv5UpgradeCoins = B("Level 5 - 평원", "upgrade_coins", 2500, "Lv5 업그레이드 골드(Coins) 비용", 60); Lv6Radius = B("Level 6 - 바다", "radius", 25f, "레벨 6 반경 (미터)", 100); Lv6FuelA = B("Level 6 - 바다", "fuel_primary", "Wood", "레벨 6 주 연료 — 나무 (바다에는 지역 나무가 없어 나무+원목으로 대체) (프리팹명)", 90); Lv6FuelAAmount = B("Level 6 - 바다", "fuel_primary_amount", 2, "레벨 6 주 연료 소모량", 89); Lv6FuelB = B("Level 6 - 바다", "fuel_secondary", "Resin", "레벨 6 보조 연료 — 수지 (프리팹명)", 88); Lv6FuelBAmount = B("Level 6 - 바다", "fuel_secondary_amount", 1, "레벨 6 보조 연료 소모량", 87); Lv6FuelC = B("Level 6 - 바다", "fuel_tertiary", "RoundLog", "레벨 6 추가 연료 — 원목 (프리팹명, 비워두면 미사용)", 86); Lv6FuelCAmount = B("Level 6 - 바다", "fuel_tertiary_amount", 1, "레벨 6 추가 연료 소모량", 85); Lv6IntervalMinutes = B("Level 6 - 바다", "fuel_interval_minutes", 8f, "레벨 6 연료 소모 간격 (분)", 80); Lv6UpgradeItemA = B("Level 6 - 바다", "upgrade_item_primary", "Chitin", "Lv6 업그레이드 주 재료 (키틴)", 70); Lv6UpgradeItemAAmount = B("Level 6 - 바다", "upgrade_item_primary_amount", 30, "Lv6 업그레이드 주 재료 수량", 69); Lv6UpgradeItemB = B("Level 6 - 바다", "upgrade_item_secondary", "Ooze", "Lv6 업그레이드 보조 재료 (점액)", 68); Lv6UpgradeItemBAmount = B("Level 6 - 바다", "upgrade_item_secondary_amount", 17, "Lv6 업그레이드 보조 재료 수량", 67); Lv6UpgradeCoins = B("Level 6 - 바다", "upgrade_coins", 3000, "Lv6 업그레이드 골드(Coins) 비용", 60); Lv7Radius = B("Level 7 - 미스트랜드", "radius", 28f, "레벨 7 반경 (미터)", 100); Lv7FuelA = B("Level 7 - 미스트랜드", "fuel_primary", "YggdrasilWood", "레벨 7 주 연료 — 이그드라실 나무 (프리팹명)", 90); Lv7FuelAAmount = B("Level 7 - 미스트랜드", "fuel_primary_amount", 4, "레벨 7 주 연료 소모량", 89); Lv7FuelB = B("Level 7 - 미스트랜드", "fuel_secondary", "Resin", "레벨 7 보조 연료 — 수지 (프리팹명)", 88); Lv7FuelBAmount = B("Level 7 - 미스트랜드", "fuel_secondary_amount", 1, "레벨 7 보조 연료 소모량", 87); Lv7IntervalMinutes = B("Level 7 - 미스트랜드", "fuel_interval_minutes", 9f, "레벨 7 연료 소모 간격 (분)", 80); Lv7UpgradeItemA = B("Level 7 - 미스트랜드", "upgrade_item_primary", "YggdrasilWood", "Lv7 업그레이드 주 재료 (이그드라실 나무)", 70); Lv7UpgradeItemAAmount = B("Level 7 - 미스트랜드", "upgrade_item_primary_amount", 35, "Lv7 업그레이드 주 재료 수량", 69); Lv7UpgradeItemB = B("Level 7 - 미스트랜드", "upgrade_item_secondary", "JotunPuffs", "Lv7 업그레이드 보조 재료 (요툰 버섯)", 68); Lv7UpgradeItemBAmount = B("Level 7 - 미스트랜드", "upgrade_item_secondary_amount", 20, "Lv7 업그레이드 보조 재료 수량", 67); Lv7UpgradeCoins = B("Level 7 - 미스트랜드", "upgrade_coins", 4000, "Lv7 업그레이드 골드(Coins) 비용", 60); Lv8Radius = B("Level 8 - 애쉬랜드", "radius", 30f, "레벨 8 반경 (미터)", 100); Lv8FuelA = B("Level 8 - 애쉬랜드", "fuel_primary", "Wood", "레벨 8 주 연료 — 나무 (애쉬랜드에는 지역 나무가 없어 나무+이그드라실 나무로 대체) (프리팹명)", 90); Lv8FuelAAmount = B("Level 8 - 애쉬랜드", "fuel_primary_amount", 3, "레벨 8 주 연료 소모량", 89); Lv8FuelB = B("Level 8 - 애쉬랜드", "fuel_secondary", "Resin", "레벨 8 보조 연료 — 수지 (프리팹명)", 88); Lv8FuelBAmount = B("Level 8 - 애쉬랜드", "fuel_secondary_amount", 1, "레벨 8 보조 연료 소모량", 87); Lv8FuelC = B("Level 8 - 애쉬랜드", "fuel_tertiary", "YggdrasilWood", "레벨 8 추가 연료 — 이그드라실 나무 (프리팹명, 비워두면 미사용)", 86); Lv8FuelCAmount = B("Level 8 - 애쉬랜드", "fuel_tertiary_amount", 1, "레벨 8 추가 연료 소모량", 85); Lv8IntervalMinutes = B("Level 8 - 애쉬랜드", "fuel_interval_minutes", 10f, "레벨 8 연료 소모 간격 (분)", 80); Lv8UpgradeItemA = B("Level 8 - 애쉬랜드", "upgrade_item_primary", "CharredBone", "Lv8 업그레이드 주 재료 (불탄 뼈)", 70); Lv8UpgradeItemAAmount = B("Level 8 - 애쉬랜드", "upgrade_item_primary_amount", 40, "Lv8 업그레이드 주 재료 수량", 69); Lv8UpgradeItemB = B("Level 8 - 애쉬랜드", "upgrade_item_secondary", "Grausten", "Lv8 업그레이드 보조 재료 (그라우스텐 돌)", 68); Lv8UpgradeItemBAmount = B("Level 8 - 애쉬랜드", "upgrade_item_secondary_amount", 23, "Lv8 업그레이드 보조 재료 수량", 67); Lv8UpgradeCoins = B("Level 8 - 애쉬랜드", "upgrade_coins", 5000, "Lv8 업그레이드 골드(Coins) 비용", 60); ConfigEntry B(string section, string key, T def, string desc, int order = 0) { //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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown return cfg.Bind(section, key, def, new ConfigDescription(desc, (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, Order = order } })); } } public static float GetRadius(int level) { return level switch { 2 => Lv2Radius.Value, 3 => Lv3Radius.Value, 4 => Lv4Radius.Value, 5 => Lv5Radius.Value, 6 => Lv6Radius.Value, 7 => Lv7Radius.Value, 8 => Lv8Radius.Value, _ => Lv1Radius.Value, }; } private static FuelTier GetTier(int level) { return level switch { 2 => new FuelTier { Level = 2, ItemA = Lv2FuelA.Value, AmountA = Lv2FuelAAmount.Value, ItemB = Lv2FuelB.Value, AmountB = Lv2FuelBAmount.Value, IntervalSeconds = Lv2IntervalMinutes.Value * 60f }, 3 => new FuelTier { Level = 3, ItemA = Lv3FuelA.Value, AmountA = Lv3FuelAAmount.Value, ItemB = Lv3FuelB.Value, AmountB = Lv3FuelBAmount.Value, IntervalSeconds = Lv3IntervalMinutes.Value * 60f }, 4 => new FuelTier { Level = 4, ItemA = Lv4FuelA.Value, AmountA = Lv4FuelAAmount.Value, ItemB = Lv4FuelB.Value, AmountB = Lv4FuelBAmount.Value, IntervalSeconds = Lv4IntervalMinutes.Value * 60f }, 5 => new FuelTier { Level = 5, ItemA = Lv5FuelA.Value, AmountA = Lv5FuelAAmount.Value, ItemB = Lv5FuelB.Value, AmountB = Lv5FuelBAmount.Value, IntervalSeconds = Lv5IntervalMinutes.Value * 60f }, 6 => new FuelTier { Level = 6, ItemA = Lv6FuelA.Value, AmountA = Lv6FuelAAmount.Value, ItemB = Lv6FuelB.Value, AmountB = Lv6FuelBAmount.Value, ItemC = Lv6FuelC.Value, AmountC = Lv6FuelCAmount.Value, IntervalSeconds = Lv6IntervalMinutes.Value * 60f }, 7 => new FuelTier { Level = 7, ItemA = Lv7FuelA.Value, AmountA = Lv7FuelAAmount.Value, ItemB = Lv7FuelB.Value, AmountB = Lv7FuelBAmount.Value, IntervalSeconds = Lv7IntervalMinutes.Value * 60f }, 8 => new FuelTier { Level = 8, ItemA = Lv8FuelA.Value, AmountA = Lv8FuelAAmount.Value, ItemB = Lv8FuelB.Value, AmountB = Lv8FuelBAmount.Value, ItemC = Lv8FuelC.Value, AmountC = Lv8FuelCAmount.Value, IntervalSeconds = Lv8IntervalMinutes.Value * 60f }, _ => new FuelTier { Level = 1, ItemA = Lv1FuelA.Value, AmountA = Lv1FuelAAmount.Value, ItemB = Lv1FuelB.Value, AmountB = Lv1FuelBAmount.Value, IntervalSeconds = Lv1IntervalMinutes.Value * 60f }, }; } public static List GetFuelTiers(int uptoLevel) { List list = new List(2) { GetTier(1) }; if (uptoLevel > 1) { list.Add(GetTier(uptoLevel)); } return list; } public static UpgradeCostInfo GetUpgradeCost(int targetLevel) { return targetLevel switch { 2 => new UpgradeCostInfo { ItemA = Lv2UpgradeItemA.Value, ItemAAmount = Lv2UpgradeItemAAmount.Value, ItemB = Lv2UpgradeItemB.Value, ItemBAmount = Lv2UpgradeItemBAmount.Value, Coins = Lv2UpgradeCoins.Value }, 3 => new UpgradeCostInfo { ItemA = Lv3UpgradeItemA.Value, ItemAAmount = Lv3UpgradeItemAAmount.Value, ItemB = Lv3UpgradeItemB.Value, ItemBAmount = Lv3UpgradeItemBAmount.Value, Coins = Lv3UpgradeCoins.Value }, 4 => new UpgradeCostInfo { ItemA = Lv4UpgradeItemA.Value, ItemAAmount = Lv4UpgradeItemAAmount.Value, ItemB = Lv4UpgradeItemB.Value, ItemBAmount = Lv4UpgradeItemBAmount.Value, Coins = Lv4UpgradeCoins.Value }, 5 => new UpgradeCostInfo { ItemA = Lv5UpgradeItemA.Value, ItemAAmount = Lv5UpgradeItemAAmount.Value, ItemB = Lv5UpgradeItemB.Value, ItemBAmount = Lv5UpgradeItemBAmount.Value, Coins = Lv5UpgradeCoins.Value }, 6 => new UpgradeCostInfo { ItemA = Lv6UpgradeItemA.Value, ItemAAmount = Lv6UpgradeItemAAmount.Value, ItemB = Lv6UpgradeItemB.Value, ItemBAmount = Lv6UpgradeItemBAmount.Value, Coins = Lv6UpgradeCoins.Value }, 7 => new UpgradeCostInfo { ItemA = Lv7UpgradeItemA.Value, ItemAAmount = Lv7UpgradeItemAAmount.Value, ItemB = Lv7UpgradeItemB.Value, ItemBAmount = Lv7UpgradeItemBAmount.Value, Coins = Lv7UpgradeCoins.Value }, 8 => new UpgradeCostInfo { ItemA = Lv8UpgradeItemA.Value, ItemAAmount = Lv8UpgradeItemAAmount.Value, ItemB = Lv8UpgradeItemB.Value, ItemBAmount = Lv8UpgradeItemBAmount.Value, Coins = Lv8UpgradeCoins.Value }, _ => default(UpgradeCostInfo), }; } } [HarmonyPatch(typeof(DamageText), "AddInworldText")] public static class Patch_DamageText_RichText { internal static readonly HashSet SlowRiseFields = new HashSet(); private static void Postfix(DamageText __instance, string text) { if (!string.IsNullOrEmpty(text) && text.Contains(" __instance.m_textDuration) { Patch_DamageText_RichText.SlowRiseFields.Remove(worldText.m_textField); } } } } } [HarmonyPatch(typeof(Door), "Interact")] public static class Patch_Door_AutoClose { private static void Postfix(Door __instance) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) if (TerritoryConfig.DoorAutoCloseEnabled.Value && !((Object)(object)__instance.m_nview == (Object)null) && __instance.m_nview.IsOwner() && __instance.m_nview.GetZDO().GetInt("state", 0) != 0 && TerritoryWard.IsInsideActiveWard(((Component)__instance).transform.position)) { ((MonoBehaviour)__instance).StartCoroutine(AutoCloseRoutine(__instance)); } } private static IEnumerator AutoCloseRoutine(Door door) { yield return (object)new WaitForSeconds(TerritoryConfig.DoorAutoCloseDelay.Value); if (!((Object)(object)door == (Object)null) && !((Object)(object)door.m_nview == (Object)null) && door.m_nview.IsValid() && door.m_nview.GetZDO().GetInt("state", 0) != 0 && TerritoryWard.IsInsideActiveWard(((Component)door).transform.position)) { door.m_nview.InvokeRPC(ZNetView.Everybody, "UseDoor", new object[1] { false }); } } } [HarmonyPatch(typeof(Player), "Interact")] public static class Patch_Player_Interact { private static bool Prefix(Player __instance, GameObject go) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)go == (Object)null) { return true; } if (((Object)((Component)go.transform.root).gameObject).name.Contains("territoryward")) { return true; } Vector3 position = go.transform.position; if (TerritoryWard.IsInsideDeactivatedWard(position)) { ((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_off_blocked", 0, (Sprite)null); return false; } return true; } } [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData), typeof(int), typeof(int), typeof(int) })] public static class Patch_Inventory_AddItem_MaxStack { private static void Prefix(Inventory __instance, ItemData item, out int __state) { __state = item.m_shared.m_maxStackSize; if (WardInventoryHelper.IsWardStorage(__instance) && WardInventoryHelper.IsWardFuel(item.m_shared.m_name)) { item.m_shared.m_maxStackSize = 999; } } private static void Postfix(ItemData item, int __state) { item.m_shared.m_maxStackSize = __state; } } [HarmonyPatch(typeof(Inventory), "CanAddItem", new Type[] { typeof(ItemData), typeof(int) })] public static class Patch_Inventory_CanAddItem_MaxStack { private static void Prefix(Inventory __instance, ItemData item, out int __state) { __state = item.m_shared.m_maxStackSize; if (WardInventoryHelper.IsWardStorage(__instance) && WardInventoryHelper.IsWardFuel(item.m_shared.m_name)) { item.m_shared.m_maxStackSize = 999; } } private static void Postfix(ItemData item, int __state) { item.m_shared.m_maxStackSize = __state; } } [HarmonyPatch(typeof(PrivateArea), "Interact")] public static class Patch_PrivateArea_PermittedToggle { private static bool Prefix(PrivateArea __instance, Humanoid human, bool hold, bool alt) { if (!((Object)((Component)__instance).gameObject).name.Contains("territoryward")) { return true; } if (hold) { return true; } if (alt || Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303)) { return false; } if (__instance.m_piece.IsCreator()) { return true; } Player val = (Player)(object)((human is Player) ? human : null); if ((Object)(object)val == (Object)null) { return true; } if (__instance.IsPermitted(val.GetPlayerID())) { __instance.m_nview.InvokeRPC("ToggleEnabled", new object[1] { val.GetPlayerID() }); } else { __instance.m_nview.InvokeRPC("TogglePermitted", new object[2] { val.GetPlayerID(), val.GetPlayerName() }); } return false; } } [HarmonyPatch(typeof(PrivateArea), "RPC_ToggleEnabled")] public static class Patch_PrivateArea_RPC_ToggleEnabled { private static bool Prefix(PrivateArea __instance, long uid, long playerID) { if (!((Object)((Component)__instance).gameObject).name.Contains("territoryward")) { return true; } if (!__instance.m_nview.IsOwner()) { return true; } if (__instance.m_piece.GetCreator() == playerID) { return true; } if (!__instance.IsPermitted(playerID)) { return true; } __instance.SetEnabled(!__instance.IsEnabled()); return false; } } [HarmonyPatch(typeof(PrivateArea), "RPC_TogglePermitted")] public static class Patch_PrivateArea_RPC_TogglePermitted { private static bool Prefix(PrivateArea __instance, long uid, long playerID, string name) { if (!((Object)((Component)__instance).gameObject).name.Contains("territoryward")) { return true; } if (!__instance.m_nview.IsOwner()) { return true; } if (__instance.m_piece.GetCreator() == uid) { return true; } FieldInfo field = typeof(PrivateArea).GetField("m_permittedPlayers", BindingFlags.Instance | BindingFlags.NonPublic); if (field == null) { return true; } if (!(field.GetValue(__instance) is List> list)) { return true; } int num = list.FindIndex((KeyValuePair kv) => kv.Key == playerID); if (num >= 0) { list.RemoveAt(num); } else { list.Add(new KeyValuePair(playerID, name)); } typeof(PrivateArea).GetMethod("Save", BindingFlags.Instance | BindingFlags.NonPublic)?.Invoke(__instance, null); return false; } } [HarmonyPatch(typeof(PrivateArea), "GetHoverText")] public static class Patch_PrivateArea_HoverText { private const string Cyan = "#00FFFF"; private const string Yellow = "yellow"; private static void Postfix(PrivateArea __instance, ref string __result) { //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Unknown result type (might be due to invalid IL or missing references) //IL_045c: Unknown result type (might be due to invalid IL or missing references) //IL_04d6: Unknown result type (might be due to invalid IL or missing references) //IL_052c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)((Component)__instance).gameObject).name.Contains("territoryward")) { return; } TerritoryWardController component = ((Component)__instance).GetComponent(); ZNetView val = component?.m_nview ?? ((Component)__instance).GetComponent(); int num = 1; if ((Object)(object)val != (Object)null && val.IsValid()) { num = val.GetZDO().GetInt("tw_level", 1); } string arg = (__instance.IsEnabled() ? "활성화" : "비활성화"); Player localPlayer = Player.m_localPlayer; bool flag = (Object)(object)localPlayer != (Object)null && __instance.m_piece.IsCreator(); bool flag2 = (Object)(object)localPlayer != (Object)null && (Object)(object)val != (Object)null && val.IsValid() && __instance.IsPermitted(localPlayer.GetPlayerID()); string text = Localization.instance.Localize("$KEY_Use"); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(string.Format("[ 영토 와드 Lv{1}({2}) ]", "#00FFFF", num, arg)); if ((Object)(object)component != (Object)null) { stringBuilder.Append("\n연료 : " + component.GetFuelInfoText()); } stringBuilder.Append(string.Format("\n범위 : {1:0}m", "yellow", __instance.m_radius)); stringBuilder.Append("\n"); object obj; if (val == null) { obj = null; } else { ZDO zDO = val.GetZDO(); obj = ((zDO != null) ? zDO.GetString("creatorName", "???") : null); } if (obj == null) { obj = "???"; } string text2 = (string)obj; string permittedNamesString = GetPermittedNamesString(__instance, val); stringBuilder.Append("\n소유자 : " + text2 + ""); stringBuilder.Append("\n허용됨 : " + permittedNamesString + ""); stringBuilder.Append("\n"); if (flag || flag2) { stringBuilder.Append("\n[" + text + "] 와드 활성화 / 비활성화"); if (flag2 && !flag) { stringBuilder.Append("\n[Shift+" + text + "] 멤버 탈퇴"); } } else { stringBuilder.Append("\n[" + text + "] 멤버 가입"); stringBuilder.Append("\n[Shift+" + text + "] 멤버 탈퇴"); } stringBuilder.Append(string.Format("\n[{1}] $territoryward_fuel_hint", "yellow", TerritoryConfig.FuelStorageKey.Value)); stringBuilder.Append("\n"); stringBuilder.Append(string.Format("\n[{1}] $territoryward_upgrade_hint_key", "yellow", TerritoryConfig.UpgradeKey.Value)); if ((Object)(object)component != (Object)null) { if (num < 8) { float? nextLevelRadius = component.GetNextLevelRadius(); stringBuilder.Append(string.Format(" Lv{1}→Lv{3}", "#00FFFF", num, "#00FFFF", num + 1)); stringBuilder.Append("\n재료 : " + component.GetUpgradeRequirementText()); if (nextLevelRadius.HasValue) { stringBuilder.Append(string.Format("\n범위 : {1:0}m", "yellow", nextLevelRadius.Value)); } stringBuilder.Append("\n연료 : " + component.GetNextLevelFuelInfoText()); string nextLevelFullFuelText = component.GetNextLevelFullFuelText(); if (!string.IsNullOrEmpty(nextLevelFullFuelText)) { stringBuilder.Append(string.Format("\nLv1/Lv{1} 연료 :", "yellow", num + 1)); stringBuilder.Append("\n" + nextLevelFullFuelText); } } else { stringBuilder.Append(" $territoryward_max_level"); } } if (num >= 5 && (Object)(object)component != (Object)null) { if (component.IsShielded()) { int num2 = Mathf.CeilToInt(component.GetShieldRemainingMinutes()); string text3 = Localization.instance.Localize("$territoryward_shield_active", new string[1] { num2.ToString() }); stringBuilder.Append("\n[" + text3 + "]"); if (flag) { stringBuilder.Append(string.Format("\n[{1}] $territoryward_shield_deactivate_hint_key", "yellow", TerritoryConfig.ShieldKey.Value)); } } else if (flag) { float shieldBankedRemainingMinutes = component.GetShieldBankedRemainingMinutes(); if (shieldBankedRemainingMinutes > 0f) { int num3 = Mathf.CeilToInt(shieldBankedRemainingMinutes); string arg2 = Localization.instance.Localize("$territoryward_shield_resume_hint", new string[1] { num3.ToString() }); stringBuilder.Append(string.Format("\n[{1}] {2}", "yellow", TerritoryConfig.ShieldKey.Value, arg2)); } else { string arg3 = Localization.instance.Localize(TerritoryWardController.Resolve(TerritoryConfig.ShieldItemName.Value) ?? TerritoryConfig.ShieldItemName.Value); stringBuilder.Append(string.Format("\n[{1}] $territoryward_shield_hint_key ({2} x1)", "yellow", TerritoryConfig.ShieldKey.Value, arg3)); } } } __result = Localization.instance.Localize(stringBuilder.ToString()); } private static string GetPermittedNamesString(PrivateArea instance, ZNetView nview) { try { if ((Object)(object)nview != (Object)null && nview.IsValid()) { ZDO zDO = nview.GetZDO(); int num = zDO.GetInt("permitted", 0); if (num > 0) { List list = new List(num); for (int i = 0; i < num; i++) { string text = zDO.GetString("pu_name" + i, ""); if (!string.IsNullOrEmpty(text)) { list.Add(text); } } if (list.Count > 0) { return string.Join(", ", list); } } } } catch { } try { FieldInfo[] fields = typeof(PrivateArea).GetFields(BindingFlags.Instance | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (!fieldInfo.Name.ToLower().Contains("permitted") || !(fieldInfo.GetValue(instance) is IEnumerable enumerable)) { continue; } List list2 = new List(); foreach (object item in enumerable) { if (item != null) { string text2 = item.GetType().GetProperty("Value")?.GetValue(item) as string; if (!string.IsNullOrEmpty(text2)) { list2.Add(text2); } } } if (list2.Count > 0) { return string.Join(", ", list2); } } } catch { } return "없음"; } } [HarmonyPatch(typeof(Hud), "UpdateCrosshair")] public static class Patch_Hud_WardHoverTextPosition { private static Vector2? s_basePos; private static Vector2? s_baseSizeDelta; private static TextMeshProUGUI s_rightColumn; private static RectTransform s_dividerRect; private const float OffsetY = 340f; private const float WidthMultiplier = 1.3225f; private const float DividerWidth = 4f; private const float ColumnGap = 12f; private const float MinDividerHeight = 200f; private const float DividerHeightPad = 20f; private static void Postfix(Hud __instance) { //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0235: 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_0270: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: 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_0315: Unknown result type (might be due to invalid IL or missing references) //IL_031a: Unknown result type (might be due to invalid IL or missing references) try { object? obj = typeof(Hud).GetField("m_hoverName", BindingFlags.Instance | BindingFlags.Public)?.GetValue(__instance); Component val = (Component)((obj is Component) ? obj : null); if ((Object)(object)val == (Object)null) { return; } RectTransform component = val.GetComponent(); if ((Object)(object)component == (Object)null) { return; } PropertyInfo property = ((object)val).GetType().GetProperty("text", BindingFlags.Instance | BindingFlags.Public); if (property == null) { return; } string text = (property.GetValue(val) as string) ?? ""; bool flag = text.Contains("영토 와드") || text.Contains("Territory Ward"); if (!s_basePos.HasValue) { s_basePos = component.anchoredPosition; } if (!s_baseSizeDelta.HasValue) { s_baseSizeDelta = component.sizeDelta; } component.anchoredPosition = s_basePos.Value + (Vector2)(flag ? new Vector2(0f, 340f) : Vector2.zero); if (!flag) { component.sizeDelta = s_baseSizeDelta.Value; if ((Object)(object)s_rightColumn != (Object)null) { ((Component)s_rightColumn).gameObject.SetActive(false); } if ((Object)(object)s_dividerRect != (Object)null) { ((Component)s_dividerRect).gameObject.SetActive(false); } return; } EnsureColumnObjects(val, component); float num = s_baseSizeDelta.Value.x * 1.3225f; component.sizeDelta = new Vector2(num, s_baseSizeDelta.Value.y); string[] array = text.Split(new char[1] { '\n' }); int num2 = Mathf.CeilToInt((float)array.Length / 2f); string value = string.Join("\n", array, 0, num2); string text2 = string.Join("\n", array, num2, array.Length - num2); property.SetValue(val, value); ((TMP_Text)s_rightColumn).text = text2; Vector2 anchoredPosition = component.anchoredPosition; float num3 = num + 12f; float num4 = num + 24f + 4f; RectTransform component2 = ((Component)s_rightColumn).GetComponent(); component2.sizeDelta = new Vector2(num, s_baseSizeDelta.Value.y); component2.anchoredPosition = anchoredPosition + new Vector2(num4, 0f); ((Component)s_rightColumn).gameObject.SetActive(true); TextMeshProUGUI val2 = (TextMeshProUGUI)(object)((val is TextMeshProUGUI) ? val : null); float num5 = (((Object)(object)val2 != (Object)null) ? ((TMP_Text)val2).preferredHeight : 200f); float preferredHeight = ((TMP_Text)s_rightColumn).preferredHeight; float num6 = Mathf.Max(Mathf.Max(num5, preferredHeight), 200f) + 20f; s_dividerRect.sizeDelta = new Vector2(4f, num6); s_dividerRect.anchoredPosition = anchoredPosition + new Vector2(num3, 0f); ((Component)s_dividerRect).gameObject.SetActive(true); } catch { } } private static void EnsureColumnObjects(Component originalComp, RectTransform originalRt) { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //IL_00a6: 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) if ((Object)(object)s_rightColumn == (Object)null) { GameObject val = Object.Instantiate(originalComp.gameObject, ((Transform)originalRt).parent); ((Object)val).name = "TerritoryWard_HoverTextRightColumn"; s_rightColumn = val.GetComponent(); } if ((Object)(object)s_dividerRect == (Object)null) { GameObject val2 = new GameObject("TerritoryWard_HoverTextDivider", new Type[2] { typeof(RectTransform), typeof(Image) }); val2.transform.SetParent(((Transform)originalRt).parent, false); ((Graphic)val2.GetComponent()).color = new Color(1f, 1f, 1f, 0.4f); s_dividerRect = val2.GetComponent(); s_dividerRect.pivot = new Vector2(0.5f, 1f); } } } internal static class WardInventoryHelper { internal static bool IsWardStorage(Inventory inv) { return inv.m_name == "$territoryward_storage"; } internal static bool IsWardFuel(string name) { return name == "$item_wood" || name == "$item_resin"; } } [HarmonyPatch(typeof(InventoryGrid), "UpdateInventory")] public static class Patch_InventoryGrid_UpdateInventory_ForceRebuild { private static void Prefix(InventoryGrid __instance, Inventory inventory) { if (inventory != null) { int num = inventory.GetWidth() * inventory.GetHeight(); if (__instance.m_elements.Count != num) { __instance.m_width = -1; } } } } [HarmonyPatch(typeof(InventoryGrid), "GetElement")] public static class Patch_InventoryGrid_GetElement_Safety { private static bool Prefix(InventoryGrid __instance, int x, int y, int width, ref Element __result) { int num = y * width + x; if (num >= 0 && num < __instance.m_elements.Count) { return true; } if (__instance.m_elements.Count == 0) { return true; } ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)$"[Territory] InventoryGrid.GetElement 범위 밖 접근 방어: x={x}, y={y}, width={width}, elements={__instance.m_elements.Count}"); } __result = __instance.m_elements[Mathf.Clamp(num, 0, __instance.m_elements.Count - 1)]; return false; } } [HarmonyPatch(typeof(Container), "Interact")] public static class Patch_Container_Interact_IntrusionAlert { private static void Prefix(Container __instance, Humanoid character) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) IntrusionAlert.CheckAndAlert(((Component)__instance).transform.position, character); } } [HarmonyPatch(typeof(CraftingStation), "Interact")] public static class Patch_CraftingStation_Interact_IntrusionAlert { private static void Prefix(CraftingStation __instance, Humanoid user) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) IntrusionAlert.CheckAndAlert(((Component)__instance).transform.position, user); } } internal static class IntrusionAlert { public static void CheckAndAlert(Vector3 position, Humanoid character) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)character != (Object)(object)Player.m_localPlayer) { return; } foreach (PrivateArea allArea in PrivateArea.m_allAreas) { if (allArea.IsEnabled() && ((Object)((Component)allArea).gameObject).name.Contains("territoryward") && allArea.IsInside(position, 0f) && !allArea.HaveLocalAccess()) { ((Component)allArea).GetComponent()?.ReportIntrusion(Player.m_localPlayer.GetPlayerName()); } } } } public static class TerritoryLocalization { public static void Register() { CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); string text = "Korean"; localization.AddTranslation(ref text, new Dictionary { ["territoryward_name"] = "영토 와드", ["territoryward_storage"] = "영토 와드 창고", ["territoryward_no_fuel"] = "연료 부족으로 영토 와드가 비활성화되었습니다!", ["territoryward_off_blocked"] = "비활성화된 영토 와드 구역에서는 사용할 수 없습니다!", ["territoryward_no_build"] = "영토 와드 구역 안에서만 건설할 수 있습니다!", ["territoryward_must_activate"] = "영토와드를 활성화 해야합니다!", ["territoryward_no_overlap"] = "다른 영토 와드 구역 안에서는 설치할 수 없습니다!", ["territoryward_fuel_hint"] = "연료 창고 열기", ["territoryward_disabled"] = "영토 와드 시스템이 비활성화되어 있습니다!", ["territoryward_limit_reached"] = "영토 와드 설치 한도를 초과했습니다!", ["territoryward_upgrade_hint_key"] = "영토 와드 업그레이드", ["territoryward_range_label"] = "범위", ["territoryward_fuel_label"] = "연료", ["territoryward_fuel_per_minutes"] = "$1분마다", ["territoryward_fuel_or"] = "또는", ["territoryward_upgrade_too_far"] = "영토 와드와 너무 멀리 떨어져 있습니다!", ["territoryward_upgrade_not_creator"] = "영토 와드를 설치한 사람만 업그레이드할 수 있습니다!", ["territoryward_intrusion_alert"] = "$1가 승인없이 영토에 침입했습니다.", ["territoryward_upgrade_success"] = "영토 와드가 업그레이드되었습니다!", ["territoryward_max_level"] = "이미 최대 레벨입니다!", ["territoryward_missing_fuel_suffix"] = " 부족!", ["territoryward_shield_hint_key"] = "영토 보호 활성화", ["territoryward_shield_deactivate_hint_key"] = "영토 보호 비활성화", ["territoryward_shield_active"] = "보호 중 — 남은 $1분", ["territoryward_shield_started"] = "영토 보호가 활성화되었습니다! (1시간)", ["territoryward_shield_stopped"] = "영토 보호가 비활성화되었습니다.", ["territoryward_shield_resumed"] = "남은 시간으로 영토 보호가 재개되었습니다! (아이템 소모 없음)", ["territoryward_shield_resume_hint"] = "재개 (아이템 소모 없음, 남은 $1분)", ["territoryward_shield_no_item"] = "슈트링 코어가 부족합니다!", ["territoryward_shield_low_level"] = "Lv5 이상에서만 사용 가능합니다!", ["territoryward_rangering_hint_key"] = "범위 링 토글", ["territoryward_shield_hud"] = "[ 영토 보호 중 — $1분 남음 ]", ["territoryward_intrusion_chat"] = "[영토 침입 경고] $1가 승인 없이 영토에 진입했습니다!" }); text = "English"; localization.AddTranslation(ref text, new Dictionary { ["territoryward_name"] = "Territory Ward", ["territoryward_storage"] = "Territory Ward Storage", ["territoryward_no_fuel"] = "Territory Ward deactivated: out of fuel!", ["territoryward_off_blocked"] = "Cannot use items inside a deactivated Territory Ward!", ["territoryward_no_build"] = "You can only build inside a Territory Ward!", ["territoryward_must_activate"] = "You must activate the Territory Ward!", ["territoryward_no_overlap"] = "Cannot place a Territory Ward inside another Territory Ward!", ["territoryward_fuel_hint"] = "Open Fuel Storage", ["territoryward_disabled"] = "Territory Ward system is disabled!", ["territoryward_limit_reached"] = "Territory Ward placement limit reached!", ["territoryward_upgrade_hint_key"] = "Upgrade Territory Ward", ["territoryward_range_label"] = "Range", ["territoryward_fuel_label"] = "Fuel", ["territoryward_fuel_per_minutes"] = "every $1 min", ["territoryward_fuel_or"] = "or", ["territoryward_upgrade_too_far"] = "You are too far from the Territory Ward!", ["territoryward_upgrade_not_creator"] = "Only the creator of this Territory Ward can upgrade it!", ["territoryward_intrusion_alert"] = "$1 has invaded the territory without permission!", ["territoryward_upgrade_success"] = "Territory Ward upgraded!", ["territoryward_max_level"] = "Already at max level!", ["territoryward_missing_fuel_suffix"] = " is missing!", ["territoryward_shield_hint_key"] = "Activate Territory Shield", ["territoryward_shield_deactivate_hint_key"] = "Deactivate Territory Shield", ["territoryward_shield_active"] = "Shield Active — $1 min remaining", ["territoryward_shield_started"] = "Territory Shield activated! (1 hour)", ["territoryward_shield_stopped"] = "Territory Shield deactivated.", ["territoryward_shield_resumed"] = "Territory Shield resumed with remaining time! (no item consumed)", ["territoryward_shield_resume_hint"] = "Resume (no item needed, $1 min left)", ["territoryward_shield_no_item"] = "Not enough Surtling Core!", ["territoryward_shield_low_level"] = "Requires Lv5 or higher!", ["territoryward_rangering_hint_key"] = "Toggle Range Ring", ["territoryward_shield_hud"] = "[ Shield Active — $1 min remaining ]", ["territoryward_intrusion_chat"] = "[Intrusion Alert] $1 has entered the territory without permission!" }); } public static void RefreshWardDescription() { CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); string text = Localization.instance.Localize(TerritoryWardController.Resolve(TerritoryConfig.Lv1FuelA.Value, warnIfMissing: false) ?? "$item_wood"); string text2 = Localization.instance.Localize(TerritoryWardController.Resolve(TerritoryConfig.Lv1FuelB.Value, warnIfMissing: false) ?? "$item_resin"); float value = TerritoryConfig.Lv1Radius.Value; int value2 = TerritoryConfig.Lv1FuelAAmount.Value; int value3 = TerritoryConfig.Lv1FuelBAmount.Value; float value4 = TerritoryConfig.Lv1IntervalMinutes.Value; string text3 = "Korean"; localization.AddTranslation(ref text3, new Dictionary { ["territoryward_desc"] = $"반경 {value:0}미터의 영토를 설정합니다.\n" + "ON 상태에서만 구역 안에서 건설하고 상호작용할 수 있습니다.\n" + $"연료: {text} {value2}개 + {text2} {value3}개 / {value4:0}분마다" }); text3 = "English"; localization.AddTranslation(ref text3, new Dictionary { ["territoryward_desc"] = $"Sets a territory with {value:0}m radius.\n" + "Building and interaction only allowed when ON.\n" + $"Fuel: {text} x{value2} + {text2} x{value3} every {value4:0} min" }); } } [BepInPlugin("KorCaptain_territorial_ward", "Captain Territorial", "1.0.21")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { internal const string UpgradeButtonName = "TerritorialWardUpgrade"; internal static ButtonConfig UpgradeButton; internal static ButtonConfig ShieldButton; internal static ButtonConfig RangeRingButton; internal static ManualLogSource Log; private readonly Harmony _harmony = new Harmony("KorCaptain.Captain_territorial"); private void Awake() { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0113: 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_0130: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; TerritoryConfig.Init(((BaseUnityPlugin)this).Config); TerritoryLocalization.Register(); VFXManager.Initialize(); PrefabManager.OnVanillaPrefabsAvailable += TerritoryWard.Create; PrefabManager.OnVanillaPrefabsAvailable += TerritoryLocalization.RefreshWardDescription; UpgradeButton = new ButtonConfig { Name = "TerritorialWardUpgrade", Config = TerritoryConfig.UpgradeKey, HintToken = "$territoryward_upgrade_hint_key" }; InputManager.Instance.AddButton(((BaseUnityPlugin)this).Info.Metadata.GUID, UpgradeButton); ShieldButton = new ButtonConfig { Name = "TerritorialWardShield", Config = TerritoryConfig.ShieldKey, HintToken = "$territoryward_shield_hint_key" }; InputManager.Instance.AddButton(((BaseUnityPlugin)this).Info.Metadata.GUID, ShieldButton); RangeRingButton = new ButtonConfig { Name = "TerritorialWardRangeRing", Config = TerritoryConfig.RangeRingKey, HintToken = "$territoryward_rangering_hint_key" }; InputManager.Instance.AddButton(((BaseUnityPlugin)this).Info.Metadata.GUID, RangeRingButton); SynchronizationManager.OnConfigurationSynchronized += delegate(object _, ConfigurationSynchronizationEventArgs e) { if (e.InitialSynchronization) { TerritoryLocalization.RefreshWardDescription(); } }; _harmony.PatchAll(); PrintLoadedMessage(); } private void PrintLoadedMessage() { string text = $"[Captain_territorial] Captain Territorial {((BaseUnityPlugin)this).Info.Metadata.Version} Loaded!"; try { Type type = typeof(BaseUnityPlugin).Assembly.GetType("BepInEx.ConsoleManager"); MethodInfo methodInfo = type?.GetMethod("SetConsoleColor", BindingFlags.Static | BindingFlags.Public); TextWriter textWriter = type?.GetProperty("StandardOutStream", BindingFlags.Static | BindingFlags.Public)?.GetValue(null) as TextWriter; if (methodInfo != null && textWriter != null) { methodInfo.Invoke(null, new object[1] { ConsoleColor.Cyan }); textWriter.WriteLine(text); methodInfo.Invoke(null, new object[1] { ConsoleColor.Gray }); } else { Log.LogMessage((object)text); } } catch { Log.LogMessage((object)text); } } private void OnDestroy() { _harmony.UnpatchSelf(); } } [HarmonyPatch(typeof(WearNTear), "Damage")] public static class Patch_WearNTear_Damage_ShieldZone { private static bool Prefix(WearNTear __instance) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) foreach (PrivateArea allArea in PrivateArea.m_allAreas) { if (allArea.IsEnabled() && ((Object)((Component)allArea).gameObject).name.Contains("territoryward")) { TerritoryWardController component = ((Component)allArea).GetComponent(); if ((Object)(object)component != (Object)null && component.IsShielded() && allArea.IsInside(((Component)__instance).transform.position, 0f)) { return false; } } } return true; } } [HarmonyPatch(typeof(Character), "Damage")] public static class Patch_Character_Damage_ShieldZone { private static bool Prefix(Character __instance) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) if (!(__instance is Player)) { return true; } foreach (PrivateArea allArea in PrivateArea.m_allAreas) { if (allArea.IsEnabled() && ((Object)((Component)allArea).gameObject).name.Contains("territoryward")) { TerritoryWardController component = ((Component)allArea).GetComponent(); if ((Object)(object)component != (Object)null && component.IsShielded() && allArea.IsInside(((Component)__instance).transform.position, 0f)) { return false; } } } return true; } } [HarmonyPatch(typeof(BaseAI), "FindEnemy")] public static class Patch_BaseAI_FindEnemy_ShieldZone { private static bool Prefix(BaseAI __instance, ref Character __result) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) foreach (PrivateArea allArea in PrivateArea.m_allAreas) { if (allArea.IsEnabled() && ((Object)((Component)allArea).gameObject).name.Contains("territoryward")) { TerritoryWardController component = ((Component)allArea).GetComponent(); if (!((Object)(object)component == (Object)null) && component.IsShielded() && allArea.IsInside(((Component)__instance).transform.position, 0f)) { __result = null; return false; } } } return true; } } public static class TerritoryWard { public const string PrefabName = "territoryward"; public const string StorageName = "$territoryward_storage"; internal static readonly List s_wards = new List(16); private static Piece s_piece; private static Requirement[] s_normalRequirements; private static readonly Requirement[] s_freeRequirements = (Requirement[])(object)new Requirement[0]; public static void Create() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Expected O, but got Unknown PieceConfig val = new PieceConfig { Name = "$territoryward_name", Description = "$territoryward_desc", PieceTable = "Hammer", Category = "Misc" }; val.AddRequirement(new RequirementConfig("Wood", 10, 0, true)); val.AddRequirement(new RequirementConfig("Stone", 10, 0, true)); CustomPiece val2 = new CustomPiece("territoryward", "guard_stone", val); if ((Object)(object)val2.PiecePrefab == (Object)null) { Plugin.Log.LogError((object)"[Captain_territorial] guard_stone 클론 실패 — 바닐라 프리팹 없음"); PrefabManager.OnVanillaPrefabsAvailable -= Create; return; } PrivateArea component = val2.PiecePrefab.GetComponent(); if ((Object)(object)component != (Object)null) { component.m_name = "$territoryward_name"; } Container val3 = val2.PiecePrefab.AddComponent(); val3.m_name = "$territoryward_storage"; val3.m_width = 2; val3.m_height = 2; val3.m_defaultItems = new DropTable(); val3.m_checkGuardStone = false; val2.PiecePrefab.AddComponent(); PieceManager.Instance.AddPiece(val2); PrefabManager.OnVanillaPrefabsAvailable -= Create; s_piece = val2.PiecePrefab.GetComponent(); s_normalRequirements = s_piece.m_resources; ApplyAdminBypass(TerritoryConfig.AdminBypass.Value); TerritoryConfig.AdminBypass.SettingChanged += delegate { ApplyAdminBypass(TerritoryConfig.AdminBypass.Value); }; Plugin.Log.LogInfo((object)"[Captain_territorial] territoryward 등록 완료"); } private static void ApplyAdminBypass(bool enabled) { if (!((Object)(object)s_piece == (Object)null)) { s_piece.m_resources = (enabled ? s_freeRequirements : s_normalRequirements); } } public static bool IsInsideActiveWard(Vector3 point) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) foreach (PrivateArea s_ward in s_wards) { if ((Object)(object)s_ward == (Object)null || !s_ward.IsEnabled() || !(Vector3.Distance(((Component)s_ward).transform.position, point) <= s_ward.m_radius)) { continue; } return true; } return false; } public static bool IsInsideDeactivatedWard(Vector3 point) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) foreach (PrivateArea s_ward in s_wards) { if ((Object)(object)s_ward == (Object)null || s_ward.IsEnabled() || !(Vector3.Distance(((Component)s_ward).transform.position, point) <= s_ward.m_radius)) { continue; } return true; } return false; } } public class TerritoryWardController : MonoBehaviour { private struct ResolvedTier { public int Level; public string NameA; public int AmountA; public string NameB; public int AmountB; public string NameC; public int AmountC; public float IntervalSeconds; } internal ZNetView m_nview; private Container m_container; private PrivateArea m_privateArea; private Piece m_piece; private static readonly FieldInfo s_hoveringField = typeof(Player).GetField("m_hovering", BindingFlags.Instance | BindingFlags.NonPublic); private readonly List m_tiers = new List(); private bool m_fuelDepleted = false; private bool m_missingFuelWarned = false; private bool m_wasEnabled = false; private int m_level = 1; private float m_lastIntrusionAlertTime = -999f; private PinData m_minimapPin; private readonly Dictionary m_intruders = new Dictionary(); private GameObject m_shieldGenObject; private bool m_showRangeRing = false; private const string ZDO_LAST_CONSUME = "tw_lastConsume"; private const string ZDO_SHIELD_END = "tw_shield_end"; private const string ZDO_SHIELD_REMAINING = "tw_shield_remaining"; private const string ZDO_LEVEL = "tw_level"; private const float CHECK_INTERVAL = 5f; private const float INTRUSION_ALERT_COOLDOWN = 10f; private static readonly (int Width, int Height)[] s_storageSizes = new(int, int)[8] { (2, 2), (2, 3), (3, 3), (3, 4), (4, 4), (4, 5), (5, 5), (5, 6) }; private static bool s_shieldTemplateUnavailableLogged = false; private bool m_showWhitelistUI = false; private List> m_uiPermitted = new List>(); private Vector2 m_uiScrollPos; private static GUIStyle s_intruderStyle; private static GUIStyle s_titleStyle; private static GUIStyle s_sectionStyle; private static GUIStyle s_shieldHUDStyle; private void Awake() { m_nview = ((Component)this).GetComponent(); m_container = ((Component)this).GetComponent(); m_privateArea = ((Component)this).GetComponent(); m_piece = ((Component)this).GetComponent(); if ((Object)(object)m_nview != (Object)null) { m_nview.Register("RPC_ApplyLevel", (Action)RPC_ApplyLevel); m_nview.Register("RPC_ReportIntrusion", (Action)RPC_ReportIntrusion); m_nview.Register("RPC_ActivateShield", (Action)RPC_ActivateShield); m_nview.Register("RPC_DeactivateShield", (Action)RPC_DeactivateShield); } } private void Start() { int level = 1; if ((Object)(object)m_nview != (Object)null && m_nview.IsValid()) { level = m_nview.GetZDO().GetInt("tw_level", 1); } ApplyLevel(level); AddMinimapPin(); if ((Object)(object)m_privateArea != (Object)null) { TerritoryWard.s_wards.Add(m_privateArea); } if ((Object)(object)m_nview != (Object)null && m_nview.IsOwner()) { ((MonoBehaviour)this).InvokeRepeating("CheckConsumption", 5f, 5f); } } private void OnDestroy() { ((MonoBehaviour)this).CancelInvoke(); if ((Object)(object)m_privateArea != (Object)null) { TerritoryWard.s_wards.Remove(m_privateArea); } RemoveMinimapPin(); StopShieldVFX(); } private void AddMinimapPin() { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Minimap.instance == (Object)null)) { RemoveMinimapPin(); string arg = (((Object)(object)m_nview != (Object)null && m_nview.IsValid()) ? m_nview.GetZDO().GetString("creatorName", "???") : "???"); string text = $"영토 와드 Lv{m_level} [{arg}]"; m_minimapPin = Minimap.instance.AddPin(((Component)this).transform.position, (PinType)3, text, false, false, 0L, default(PlatformUserID)); } } private void RemoveMinimapPin() { if (m_minimapPin != null && !((Object)(object)Minimap.instance == (Object)null)) { Minimap.instance.RemovePin(m_minimapPin); m_minimapPin = null; } } private void ApplyLevel(int level) { //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0330: Unknown result type (might be due to invalid IL or missing references) //IL_033f: 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) //IL_035b: Unknown result type (might be due to invalid IL or missing references) m_level = level; float radius = TerritoryConfig.GetRadius(level); if ((Object)(object)m_privateArea != (Object)null) { m_privateArea.m_radius = radius; if ((Object)(object)m_privateArea.m_areaMarker != (Object)null) { m_privateArea.m_areaMarker.m_radius = radius; } } if ((Object)(object)m_shieldGenObject != (Object)null) { ShieldGenerator component = m_shieldGenObject.GetComponent(); if ((Object)(object)component != (Object)null) { component.m_minShieldRadius = radius; component.m_maxShieldRadius = radius; component.m_radiusTarget = radius; component.m_radius = radius; } } if ((Object)(object)m_container == (Object)null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)$"[Territory] ApplyLevel Lv{level}: m_container가 null — 창고 리사이즈 스킵"); } } else { Inventory inventory = m_container.GetInventory(); if (inventory == null) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)$"[Territory] ApplyLevel Lv{level}: GetInventory()가 null — 창고 리사이즈 스킵"); } } else { (int, int) tuple = s_storageSizes[Mathf.Clamp(level, 1, s_storageSizes.Length) - 1]; inventory.m_width = Mathf.Max(inventory.m_width, tuple.Item1); inventory.m_height = Mathf.Max(inventory.m_height, tuple.Item2); ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogInfo((object)$"[Territory] ApplyLevel Lv{level}: 창고 크기 목표 {tuple.Item1}x{tuple.Item2}, 실제 적용 {inventory.GetWidth()}x{inventory.GetHeight()}"); } bool flag = false; foreach (ItemData allItem in inventory.GetAllItems()) { if (allItem.m_gridPos.x >= 0 && allItem.m_gridPos.x < inventory.m_width && allItem.m_gridPos.y >= 0 && allItem.m_gridPos.y < inventory.m_height) { continue; } Vector2i val = inventory.FindEmptySlot(false); if (val.x < 0) { ManualLogSource log4 = Plugin.Log; if (log4 != null) { log4.LogWarning((object)$"[Territory] 창고 아이템 '{allItem.m_shared.m_name}'가 범위 밖({allItem.m_gridPos.x},{allItem.m_gridPos.y})인데 빈 칸을 못 찾음 (창고 {inventory.m_width}x{inventory.m_height})"); } continue; } ManualLogSource log5 = Plugin.Log; if (log5 != null) { log5.LogWarning((object)$"[Territory] 창고 아이템 '{allItem.m_shared.m_name}' gridPos({allItem.m_gridPos.x},{allItem.m_gridPos.y})가 범위 밖 — ({val.x},{val.y})로 재배치"); } allItem.m_gridPos = val; flag = true; } if (flag && (Object)(object)m_nview != (Object)null && m_nview.IsOwner()) { m_container.Save(); } } } m_tiers.Clear(); foreach (TerritoryConfig.FuelTier fuelTier in TerritoryConfig.GetFuelTiers(level)) { bool flag2 = !string.IsNullOrEmpty(fuelTier.ItemC); m_tiers.Add(new ResolvedTier { Level = fuelTier.Level, NameA = (Resolve(fuelTier.ItemA) ?? fuelTier.ItemA), AmountA = fuelTier.AmountA, NameB = (Resolve(fuelTier.ItemB) ?? fuelTier.ItemB), AmountB = fuelTier.AmountB, NameC = (flag2 ? (Resolve(fuelTier.ItemC) ?? fuelTier.ItemC) : null), AmountC = (flag2 ? fuelTier.AmountC : 0), IntervalSeconds = fuelTier.IntervalSeconds }); } } private void RPC_ApplyLevel(long sender, int level) { if ((Object)(object)m_nview != (Object)null && m_nview.IsOwner()) { m_nview.GetZDO().Set("tw_level", level); } ApplyLevel(level); AddMinimapPin(); } public void ReportIntrusion(string intruderName) { if (!((Object)(object)m_nview == (Object)null) && m_nview.IsValid() && !(Time.time - m_lastIntrusionAlertTime < 10f)) { m_lastIntrusionAlertTime = Time.time; m_nview.InvokeRPC(ZNetView.Everybody, "RPC_ReportIntrusion", new object[1] { intruderName }); } } private void RPC_ReportIntrusion(long sender, string intruderName) { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)m_privateArea == (Object)null) { return; } long playerID = Game.instance.GetPlayerProfile().GetPlayerID(); bool flag = (Object)(object)m_piece != (Object)null && m_piece.GetCreator() == playerID; bool flag2 = m_privateArea.IsPermitted(playerID); if (flag || flag2) { m_intruders[intruderName] = Time.time; string text = Localization.instance.Localize("$territoryward_intrusion_alert", new string[1] { intruderName }); ((Character)Player.m_localPlayer).Message((MessageType)2, text, 0, (Sprite)null); VFXManager.PlayIntrusionAlert(((Component)Player.m_localPlayer).transform.position); if ((Object)(object)Chat.instance != (Object)null) { string text2 = Localization.instance.Localize("$territoryward_intrusion_chat", new string[1] { intruderName }); ((Terminal)Chat.instance).AddString("", text2, (Type)1, false); } } } private void Update() { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) UpdateAreaMarkerForBuilding(); bool flag = IsShielded(); if (flag && (Object)(object)m_shieldGenObject == (Object)null) { StartShieldVFX(); } if (!flag && (Object)(object)m_shieldGenObject != (Object)null) { StopShieldVFX(); } if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)m_privateArea == (Object)null) { return; } float num = Vector3.Distance(((Component)Player.m_localPlayer).transform.position, ((Component)this).transform.position); if ((Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303)) && Input.GetKeyDown((KeyCode)101) && num <= 5f && IsHoveredByLocalPlayer(((Component)this).gameObject)) { if (m_privateArea.m_piece.IsCreator()) { m_showWhitelistUI = !m_showWhitelistUI; if (m_showWhitelistUI) { RefreshWhitelistUI(); } } else { m_nview.InvokeRPC("TogglePermitted", new object[2] { Player.m_localPlayer.GetPlayerID(), Player.m_localPlayer.GetPlayerName() }); } } else if (Input.GetKeyDown(TerritoryConfig.FuelStorageKey.Value) && num <= 5f && IsHoveredByLocalPlayer(((Component)this).gameObject)) { if ((Object)(object)m_container != (Object)null) { ApplyLevel(m_level); m_container.Interact((Humanoid)(object)Player.m_localPlayer, false, false); } } else if (Plugin.RangeRingButton != null && ZInput.GetButtonDown(Plugin.RangeRingButton.Name) && num <= 5f && IsHoveredByLocalPlayer(((Component)this).gameObject)) { m_showRangeRing = !m_showRangeRing; } else if (Plugin.ShieldButton != null && ZInput.GetButtonDown(Plugin.ShieldButton.Name)) { HandleShieldActivation(num); } else if (ZInput.GetButtonDown(Plugin.UpgradeButton.Name)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"[Territory] U key pressed near ward"); } if (num > 3f) { ((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_upgrade_too_far", 0, (Sprite)null); } else if ((Object)(object)m_piece == (Object)null || !m_piece.IsCreator()) { ((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_upgrade_not_creator", 0, (Sprite)null); } else if (m_level >= 8) { ((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_max_level", 0, (Sprite)null); } else { TryUpgrade(); } } } private static bool IsHoveredByLocalPlayer(GameObject obj) { try { object? obj2 = s_hoveringField?.GetValue(Player.m_localPlayer); GameObject val = (GameObject)((obj2 is GameObject) ? obj2 : null); return (Object)(object)val != (Object)null && (Object)(object)((Component)val.transform.root).gameObject == (Object)(object)obj; } catch { return false; } } private void UpdateAreaMarkerForBuilding() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)m_privateArea == (Object)null)) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null && ((Object)(object)localPlayer.m_placementGhost != (Object)null || m_showRangeRing) && Vector3.Distance(((Component)localPlayer).transform.position, ((Component)this).transform.position) <= m_privateArea.m_radius + 20f) { m_privateArea.ShowAreaMarker(); } } } public string GetUpgradeRequirementText() { if (m_level >= 8) { return Localization.instance.Localize("$territoryward_max_level"); } TerritoryConfig.UpgradeCostInfo upgradeCost = TerritoryConfig.GetUpgradeCost(m_level + 1); string text = Localization.instance.Localize(Resolve(upgradeCost.ItemA) ?? upgradeCost.ItemA); string text2 = Localization.instance.Localize(Resolve(upgradeCost.ItemB) ?? upgradeCost.ItemB); string text3 = $"{text} x{upgradeCost.ItemAAmount} + {text2} x{upgradeCost.ItemBAmount}"; if (upgradeCost.Coins > 0) { string arg = Localization.instance.Localize(Resolve("Coins") ?? "$item_coins"); text3 += $" + {arg} x{upgradeCost.Coins}"; } return text3; } public int GetLevel() { return m_level; } private static string FormatTierItems(string nameA, int amountA, string nameB, int amountB, string nameC, int amountC) { string text = $"{Localization.instance.Localize(nameA)} {amountA}, {Localization.instance.Localize(nameB)} {amountB}"; if (!string.IsNullOrEmpty(nameC)) { text += $", {Localization.instance.Localize(nameC)} {amountC}"; } return text; } public string GetFuelInfoText() { string text = Localization.instance.Localize("$territoryward_fuel_or"); List list = new List(); foreach (ResolvedTier tier in m_tiers) { string text2 = (tier.IntervalSeconds / 60f).ToString("0"); string text3 = Localization.instance.Localize("$territoryward_fuel_per_minutes", new string[1] { text2 }); list.Add(text3 + " " + FormatTierItems(tier.NameA, tier.AmountA, tier.NameB, tier.AmountB, tier.NameC, tier.AmountC)); } return string.Join("\n" + text + "\n", list); } public string GetNextLevelFuelInfoText() { if (m_level >= 8) { return ""; } List fuelTiers = TerritoryConfig.GetFuelTiers(m_level + 1); TerritoryConfig.FuelTier fuelTier = fuelTiers[fuelTiers.Count - 1]; string nameA = Resolve(fuelTier.ItemA) ?? fuelTier.ItemA; string nameB = Resolve(fuelTier.ItemB) ?? fuelTier.ItemB; string nameC = (string.IsNullOrEmpty(fuelTier.ItemC) ? null : (Resolve(fuelTier.ItemC) ?? fuelTier.ItemC)); string text = (fuelTier.IntervalSeconds / 60f).ToString("0"); string text2 = Localization.instance.Localize("$territoryward_fuel_per_minutes", new string[1] { text }); return text2 + " " + FormatTierItems(nameA, fuelTier.AmountA, nameB, fuelTier.AmountB, nameC, fuelTier.AmountC); } public string GetNextLevelFullFuelText() { if (m_level >= 8) { return ""; } int uptoLevel = m_level + 1; List fuelTiers = TerritoryConfig.GetFuelTiers(uptoLevel); if (fuelTiers.Count == 0) { return ""; } string text = Localization.instance.Localize("$territoryward_fuel_or"); List list = new List(); foreach (TerritoryConfig.FuelTier item in fuelTiers) { string nameA = Resolve(item.ItemA) ?? item.ItemA; string nameB = Resolve(item.ItemB) ?? item.ItemB; string nameC = (string.IsNullOrEmpty(item.ItemC) ? null : (Resolve(item.ItemC) ?? item.ItemC)); string text2 = (item.IntervalSeconds / 60f).ToString("0"); string text3 = Localization.instance.Localize("$territoryward_fuel_per_minutes", new string[1] { text2 }); list.Add(text3 + " " + FormatTierItems(nameA, item.AmountA, nameB, item.AmountB, nameC, item.AmountC)); } return string.Join("\n" + text + "\n", list); } public float? GetNextLevelRadius() { if (m_level >= 8) { return null; } return TerritoryConfig.GetRadius(m_level + 1); } private void TryUpgrade() { //IL_0244: Unknown result type (might be due to invalid IL or missing references) int num = m_level + 1; TerritoryConfig.UpgradeCostInfo upgradeCost = TerritoryConfig.GetUpgradeCost(num); if (!TerritoryConfig.AdminBypass.Value) { Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory(); string text = Resolve(upgradeCost.ItemA) ?? upgradeCost.ItemA; string text2 = Resolve(upgradeCost.ItemB) ?? upgradeCost.ItemB; string text3 = Resolve("Coins") ?? "$item_coins"; int num2 = inventory.CountItems(text, -1, false); int num3 = inventory.CountItems(text2, -1, false); int num4 = inventory.CountItems(text3, -1, false); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"[Territory] TryUpgrade Lv{num}: A:{num2}/{upgradeCost.ItemAAmount}, B:{num3}/{upgradeCost.ItemBAmount}, Coin:{num4}/{upgradeCost.Coins}"); } List list = new List(); string text4 = Localization.instance.Localize("$territoryward_missing_fuel_suffix"); if (num2 < upgradeCost.ItemAAmount) { list.Add(Localization.instance.Localize(text) + text4); } if (num3 < upgradeCost.ItemBAmount) { list.Add(Localization.instance.Localize(text2) + text4); } if (num4 < upgradeCost.Coins) { list.Add(Localization.instance.Localize(text3) + text4); } if (list.Count > 0) { ((Character)Player.m_localPlayer).Message((MessageType)2, string.Join("\n", list), 0, (Sprite)null); return; } inventory.RemoveItem(text, upgradeCost.ItemAAmount, -1, true); inventory.RemoveItem(text2, upgradeCost.ItemBAmount, -1, true); if (upgradeCost.Coins > 0) { inventory.RemoveItem(text3, upgradeCost.Coins, -1, true); } } m_nview.InvokeRPC(ZNetView.Everybody, "RPC_ApplyLevel", new object[1] { num }); VFXManager.PlayUpgradeEffect(((Component)this).transform.position); ((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_upgrade_success", 0, (Sprite)null); } public bool IsShielded() { if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid()) { return false; } float num = m_nview.GetZDO().GetFloat("tw_shield_end", 0f); return (Object)(object)ZNet.instance != (Object)null && ZNet.instance.GetTimeSeconds() < (double)num; } public float GetShieldRemainingMinutes() { if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid()) { return 0f; } float num = m_nview.GetZDO().GetFloat("tw_shield_end", 0f); float num2 = num - (float)ZNet.instance.GetTimeSeconds(); return Mathf.Max(0f, num2 / 60f); } public float GetShieldBankedRemainingMinutes() { if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid()) { return 0f; } return m_nview.GetZDO().GetFloat("tw_shield_remaining", 0f) / 60f; } private void StartShieldVFX() { //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)m_shieldGenObject != (Object)null) { return; } ZNetScene instance = ZNetScene.instance; GameObject val = ((instance != null) ? instance.GetPrefab("charred_shieldgenerator") : null); ShieldGenerator val2 = ((val != null) ? val.GetComponent() : null); if ((Object)(object)val2?.m_shieldDome == (Object)null) { if (!s_shieldTemplateUnavailableLogged) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"[Territory] charred_shieldgenerator ShieldGenerator not found — shield VFX skipped"); } s_shieldTemplateUnavailableLogged = true; } return; } if ((Object)(object)ShieldGenerator.m_shieldDomeEffect == (Object)null) { ShieldGenerator.m_shieldDomeEffect = Object.FindObjectOfType(); } if (!((Object)(object)ShieldGenerator.m_shieldDomeEffect == (Object)null)) { m_shieldGenObject = new GameObject("TW_ShieldVFX"); m_shieldGenObject.transform.position = ((Component)this).transform.position; GameObject val3 = Object.Instantiate(val2.m_shieldDome); val3.transform.SetParent(m_shieldGenObject.transform); val3.transform.localPosition = Vector3.zero; val3.SetActive(true); ShieldGenerator val4 = m_shieldGenObject.AddComponent(); val4.m_shieldDome = val3; val4.m_minShieldRadius = m_privateArea.m_radius; val4.m_maxShieldRadius = m_privateArea.m_radius; val4.m_radiusTarget = m_privateArea.m_radius; val4.m_radius = m_privateArea.m_radius; val4.m_lastFuel = 1f; val4.m_maxFuel = 1; val4.m_fuelPerDamage = 0f; val4.m_enableAttack = false; val4.m_energyParticles = (ParticleSystem[])(object)new ParticleSystem[0]; val4.m_coloredLights = (Light[])(object)new Light[0]; } } private void StopShieldVFX() { if (!((Object)(object)m_shieldGenObject == (Object)null)) { Object.Destroy((Object)(object)m_shieldGenObject); m_shieldGenObject = null; } } private void HandleShieldActivation(float dist) { if (!m_privateArea.m_piece.IsCreator() || dist > 5f || !IsHoveredByLocalPlayer(((Component)this).gameObject)) { return; } if (m_level < 5) { ((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_shield_low_level", 0, (Sprite)null); return; } if (IsShielded()) { m_nview.InvokeRPC(ZNetView.Everybody, "RPC_DeactivateShield", Array.Empty()); ((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_shield_stopped", 0, (Sprite)null); return; } float num = (((Object)(object)m_nview != (Object)null && m_nview.IsValid()) ? m_nview.GetZDO().GetFloat("tw_shield_remaining", 0f) : 0f); if (num > 0f) { m_nview.InvokeRPC(ZNetView.Everybody, "RPC_ActivateShield", new object[1] { num }); ((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_shield_resumed", 0, (Sprite)null); return; } string text = Resolve(TerritoryConfig.ShieldItemName.Value) ?? TerritoryConfig.ShieldItemName.Value; Inventory inventory = m_container.GetInventory(); if (inventory.CountItems(text, -1, false) < 1) { ((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_shield_no_item", 0, (Sprite)null); return; } inventory.RemoveItem(text, 1, -1, true); m_nview.InvokeRPC(ZNetView.Everybody, "RPC_ActivateShield", new object[1] { 3600f }); ((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_shield_started", 0, (Sprite)null); } private void RPC_ActivateShield(long sender, float duration) { if (!((Object)(object)m_nview == (Object)null) && m_nview.IsOwner()) { m_nview.GetZDO().Set("tw_shield_end", (float)ZNet.instance.GetTimeSeconds() + duration); m_nview.GetZDO().Set("tw_shield_remaining", 0f); } } private void RPC_DeactivateShield(long sender) { if (!((Object)(object)m_nview == (Object)null) && m_nview.IsOwner()) { float num = (float)ZNet.instance.GetTimeSeconds(); float num2 = m_nview.GetZDO().GetFloat("tw_shield_end", 0f); m_nview.GetZDO().Set("tw_shield_remaining", Mathf.Max(0f, num2 - num)); m_nview.GetZDO().Set("tw_shield_end", num); } } internal static string Resolve(string prefabName, bool warnIfMissing = true) { if ((Object)(object)ObjectDB.instance == (Object)null) { return null; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefabName); string text = ((itemPrefab == null) ? null : itemPrefab.GetComponent()?.m_itemData.m_shared.m_name); if (text == null && warnIfMissing) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Territory] Resolve: '" + prefabName + "' not found in ObjectDB — CountItems will return 0")); } } return text; } private void CheckConsumption() { if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid() || !m_nview.IsOwner() || (Object)(object)m_privateArea == (Object)null || (Object)(object)m_container == (Object)null || m_tiers.Count == 0) { return; } bool flag = m_privateArea.IsEnabled(); if (flag && !m_wasEnabled) { m_fuelDepleted = false; m_missingFuelWarned = false; } m_wasEnabled = flag; if (!flag) { return; } Inventory inv = m_container.GetInventory(); if (!m_tiers.Exists((ResolvedTier t) => HasTier(inv, t))) { if (!m_missingFuelWarned) { m_missingFuelWarned = true; string itemName = Localization.instance.Localize(m_tiers[0].NameA); ((MonoBehaviour)this).StartCoroutine(ShowMissingFuelAlert(itemName)); } } else { m_missingFuelWarned = false; } float num = m_nview.GetZDO().GetFloat("tw_lastConsume", 0f); float num2 = (float)ZNet.instance.GetTimeSeconds(); float num3 = num2 - num; for (int num4 = m_tiers.Count - 1; num4 >= 0; num4--) { ResolvedTier tier = m_tiers[num4]; if (!(num3 < tier.IntervalSeconds) && HasTier(inv, tier)) { inv.RemoveItem(tier.NameA, tier.AmountA, -1, true); inv.RemoveItem(tier.NameB, tier.AmountB, -1, true); if (!string.IsNullOrEmpty(tier.NameC)) { inv.RemoveItem(tier.NameC, tier.AmountC, -1, true); } ShowConsumeText(tier); VFXManager.PlayWardConsumeEffect(((Component)this).transform); m_nview.GetZDO().Set("tw_lastConsume", num2); m_fuelDepleted = false; return; } } if (num3 >= m_tiers[0].IntervalSeconds && !m_fuelDepleted) { m_fuelDepleted = true; m_nview.GetZDO().Set("tw_lastConsume", num2); if (m_privateArea.IsEnabled()) { long num5 = (((Object)(object)m_piece != (Object)null) ? m_piece.GetCreator() : 0); m_nview.InvokeRPC(ZNetView.Everybody, "ToggleEnabled", new object[1] { num5 }); } ((MonoBehaviour)this).StartCoroutine(ShowFuelAlert(5)); } } private bool HasTier(Inventory inv, ResolvedTier tier) { return inv.CountItems(tier.NameA, -1, false) >= tier.AmountA && inv.CountItems(tier.NameB, -1, false) >= tier.AmountB && (string.IsNullOrEmpty(tier.NameC) || inv.CountItems(tier.NameC, -1, false) >= tier.AmountC); } private void ShowConsumeText(ResolvedTier tier) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_0056: 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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)DamageText.instance == (Object)null)) { string arg = Localization.instance.Localize(tier.NameA); string arg2 = Localization.instance.Localize(tier.NameB); Vector3 val = ((Component)this).transform.position + Vector3.up * 2.5f; DamageText.instance.ShowText((TextType)0, val, $"{arg} -{tier.AmountA}", false); DamageText.instance.ShowText((TextType)0, val + Vector3.up * 0.4f, $"{arg2} -{tier.AmountB}", false); if (!string.IsNullOrEmpty(tier.NameC)) { string arg3 = Localization.instance.Localize(tier.NameC); DamageText.instance.ShowText((TextType)0, val + Vector3.up * 0.8f, $"{arg3} -{tier.AmountC}", false); } } } private IEnumerator ShowMissingFuelAlert(string itemName) { string suffix = Localization.instance.Localize("$territoryward_missing_fuel_suffix"); string text = itemName + suffix; for (int i = 0; i < 3; i++) { if ((Object)(object)Player.m_localPlayer != (Object)null) { float dist = Vector3.Distance(((Component)Player.m_localPlayer).transform.position, ((Component)this).transform.position); if (dist <= m_privateArea.m_radius) { ((Character)Player.m_localPlayer).Message((MessageType)2, text, 0, (Sprite)null); } } yield return (object)new WaitForSeconds(2f); } } private IEnumerator ShowFuelAlert(int count) { for (int i = 0; i < count; i++) { if ((Object)(object)Player.m_localPlayer != (Object)null) { float dist = Vector3.Distance(((Component)Player.m_localPlayer).transform.position, ((Component)this).transform.position); if (dist <= m_privateArea.m_radius) { ((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_no_fuel", 0, (Sprite)null); } } yield return (object)new WaitForSeconds(1f); } } internal void RefreshWhitelistUI() { m_uiPermitted.Clear(); if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid()) { return; } ZDO zDO = m_nview.GetZDO(); int num = zDO.GetInt("permitted", 0); for (int i = 0; i < num; i++) { long num2 = zDO.GetLong("pu_id" + i, 0L); string value = zDO.GetString("pu_name" + i, ""); if (num2 != 0L && !string.IsNullOrEmpty(value)) { m_uiPermitted.Add(new KeyValuePair(num2, value)); } } } private void DrawIntruderLabels() { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0166: 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_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) if (m_intruders.Count == 0) { return; } if ((Object)(object)m_privateArea == (Object)null || !m_privateArea.IsEnabled()) { m_intruders.Clear(); return; } Camera mainCamera = Utils.GetMainCamera(); if ((Object)(object)mainCamera == (Object)null) { return; } if (s_intruderStyle == null) { s_intruderStyle = new GUIStyle(GUI.skin.label); s_intruderStyle.normal.textColor = Color.red; s_intruderStyle.fontSize = 16; } List list = new List(); foreach (KeyValuePair intruder in m_intruders) { if (Time.time - intruder.Value > 3600f) { list.Add(intruder.Key); continue; } foreach (Character allCharacter in Character.GetAllCharacters()) { if (!allCharacter.IsPlayer()) { continue; } Player val = (Player)(object)((allCharacter is Player) ? allCharacter : null); if ((Object)(object)val == (Object)null || val.GetPlayerName() != intruder.Key) { continue; } Vector3 val2 = mainCamera.WorldToScreenPoint(allCharacter.GetHeadPoint() + Vector3.up * 0.5f); if (!(val2.z <= 0f)) { GUI.Label(new Rect(val2.x - 40f, (float)Screen.height - val2.y - 20f, 80f, 25f), "침입자", s_intruderStyle); } break; } } foreach (string item in list) { m_intruders.Remove(item); } } private void DrawShieldHUD() { //IL_0046: 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_0120: 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) //IL_0098: Expected O, but got Unknown //IL_00be: Unknown result type (might be due to invalid IL or missing references) if (!IsShielded() || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)m_privateArea == (Object)null) { return; } float num = Vector3.Distance(((Component)Player.m_localPlayer).transform.position, ((Component)this).transform.position); if (!(num > m_privateArea.m_radius)) { if (s_shieldHUDStyle == null) { s_shieldHUDStyle = new GUIStyle(GUI.skin.label); s_shieldHUDStyle.fontSize = 14; s_shieldHUDStyle.normal.textColor = new Color(0.4f, 0.9f, 1f); } int num2 = Mathf.CeilToInt(GetShieldRemainingMinutes()); string text = Localization.instance.Localize("$territoryward_shield_hud", new string[1] { num2.ToString() }); float num3 = 320f; float num4 = 28f; GUI.Label(new Rect(((float)Screen.width - num3) / 2f, (float)Screen.height * 0.82f, num3, num4), text, s_shieldHUDStyle); } } private void OnGUI() { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_0119: 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_0134: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Expected O, but got Unknown //IL_00e3: Unknown result type (might be due to invalid IL or missing references) DrawIntruderLabels(); DrawShieldHUD(); if (!m_showWhitelistUI || (Object)(object)m_privateArea == (Object)null || !m_privateArea.m_piece.IsCreator()) { return; } if (s_titleStyle == null) { s_titleStyle = new GUIStyle(GUI.skin.label); s_titleStyle.fontSize = 15; s_titleStyle.normal.textColor = new Color(0.9f, 0.85f, 0.5f); } if (s_sectionStyle == null) { s_sectionStyle = new GUIStyle(GUI.skin.label); s_sectionStyle.normal.textColor = new Color(0.6f, 0.8f, 1f); } float num = 300f; float num2 = 360f; float num3 = ((float)Screen.width - num) / 2f; float num4 = ((float)Screen.height - num2) / 2f; Color color = GUI.color; GUI.color = new Color(0.08f, 0.08f, 0.12f, 0.92f); GUI.DrawTexture(new Rect(num3 - 8f, num4 - 30f, num + 16f, num2 + 38f), (Texture)(object)Texture2D.whiteTexture); GUI.color = color; GUI.Box(new Rect(num3 - 8f, num4 - 30f, num + 16f, num2 + 38f), ""); GUILayout.BeginArea(new Rect(num3, num4 - 24f, num, num2 + 28f)); GUILayout.Label("[ 영토 와드 멤버 관리 ]", s_titleStyle, Array.Empty()); GUILayout.Box("", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Height(1f), GUILayout.ExpandWidth(true) }); GUILayout.Label("허용된 멤버", s_sectionStyle, Array.Empty()); m_uiScrollPos = GUILayout.BeginScrollView(m_uiScrollPos, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(130f) }); if (m_uiPermitted.Count == 0) { GUILayout.Label("(없음)", Array.Empty()); } else { foreach (KeyValuePair item in m_uiPermitted) { GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label(item.Value, Array.Empty()); if (GUILayout.Button("추방", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(55f) })) { m_nview.InvokeRPC("TogglePermitted", new object[2] { item.Key, item.Value }); RefreshWhitelistUI(); } GUILayout.EndHorizontal(); } } GUILayout.EndScrollView(); GUILayout.Box("", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Height(1f), GUILayout.ExpandWidth(true) }); GUILayout.Label("온라인 플레이어 추가", s_sectionStyle, Array.Empty()); if ((Object)(object)ZNet.instance != (Object)null) { List connectedPeers = ZNet.instance.GetConnectedPeers(); if (connectedPeers.Count == 0) { GUILayout.Label("(접속 중인 플레이어 없음)", Array.Empty()); } else { foreach (ZNetPeer item2 in connectedPeers) { if (!m_privateArea.IsPermitted(item2.m_uid) && GUILayout.Button("+ " + item2.m_playerName, Array.Empty())) { m_nview.InvokeRPC("TogglePermitted", new object[2] { item2.m_uid, item2.m_playerName }); RefreshWhitelistUI(); } } } } GUILayout.FlexibleSpace(); if (GUILayout.Button("닫기", Array.Empty())) { m_showWhitelistUI = false; } GUILayout.EndArea(); } } }