Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Captain territorial v1.0.22
Captain_territorial.dll
Decompiled 19 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.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<AutoCleanup>()._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<GameObject>() : 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<GameObject>(prefab, position, Quaternion.identity); prefab.SetActive(activeSelf); ZNetView component = val.GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null) { Object.DestroyImmediate((Object)(object)component); } ZSyncTransform component2 = val.GetComponent<ZSyncTransform>(); 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<ZNetView>(); 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<bool> AdminBypass; public static ConfigEntry<bool> Enabled; public static ConfigEntry<int> WardLimit; public static ConfigEntry<KeyCode> UpgradeKey; public static ConfigEntry<KeyCode> ShieldKey; public static ConfigEntry<KeyCode> RangeRingKey; public static ConfigEntry<KeyCode> FuelStorageKey; public static ConfigEntry<float> Lv1Radius; public static ConfigEntry<string> Lv1FuelA; public static ConfigEntry<int> Lv1FuelAAmount; public static ConfigEntry<string> Lv1FuelB; public static ConfigEntry<int> Lv1FuelBAmount; public static ConfigEntry<float> Lv1IntervalMinutes; public static ConfigEntry<float> Lv2Radius; public static ConfigEntry<string> Lv2FuelA; public static ConfigEntry<int> Lv2FuelAAmount; public static ConfigEntry<string> Lv2FuelB; public static ConfigEntry<int> Lv2FuelBAmount; public static ConfigEntry<float> Lv2IntervalMinutes; public static ConfigEntry<float> Lv3Radius; public static ConfigEntry<string> Lv3FuelA; public static ConfigEntry<int> Lv3FuelAAmount; public static ConfigEntry<string> Lv3FuelB; public static ConfigEntry<int> Lv3FuelBAmount; public static ConfigEntry<float> Lv3IntervalMinutes; public static ConfigEntry<float> Lv4Radius; public static ConfigEntry<string> Lv4FuelA; public static ConfigEntry<int> Lv4FuelAAmount; public static ConfigEntry<string> Lv4FuelB; public static ConfigEntry<int> Lv4FuelBAmount; public static ConfigEntry<float> Lv4IntervalMinutes; public static ConfigEntry<float> Lv5Radius; public static ConfigEntry<string> Lv5FuelA; public static ConfigEntry<int> Lv5FuelAAmount; public static ConfigEntry<string> Lv5FuelB; public static ConfigEntry<int> Lv5FuelBAmount; public static ConfigEntry<float> Lv5IntervalMinutes; public static ConfigEntry<float> Lv6Radius; public static ConfigEntry<string> Lv6FuelA; public static ConfigEntry<int> Lv6FuelAAmount; public static ConfigEntry<string> Lv6FuelB; public static ConfigEntry<int> Lv6FuelBAmount; public static ConfigEntry<string> Lv6FuelC; public static ConfigEntry<int> Lv6FuelCAmount; public static ConfigEntry<float> Lv6IntervalMinutes; public static ConfigEntry<float> Lv7Radius; public static ConfigEntry<string> Lv7FuelA; public static ConfigEntry<int> Lv7FuelAAmount; public static ConfigEntry<string> Lv7FuelB; public static ConfigEntry<int> Lv7FuelBAmount; public static ConfigEntry<float> Lv7IntervalMinutes; public static ConfigEntry<float> Lv8Radius; public static ConfigEntry<string> Lv8FuelA; public static ConfigEntry<int> Lv8FuelAAmount; public static ConfigEntry<string> Lv8FuelB; public static ConfigEntry<int> Lv8FuelBAmount; public static ConfigEntry<string> Lv8FuelC; public static ConfigEntry<int> Lv8FuelCAmount; public static ConfigEntry<float> Lv8IntervalMinutes; public static ConfigEntry<string> Lv2UpgradeItemA; public static ConfigEntry<int> Lv2UpgradeItemAAmount; public static ConfigEntry<string> Lv2UpgradeItemB; public static ConfigEntry<int> Lv2UpgradeItemBAmount; public static ConfigEntry<int> Lv2UpgradeCoins; public static ConfigEntry<string> Lv3UpgradeItemA; public static ConfigEntry<int> Lv3UpgradeItemAAmount; public static ConfigEntry<string> Lv3UpgradeItemB; public static ConfigEntry<int> Lv3UpgradeItemBAmount; public static ConfigEntry<int> Lv3UpgradeCoins; public static ConfigEntry<string> Lv4UpgradeItemA; public static ConfigEntry<int> Lv4UpgradeItemAAmount; public static ConfigEntry<string> Lv4UpgradeItemB; public static ConfigEntry<int> Lv4UpgradeItemBAmount; public static ConfigEntry<int> Lv4UpgradeCoins; public static ConfigEntry<string> Lv5UpgradeItemA; public static ConfigEntry<int> Lv5UpgradeItemAAmount; public static ConfigEntry<string> Lv5UpgradeItemB; public static ConfigEntry<int> Lv5UpgradeItemBAmount; public static ConfigEntry<int> Lv5UpgradeCoins; public static ConfigEntry<string> Lv6UpgradeItemA; public static ConfigEntry<int> Lv6UpgradeItemAAmount; public static ConfigEntry<string> Lv6UpgradeItemB; public static ConfigEntry<int> Lv6UpgradeItemBAmount; public static ConfigEntry<int> Lv6UpgradeCoins; public static ConfigEntry<string> Lv7UpgradeItemA; public static ConfigEntry<int> Lv7UpgradeItemAAmount; public static ConfigEntry<string> Lv7UpgradeItemB; public static ConfigEntry<int> Lv7UpgradeItemBAmount; public static ConfigEntry<int> Lv7UpgradeCoins; public static ConfigEntry<string> Lv8UpgradeItemA; public static ConfigEntry<int> Lv8UpgradeItemAAmount; public static ConfigEntry<string> Lv8UpgradeItemB; public static ConfigEntry<int> Lv8UpgradeItemBAmount; public static ConfigEntry<int> Lv8UpgradeCoins; public static ConfigEntry<bool> DoorAutoCloseEnabled; public static ConfigEntry<float> DoorAutoCloseDelay; public static ConfigEntry<string> ShieldItemName; public static void Init(ConfigFile cfg) { AdminBypass = B<bool>("General", "admin_bypass", def: false, "관리자 전용: 켜면 설치 개수 제한·설치 재료비·업그레이드 재료/골드 비용을 모두 무시하고 즉시 설치·업그레이드할 수 있습니다 (연료 유지비는 그대로 적용됩니다).", 200); Enabled = B<bool>("General", "territorial_ward", def: true, "영토 와드 시스템 활성화 여부 (false = 비활성화)", 190); WardLimit = B<int>("General", "ward_limit", 2, "캐릭터 1명당 설치 가능한 영토 와드 수", 180); DoorAutoCloseEnabled = B<bool>("General", "door_auto_close", def: true, "와드 구역 내 문 자동 닫힘 활성화", 170); DoorAutoCloseDelay = B<float>("General", "door_auto_close_delay", 5f, "문 자동 닫힘 대기 시간 (초)", 160); ShieldItemName = B<string>("General", "shield_item", "SurtlingCore", "Lv5+ 데미지 보호 소모 아이템 (프리팹명)", 150); UpgradeKey = B<KeyCode>("General", "upgrade_key", (KeyCode)117, "영토 와드 업그레이드 키", 140); ShieldKey = B<KeyCode>("General", "shield_key", (KeyCode)107, "Lv5+ 영토 보호 실드 활성화/비활성화 키", 130); RangeRingKey = B<KeyCode>("General", "range_ring_key", (KeyCode)114, "범위 링 수동 토글 키", 120); FuelStorageKey = B<KeyCode>("General", "fuel_storage_key", (KeyCode)113, "연료 창고 열기 키", 110); Lv1Radius = B<float>("Level 1 - 초원", "radius", 10f, "레벨 1 반경 (미터)", 100); Lv1FuelA = B<string>("Level 1 - 초원", "fuel_primary", "Wood", "레벨 1 주 연료 — 나무 (프리팹명)", 90); Lv1FuelAAmount = B<int>("Level 1 - 초원", "fuel_primary_amount", 1, "레벨 1 주 연료 소모량", 89); Lv1FuelB = B<string>("Level 1 - 초원", "fuel_secondary", "Resin", "레벨 1 보조 연료 — 수지 (프리팹명)", 88); Lv1FuelBAmount = B<int>("Level 1 - 초원", "fuel_secondary_amount", 1, "레벨 1 보조 연료 소모량", 87); Lv1IntervalMinutes = B<float>("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<float>("Level 2 - 검은숲", "radius", 13f, "레벨 2 반경 (미터)", 100); Lv2FuelA = B<string>("Level 2 - 검은숲", "fuel_primary", "RoundLog", "레벨 2 주 연료 — 원목 (프리팹명)", 90); Lv2FuelAAmount = B<int>("Level 2 - 검은숲", "fuel_primary_amount", 1, "레벨 2 주 연료 소모량", 89); Lv2FuelB = B<string>("Level 2 - 검은숲", "fuel_secondary", "Resin", "레벨 2 보조 연료 — 수지 (프리팹명)", 88); Lv2FuelBAmount = B<int>("Level 2 - 검은숲", "fuel_secondary_amount", 1, "레벨 2 보조 연료 소모량", 87); Lv2IntervalMinutes = B<float>("Level 2 - 검은숲", "fuel_interval_minutes", 4f, "레벨 2 연료 소모 간격 (분)", 80); Lv2UpgradeItemA = B<string>("Level 2 - 검은숲", "upgrade_item_primary", "RoundLog", "Lv2 업그레이드 주 재료 (원목)", 70); Lv2UpgradeItemAAmount = B<int>("Level 2 - 검은숲", "upgrade_item_primary_amount", 10, "Lv2 업그레이드 주 재료 수량", 69); Lv2UpgradeItemB = B<string>("Level 2 - 검은숲", "upgrade_item_secondary", "GreydwarfEye", "Lv2 업그레이드 보조 재료 (그레이드워프 눈)", 68); Lv2UpgradeItemBAmount = B<int>("Level 2 - 검은숲", "upgrade_item_secondary_amount", 5, "Lv2 업그레이드 보조 재료 수량", 67); Lv2UpgradeCoins = B<int>("Level 2 - 검은숲", "upgrade_coins", 0, "Lv2 업그레이드 골드(Coins) 비용", 60); Lv3Radius = B<float>("Level 3 - 늪지", "radius", 16f, "레벨 3 반경 (미터)", 100); Lv3FuelA = B<string>("Level 3 - 늪지", "fuel_primary", "ElderBark", "레벨 3 주 연료 — 고대나무껍질 (프리팹명)", 90); Lv3FuelAAmount = B<int>("Level 3 - 늪지", "fuel_primary_amount", 2, "레벨 3 주 연료 소모량", 89); Lv3FuelB = B<string>("Level 3 - 늪지", "fuel_secondary", "Resin", "레벨 3 보조 연료 — 수지 (프리팹명)", 88); Lv3FuelBAmount = B<int>("Level 3 - 늪지", "fuel_secondary_amount", 1, "레벨 3 보조 연료 소모량", 87); Lv3IntervalMinutes = B<float>("Level 3 - 늪지", "fuel_interval_minutes", 5f, "레벨 3 연료 소모 간격 (분)", 80); Lv3UpgradeItemA = B<string>("Level 3 - 늪지", "upgrade_item_primary", "ElderBark", "Lv3 업그레이드 주 재료 (고대나무껍질)", 70); Lv3UpgradeItemAAmount = B<int>("Level 3 - 늪지", "upgrade_item_primary_amount", 15, "Lv3 업그레이드 주 재료 수량", 69); Lv3UpgradeItemB = B<string>("Level 3 - 늪지", "upgrade_item_secondary", "Entrails", "Lv3 업그레이드 보조 재료 (창자)", 68); Lv3UpgradeItemBAmount = B<int>("Level 3 - 늪지", "upgrade_item_secondary_amount", 8, "Lv3 업그레이드 보조 재료 수량", 67); Lv3UpgradeCoins = B<int>("Level 3 - 늪지", "upgrade_coins", 1000, "Lv3 업그레이드 골드(Coins) 비용", 60); Lv4Radius = B<float>("Level 4 - 산", "radius", 19f, "레벨 4 반경 (미터)", 100); Lv4FuelA = B<string>("Level 4 - 산", "fuel_primary", "Obsidian", "레벨 4 주 연료 — 흑요석 (산에는 지역 나무가 없어 대체) (프리팹명)", 90); Lv4FuelAAmount = B<int>("Level 4 - 산", "fuel_primary_amount", 2, "레벨 4 주 연료 소모량", 89); Lv4FuelB = B<string>("Level 4 - 산", "fuel_secondary", "Resin", "레벨 4 보조 연료 — 수지 (프리팹명)", 88); Lv4FuelBAmount = B<int>("Level 4 - 산", "fuel_secondary_amount", 1, "레벨 4 보조 연료 소모량", 87); Lv4IntervalMinutes = B<float>("Level 4 - 산", "fuel_interval_minutes", 6f, "레벨 4 연료 소모 간격 (분)", 80); Lv4UpgradeItemA = B<string>("Level 4 - 산", "upgrade_item_primary", "FreezeGland", "Lv4 업그레이드 주 재료 (얼음 분비선)", 70); Lv4UpgradeItemAAmount = B<int>("Level 4 - 산", "upgrade_item_primary_amount", 20, "Lv4 업그레이드 주 재료 수량", 69); Lv4UpgradeItemB = B<string>("Level 4 - 산", "upgrade_item_secondary", "Obsidian", "Lv4 업그레이드 보조 재료 (흑요석)", 68); Lv4UpgradeItemBAmount = B<int>("Level 4 - 산", "upgrade_item_secondary_amount", 11, "Lv4 업그레이드 보조 재료 수량", 67); Lv4UpgradeCoins = B<int>("Level 4 - 산", "upgrade_coins", 2000, "Lv4 업그레이드 골드(Coins) 비용", 60); Lv5Radius = B<float>("Level 5 - 평원", "radius", 22f, "레벨 5 반경 (미터)", 100); Lv5FuelA = B<string>("Level 5 - 평원", "fuel_primary", "FineWood", "레벨 5 주 연료 — 경목 (프리팹명)", 90); Lv5FuelAAmount = B<int>("Level 5 - 평원", "fuel_primary_amount", 3, "레벨 5 주 연료 소모량", 89); Lv5FuelB = B<string>("Level 5 - 평원", "fuel_secondary", "Resin", "레벨 5 보조 연료 — 수지 (프리팹명)", 88); Lv5FuelBAmount = B<int>("Level 5 - 평원", "fuel_secondary_amount", 1, "레벨 5 보조 연료 소모량", 87); Lv5IntervalMinutes = B<float>("Level 5 - 평원", "fuel_interval_minutes", 7f, "레벨 5 연료 소모 간격 (분)", 80); Lv5UpgradeItemA = B<string>("Level 5 - 평원", "upgrade_item_primary", "Barley", "Lv5 업그레이드 주 재료 (보리)", 70); Lv5UpgradeItemAAmount = B<int>("Level 5 - 평원", "upgrade_item_primary_amount", 25, "Lv5 업그레이드 주 재료 수량", 69); Lv5UpgradeItemB = B<string>("Level 5 - 평원", "upgrade_item_secondary", "Tar", "Lv5 업그레이드 보조 재료 (타르)", 68); Lv5UpgradeItemBAmount = B<int>("Level 5 - 평원", "upgrade_item_secondary_amount", 14, "Lv5 업그레이드 보조 재료 수량", 67); Lv5UpgradeCoins = B<int>("Level 5 - 평원", "upgrade_coins", 2500, "Lv5 업그레이드 골드(Coins) 비용", 60); Lv6Radius = B<float>("Level 6 - 바다", "radius", 25f, "레벨 6 반경 (미터)", 100); Lv6FuelA = B<string>("Level 6 - 바다", "fuel_primary", "Wood", "레벨 6 주 연료 — 나무 (바다에는 지역 나무가 없어 나무+원목으로 대체) (프리팹명)", 90); Lv6FuelAAmount = B<int>("Level 6 - 바다", "fuel_primary_amount", 2, "레벨 6 주 연료 소모량", 89); Lv6FuelB = B<string>("Level 6 - 바다", "fuel_secondary", "Resin", "레벨 6 보조 연료 — 수지 (프리팹명)", 88); Lv6FuelBAmount = B<int>("Level 6 - 바다", "fuel_secondary_amount", 1, "레벨 6 보조 연료 소모량", 87); Lv6FuelC = B<string>("Level 6 - 바다", "fuel_tertiary", "RoundLog", "레벨 6 추가 연료 — 원목 (프리팹명, 비워두면 미사용)", 86); Lv6FuelCAmount = B<int>("Level 6 - 바다", "fuel_tertiary_amount", 1, "레벨 6 추가 연료 소모량", 85); Lv6IntervalMinutes = B<float>("Level 6 - 바다", "fuel_interval_minutes", 8f, "레벨 6 연료 소모 간격 (분)", 80); Lv6UpgradeItemA = B<string>("Level 6 - 바다", "upgrade_item_primary", "Chitin", "Lv6 업그레이드 주 재료 (키틴)", 70); Lv6UpgradeItemAAmount = B<int>("Level 6 - 바다", "upgrade_item_primary_amount", 30, "Lv6 업그레이드 주 재료 수량", 69); Lv6UpgradeItemB = B<string>("Level 6 - 바다", "upgrade_item_secondary", "Ooze", "Lv6 업그레이드 보조 재료 (점액)", 68); Lv6UpgradeItemBAmount = B<int>("Level 6 - 바다", "upgrade_item_secondary_amount", 17, "Lv6 업그레이드 보조 재료 수량", 67); Lv6UpgradeCoins = B<int>("Level 6 - 바다", "upgrade_coins", 3000, "Lv6 업그레이드 골드(Coins) 비용", 60); Lv7Radius = B<float>("Level 7 - 미스트랜드", "radius", 28f, "레벨 7 반경 (미터)", 100); Lv7FuelA = B<string>("Level 7 - 미스트랜드", "fuel_primary", "YggdrasilWood", "레벨 7 주 연료 — 이그드라실 나무 (프리팹명)", 90); Lv7FuelAAmount = B<int>("Level 7 - 미스트랜드", "fuel_primary_amount", 4, "레벨 7 주 연료 소모량", 89); Lv7FuelB = B<string>("Level 7 - 미스트랜드", "fuel_secondary", "Resin", "레벨 7 보조 연료 — 수지 (프리팹명)", 88); Lv7FuelBAmount = B<int>("Level 7 - 미스트랜드", "fuel_secondary_amount", 1, "레벨 7 보조 연료 소모량", 87); Lv7IntervalMinutes = B<float>("Level 7 - 미스트랜드", "fuel_interval_minutes", 9f, "레벨 7 연료 소모 간격 (분)", 80); Lv7UpgradeItemA = B<string>("Level 7 - 미스트랜드", "upgrade_item_primary", "YggdrasilWood", "Lv7 업그레이드 주 재료 (이그드라실 나무)", 70); Lv7UpgradeItemAAmount = B<int>("Level 7 - 미스트랜드", "upgrade_item_primary_amount", 35, "Lv7 업그레이드 주 재료 수량", 69); Lv7UpgradeItemB = B<string>("Level 7 - 미스트랜드", "upgrade_item_secondary", "JotunPuffs", "Lv7 업그레이드 보조 재료 (요툰 버섯)", 68); Lv7UpgradeItemBAmount = B<int>("Level 7 - 미스트랜드", "upgrade_item_secondary_amount", 20, "Lv7 업그레이드 보조 재료 수량", 67); Lv7UpgradeCoins = B<int>("Level 7 - 미스트랜드", "upgrade_coins", 4000, "Lv7 업그레이드 골드(Coins) 비용", 60); Lv8Radius = B<float>("Level 8 - 애쉬랜드", "radius", 30f, "레벨 8 반경 (미터)", 100); Lv8FuelA = B<string>("Level 8 - 애쉬랜드", "fuel_primary", "Wood", "레벨 8 주 연료 — 나무 (애쉬랜드에는 지역 나무가 없어 나무+이그드라실 나무로 대체) (프리팹명)", 90); Lv8FuelAAmount = B<int>("Level 8 - 애쉬랜드", "fuel_primary_amount", 3, "레벨 8 주 연료 소모량", 89); Lv8FuelB = B<string>("Level 8 - 애쉬랜드", "fuel_secondary", "Resin", "레벨 8 보조 연료 — 수지 (프리팹명)", 88); Lv8FuelBAmount = B<int>("Level 8 - 애쉬랜드", "fuel_secondary_amount", 1, "레벨 8 보조 연료 소모량", 87); Lv8FuelC = B<string>("Level 8 - 애쉬랜드", "fuel_tertiary", "YggdrasilWood", "레벨 8 추가 연료 — 이그드라실 나무 (프리팹명, 비워두면 미사용)", 86); Lv8FuelCAmount = B<int>("Level 8 - 애쉬랜드", "fuel_tertiary_amount", 1, "레벨 8 추가 연료 소모량", 85); Lv8IntervalMinutes = B<float>("Level 8 - 애쉬랜드", "fuel_interval_minutes", 10f, "레벨 8 연료 소모 간격 (분)", 80); Lv8UpgradeItemA = B<string>("Level 8 - 애쉬랜드", "upgrade_item_primary", "CharredBone", "Lv8 업그레이드 주 재료 (불탄 뼈)", 70); Lv8UpgradeItemAAmount = B<int>("Level 8 - 애쉬랜드", "upgrade_item_primary_amount", 40, "Lv8 업그레이드 주 재료 수량", 69); Lv8UpgradeItemB = B<string>("Level 8 - 애쉬랜드", "upgrade_item_secondary", "Grausten", "Lv8 업그레이드 보조 재료 (그라우스텐 돌)", 68); Lv8UpgradeItemBAmount = B<int>("Level 8 - 애쉬랜드", "upgrade_item_secondary_amount", 23, "Lv8 업그레이드 보조 재료 수량", 67); Lv8UpgradeCoins = B<int>("Level 8 - 애쉬랜드", "upgrade_coins", 5000, "Lv8 업그레이드 골드(Coins) 비용", 60); ConfigEntry<T> B<T>(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<T>(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<FuelTier> GetFuelTiers(int uptoLevel) { List<FuelTier> list = new List<FuelTier>(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<TMP_Text> SlowRiseFields = new HashSet<TMP_Text>(); private static void Postfix(DamageText __instance, string text) { if (!string.IsNullOrEmpty(text) && text.Contains("<color=") && __instance.m_worldTexts.Count != 0) { WorldTextInstance val = __instance.m_worldTexts[__instance.m_worldTexts.Count - 1]; val.m_textField.richText = true; SlowRiseFields.Add(val.m_textField); } } } [HarmonyPatch(typeof(DamageText), "UpdateWorldTexts")] public static class Patch_DamageText_SlowRise { private const float SpeedFactor = 1f / 3f; private static void Postfix(DamageText __instance, float dt) { if (Patch_DamageText_RichText.SlowRiseFields.Count == 0) { return; } foreach (WorldTextInstance worldText in __instance.m_worldTexts) { if (Patch_DamageText_RichText.SlowRiseFields.Contains(worldText.m_textField)) { worldText.m_worldPos.y -= dt * 0.6666666f; if (worldText.m_timer > __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<KeyValuePair<long, string>> list)) { return true; } int num = list.FindIndex((KeyValuePair<long, string> kv) => kv.Key == playerID); if (num >= 0) { list.RemoveAt(num); } else { list.Add(new KeyValuePair<long, string>(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<TerritoryWardController>(); ZNetView val = component?.m_nview ?? ((Component)__instance).GetComponent<ZNetView>(); int num = 1; if ((Object)(object)val != (Object)null && val.IsValid()) { num = val.GetZDO().GetInt("tw_level", 1); } string arg = (__instance.IsEnabled() ? "<color=green>활성화</color>" : "<color=red>비활성화</color>"); 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("<size=22><b>[ 영토 와드 <color={0}>Lv{1}</color>({2}) ]</b></size>", "#00FFFF", num, arg)); if ((Object)(object)component != (Object)null) { stringBuilder.Append("\n<color=yellow>연료</color> : " + component.GetFuelInfoText()); } stringBuilder.Append(string.Format("\n<color={0}>범위</color> : {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<color=yellow>소유자</color> : <color=green>" + text2 + "</color>"); stringBuilder.Append("\n<color=yellow>허용됨</color> : <color=#4FC3F7>" + permittedNamesString + "</color>"); stringBuilder.Append("\n"); if (flag || flag2) { stringBuilder.Append("\n[<color=yellow><b>" + text + "</b></color>] 와드 활성화 / 비활성화"); if (flag2 && !flag) { stringBuilder.Append("\n[<color=yellow><b>Shift+" + text + "</b></color>] 멤버 탈퇴"); } } else { stringBuilder.Append("\n[<color=yellow><b>" + text + "</b></color>] 멤버 가입"); stringBuilder.Append("\n[<color=yellow><b>Shift+" + text + "</b></color>] 멤버 탈퇴"); } stringBuilder.Append(string.Format("\n[<color={0}><b>{1}</b></color>] $territoryward_fuel_hint", "yellow", TerritoryConfig.FuelStorageKey.Value)); stringBuilder.Append("\n"); stringBuilder.Append(string.Format("\n[<color={0}><b>{1}</b></color>] $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(" <color={0}>Lv{1}</color>→<color={2}><b>Lv{3}</b></color>", "#00FFFF", num, "#00FFFF", num + 1)); stringBuilder.Append("\n<color=yellow>재료</color> : " + component.GetUpgradeRequirementText()); if (nextLevelRadius.HasValue) { stringBuilder.Append(string.Format("\n<color={0}>범위</color> : {1:0}m", "yellow", nextLevelRadius.Value)); } stringBuilder.Append("\n<color=yellow>연료</color> : " + component.GetNextLevelFuelInfoText()); string nextLevelFullFuelText = component.GetNextLevelFullFuelText(); if (!string.IsNullOrEmpty(nextLevelFullFuelText)) { stringBuilder.Append(string.Format("\n<color={0}>Lv1/Lv{1} 연료</color> :", "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<color=#00FFFF>[" + text3 + "]</color>"); if (flag) { stringBuilder.Append(string.Format("\n[<color={0}><b>{1}</b></color>] $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[<color={0}><b>{1}</b></color>] {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[<color={0}><b>{1}</b></color>] $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<string> list = new List<string>(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<string> list2 = new List<string>(); 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<RectTransform>(); 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<RectTransform>(); 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<GameObject>(originalComp.gameObject, ((Transform)originalRt).parent); ((Object)val).name = "TerritoryWard_HoverTextRightColumn"; s_rightColumn = val.GetComponent<TextMeshProUGUI>(); } 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<Image>()).color = new Color(1f, 1f, 1f, 0.4f); s_dividerRect = val2.GetComponent<RectTransform>(); 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<TerritoryWardController>()?.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<string, string> { ["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<string, string> { ["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<string, string> { ["territoryward_desc"] = $"반경 {value:0}미터의 영토를 설정합니다.\n" + "ON 상태에서만 구역 안에서 건설하고 상호작용할 수 있습니다.\n" + $"연료: {text} {value2}개 + {text2} {value3}개 / {value4:0}분마다" }); text3 = "English"; localization.AddTranslation(ref text3, new Dictionary<string, string> { ["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<TerritoryWardController>(); 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<TerritoryWardController>(); 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<TerritoryWardController>(); 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<PrivateArea> s_wards = new List<PrivateArea>(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<PrivateArea>(); if ((Object)(object)component != (Object)null) { component.m_name = "$territoryward_name"; } Container val3 = val2.PiecePrefab.AddComponent<Container>(); 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<TerritoryWardController>(); PieceManager.Instance.AddPiece(val2); PrefabManager.OnVanillaPrefabsAvailable -= Create; s_piece = val2.PiecePrefab.GetComponent<Piece>(); 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<ResolvedTier> m_tiers = new List<ResolvedTier>(); 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<string, float> m_intruders = new Dictionary<string, float>(); 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<KeyValuePair<long, string>> m_uiPermitted = new List<KeyValuePair<long, string>>(); 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<ZNetView>(); m_container = ((Component)this).GetComponent<Container>(); m_privateArea = ((Component)this).GetComponent<PrivateArea>(); m_piece = ((Component)this).GetComponent<Piece>(); if ((Object)(object)m_nview != (Object)null) { m_nview.Register<int>("RPC_ApplyLevel", (Action<long, int>)RPC_ApplyLevel); m_nview.Register<string>("RPC_ReportIntrusion", (Action<long, string>)RPC_ReportIntrusion); m_nview.Register<float>("RPC_ActivateShield", (Action<long, float>)RPC_ActivateShield); m_nview.Register("RPC_DeactivateShield", (Action<long>)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} <color=green>[{arg}]</color>"; 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<ShieldGenerator>(); 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<string> list = new List<string>(); 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<TerritoryConfig.FuelTier> 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<TerritoryConfig.FuelTier> fuelTiers = TerritoryConfig.GetFuelTiers(uptoLevel); if (fuelTiers.Count == 0) { return ""; } string text = Localization.instance.Localize("$territoryward_fuel_or"); List<string> list = new List<string>(); 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<string> list = new List<string>(); 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<ShieldGenerator>() : 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<ShieldDomeImageEffect>(); } 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<GameObject>(val2.m_shieldDome); val3.transform.SetParent(m_shieldGenObject.transform); val3.transform.localPosition = Vector3.zero; val3.SetActive(true); ShieldGenerator val4 = m_shieldGenObject.AddComponent<ShieldGenerator>(); 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<object>()); ((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<ItemDrop>()?.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_nvi