Decompiled source of Zombie Survival World v1.2.3
BepInEx/plugins/Zombie_Survival_World/Zombie_Survival_World.dll
Decompiled 2 weeks 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.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using AK_Gun; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Photon.Pun; using Photon.Realtime; using UnityEngine; using UnityEngine.Networking; using UnityEngine.SceneManagement; using Zorro.Core; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("좀비서바이벌")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("좀비서바이벌")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("36367a36-a880-4ba0-9250-87e7bd78aa73")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace ZombieNoBones { [BepInPlugin("com.Sapphire009.zombienobones", "Zombie No Bones", "1.1.0")] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Log; private Harmony _harmony; internal const float DeadCleanupDelaySeconds = 3f; internal static FieldInfo TimeDiedAtField; private void Awake() { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; TimeDiedAtField = AccessTools.Field(typeof(MushroomZombie), "timeDiedAt"); if (TimeDiedAtField == null) { Log.LogWarning((object)"Could not find MushroomZombie.timeDiedAt field."); } _harmony = new Harmony("com.Sapphire009.zombienobones"); _harmony.PatchAll(); Log.LogInfo((object)$"Zombie No Bones loaded. Dead cleanup delay = {3f}s"); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } [HarmonyPatch(typeof(MushroomZombie), "ReadyToDisable")] internal static class Patch_MushroomZombie_ReadyToDisable { [HarmonyPrefix] private static bool Prefix(MushroomZombie __instance, ref bool __result) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Invalid comparison between Unknown and I4 if ((Object)(object)__instance == (Object)null) { __result = false; return false; } try { if ((int)__instance.currentState == 6) { if (Plugin.TimeDiedAtField == null) { __result = false; return false; } object value = Plugin.TimeDiedAtField.GetValue(__instance); float num = 0f; if (value is float num2) { num = num2; } __result = num + 3f < Time.time; return false; } return true; } catch (Exception arg) { Plugin.Log.LogError((object)$"[Patch_MushroomZombie_ReadyToDisable] {arg}"); return true; } } } [HarmonyPatch(typeof(MushroomZombie), "DestroyZombie")] internal static class Patch_MushroomZombie_DestroyZombie { [HarmonyPrefix] private static bool Prefix(MushroomZombie __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PhotonNetwork.IsMasterClient) { return false; } try { if ((Object)(object)ZombieManager.Instance != (Object)null) { ZombieManager.Instance.DeRegisterZombie(__instance); } if ((Object)(object)__instance.spawner != (Object)null) { __instance.spawner.spawnedZombie = null; Object.Destroy((Object)(object)((Component)__instance.spawner).gameObject); } PhotonView component = ((Component)__instance).GetComponent<PhotonView>(); if ((Object)(object)component != (Object)null) { PhotonNetwork.Destroy(((Component)__instance).gameObject); } else { Object.Destroy((Object)(object)((Component)__instance).gameObject); } Plugin.Log.LogInfo((object)"Destroyed zombie without original DestroyZombie flow."); } catch (Exception arg) { Plugin.Log.LogError((object)$"[Patch_MushroomZombie_DestroyZombie] {arg}"); } return false; } } } namespace ZombieBase { [BepInPlugin("com.Sapphire009.peakzombieruntimeoverride", "좀비 기본 스텟", "1.1.1")] public class Plugin : BaseUnityPlugin, IInRoomCallbacks { internal static ManualLogSource Log; private static Type _peakType; private static FieldInfo _instanceField; private static FieldInfo _reachForceField; private static FieldInfo _distanceBeforeWakeupField; private static FieldInfo _lookAngleBeforeWakeupField; private static FieldInfo _initialWakeUpTimeField; private static FieldInfo _distanceBeforeChaseField; private static FieldInfo _zombieSprintDistanceField; private static FieldInfo _chaseTimeBeforeSprintField; private static FieldInfo _zombieLungeDistanceField; private static FieldInfo _lungeTimeField; private static FieldInfo _lungeRecoveryTimeField; private static FieldInfo _biteStunTimeField; private static FieldInfo _biteInitialInjuryField; private static FieldInfo _biteInitialSporesField; private static FieldInfo _biteDelayBeforeSporesField; private static FieldInfo _biteSporesPerSecondField; private static FieldInfo _totalBiteSporesTimeField; private static FieldInfo _distanceToEnableField; private static FieldInfo _zombieGruntWaitMinField; private static FieldInfo _zombieGruntWaitMaxField; private static FieldInfo _mushroomGrowTimeMinField; private static FieldInfo _mushroomGrowTimeMaxField; private static FieldInfo _attackHeightDeltaField; private float _nextApplyTime; private float _nextPublishTime; private static ZombieStatSet _activeStats; private static ZombieStatSet _hostStats; private static ConfigEntry<float> _넉백; private static ConfigEntry<float> _일어나는거리; private static ConfigEntry<float> _일어나는반경; private static ConfigEntry<float> _좀비리스폰후일어나는시간; private static ConfigEntry<float> _추격전거리; private static ConfigEntry<float> _nM내에서달리기; private static ConfigEntry<float> _일어나고n초후물기; private static ConfigEntry<float> _점프최소거리; private static ConfigEntry<float> _점프시간; private static ConfigEntry<float> _점프후회복시간; private static ConfigEntry<float> _플레이어스턴시간; private static ConfigEntry<float> _BiteInitialInjury; private static ConfigEntry<float> _BiteInitialSpores; private static ConfigEntry<float> _BiteDelayBeforeSpores; private static ConfigEntry<float> _BiteSporesPerSecond; private static ConfigEntry<float> _TotalBiteSporesTime; private static ConfigEntry<float> _DistanceToEnable; private static ConfigEntry<float> _좀비하울링소리최소; private static ConfigEntry<float> _좀비하울링소리최대; private static ConfigEntry<float> _MushroomGrowTimeMin; private static ConfigEntry<float> _MushroomGrowTimeMax; private static ConfigEntry<float> _공격높이; private const string ROOM_KEY_VERSION = "szw_stats_version"; private const string ROOM_KEY_REACH_FORCE = "szw_reachForce"; private const string ROOM_KEY_DISTANCE_BEFORE_WAKEUP = "szw_distWake"; private const string ROOM_KEY_LOOK_ANGLE_BEFORE_WAKEUP = "szw_lookWake"; private const string ROOM_KEY_INITIAL_WAKEUP_TIME = "szw_initWake"; private const string ROOM_KEY_DISTANCE_BEFORE_CHASE = "szw_distChase"; private const string ROOM_KEY_ZOMBIE_SPRINT_DISTANCE = "szw_sprintDist"; private const string ROOM_KEY_CHASE_TIME_BEFORE_SPRINT = "szw_chaseSprint"; private const string ROOM_KEY_ZOMBIE_LUNGE_DISTANCE = "szw_lungeDist"; private const string ROOM_KEY_LUNGE_TIME = "szw_lungeTime"; private const string ROOM_KEY_LUNGE_RECOVERY_TIME = "szw_lungeRecover"; private const string ROOM_KEY_BITE_STUN_TIME = "szw_biteStun"; private const string ROOM_KEY_BITE_INITIAL_INJURY = "szw_biteInjury"; private const string ROOM_KEY_BITE_INITIAL_SPORES = "szw_biteSpores0"; private const string ROOM_KEY_BITE_DELAY_BEFORE_SPORES = "szw_biteDelay"; private const string ROOM_KEY_BITE_SPORES_PER_SECOND = "szw_bitePerSec"; private const string ROOM_KEY_TOTAL_BITE_SPORES_TIME = "szw_biteTotal"; private const string ROOM_KEY_DISTANCE_TO_ENABLE = "szw_distEnable"; private const string ROOM_KEY_ZOMBIE_GRUNT_WAIT_MIN = "szw_gruntMin"; private const string ROOM_KEY_ZOMBIE_GRUNT_WAIT_MAX = "szw_gruntMax"; private const string ROOM_KEY_MUSHROOM_GROW_TIME_MIN = "szw_growMin"; private const string ROOM_KEY_MUSHROOM_GROW_TIME_MAX = "szw_growMax"; private const string ROOM_KEY_ATTACK_HEIGHT_DELTA = "szw_attackHeight"; private void Awake() { Log = ((BaseUnityPlugin)this).Logger; ((BaseUnityPlugin)this).Config.SaveOnConfigSet = true; BindConfigs(); _hostStats = CreateStatsFromConfig(); _activeStats = _hostStats; CacheReflection(); SceneManager.sceneLoaded += OnSceneLoaded; PhotonNetwork.AddCallbackTarget((object)this); if (PhotonNetwork.InRoom) { if (PhotonNetwork.IsMasterClient) { PublishHostStatsToRoom(force: true); } else { TryPullStatsFromRoom(); } } ApplyAll(forceLog: true); Log.LogInfo((object)"좀비 기본 스텟 loaded."); } private void OnDestroy() { SceneManager.sceneLoaded -= OnSceneLoaded; PhotonNetwork.RemoveCallbackTarget((object)this); } private void Update() { if (PhotonNetwork.InRoom) { if (PhotonNetwork.IsMasterClient) { _hostStats = CreateStatsFromConfig(); _activeStats = _hostStats; if (Time.time >= _nextPublishTime) { _nextPublishTime = Time.time + 2f; PublishHostStatsToRoom(force: false); } } else { TryPullStatsFromRoom(); } } else { _hostStats = CreateStatsFromConfig(); _activeStats = _hostStats; } if (!(Time.time < _nextApplyTime)) { _nextApplyTime = Time.time + 1f; ApplyAll(forceLog: false); } } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { if (PhotonNetwork.InRoom) { if (PhotonNetwork.IsMasterClient) { _hostStats = CreateStatsFromConfig(); PublishHostStatsToRoom(force: true); } else { TryPullStatsFromRoom(); } } ApplyAll(forceLog: true); } private void BindConfigs() { _넉백 = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 기본 스텟", "넉백", -1f, "ReachForce"); _일어나는거리 = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 기본 스텟", "일어나는 거리", 50f, "DistanceBeforeWakeup"); _일어나는반경 = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 기본 스텟", "일어나는 반경", 360f, "LookAngleBeforeWakeup"); _좀비리스폰후일어나는시간 = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 기본 스텟", "좀비 리스폰 후 일어나는 시간", 0f, "InitialWakeUpTime"); _추격전거리 = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 기본 스텟", "추격 전 거리", 0f, "DistanceBeforeChase"); _nM내에서달리기 = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 기본 스텟", "nM내에서 달리기", 300000f, "ZombieSprintDistance"); _일어나고n초후물기 = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 기본 스텟", "일어나고 n초 후 물기", 0f, "ChaseTimeBeforeSprint"); _점프최소거리 = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 기본 스텟", "점프 최소거리", 3f, "ZombieLungeDistance"); _점프시간 = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 기본 스텟", "점프 시간", 1.5f, "LungeTime"); _점프후회복시간 = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 기본 스텟", "점프 후 회복시간", 1f, "LungeRecoveryTime"); _플레이어스턴시간 = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 기본 스텟", "플레이어 스턴시간", 2f, "BiteStunTime"); _BiteInitialInjury = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 기본 스텟", "BiteInitialInjury", 0.1f, "BiteInitialInjury"); _BiteInitialSpores = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 기본 스텟", "BiteInitialSpores", 0.1f, "BiteInitialSpores"); _BiteDelayBeforeSpores = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 기본 스텟", "BiteDelayBeforeSpores", -1f, "BiteDelayBeforeSpores"); _BiteSporesPerSecond = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 기본 스텟", "BiteSporesPerSecond", -1f, "BiteSporesPerSecond"); _TotalBiteSporesTime = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 기본 스텟", "TotalBiteSporesTime", -1f, "TotalBiteSporesTime"); _DistanceToEnable = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 기본 스텟", "DistanceToEnable", -1f, "DistanceToEnable"); _좀비하울링소리최소 = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 기본 스텟", "좀비 하울링 소리 최소", 10f, "ZombieGruntWaitMin"); _좀비하울링소리최대 = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 기본 스텟", "좀비 하울링 소리 최대", 20f, "ZombieGruntWaitMax"); _MushroomGrowTimeMin = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 기본 스텟", "MushroomGrowTimeMin", -1f, "MushroomGrowTimeMin"); _MushroomGrowTimeMax = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 기본 스텟", "MushroomGrowTimeMax", -1f, "MushroomGrowTimeMax"); _공격높이 = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 기본 스텟", "공격 높이", 5f, "AttackHeightDelta"); } private static ZombieStatSet CreateStatsFromConfig() { ZombieStatSet result = default(ZombieStatSet); result.ReachForce = ((_넉백 != null) ? _넉백.Value : (-1f)); result.DistanceBeforeWakeup = ((_일어나는거리 != null) ? _일어나는거리.Value : 50f); result.LookAngleBeforeWakeup = ((_일어나는반경 != null) ? _일어나는반경.Value : 360f); result.InitialWakeUpTime = ((_좀비리스폰후일어나는시간 != null) ? _좀비리스폰후일어나는시간.Value : 0f); result.DistanceBeforeChase = ((_추격전거리 != null) ? _추격전거리.Value : 0f); result.ZombieSprintDistance = ((_nM내에서달리기 != null) ? _nM내에서달리기.Value : 300000f); result.ChaseTimeBeforeSprint = ((_일어나고n초후물기 != null) ? _일어나고n초후물기.Value : 0f); result.ZombieLungeDistance = ((_점프최소거리 != null) ? _점프최소거리.Value : 3f); result.LungeTime = ((_점프시간 != null) ? _점프시간.Value : 1.5f); result.LungeRecoveryTime = ((_점프후회복시간 != null) ? _점프후회복시간.Value : 1f); result.BiteStunTime = ((_플레이어스턴시간 != null) ? _플레이어스턴시간.Value : 2f); result.BiteInitialInjury = ((_BiteInitialInjury != null) ? _BiteInitialInjury.Value : 0.1f); result.BiteInitialSpores = ((_BiteInitialSpores != null) ? _BiteInitialSpores.Value : 0.1f); result.BiteDelayBeforeSpores = ((_BiteDelayBeforeSpores != null) ? _BiteDelayBeforeSpores.Value : (-1f)); result.BiteSporesPerSecond = ((_BiteSporesPerSecond != null) ? _BiteSporesPerSecond.Value : (-1f)); result.TotalBiteSporesTime = ((_TotalBiteSporesTime != null) ? _TotalBiteSporesTime.Value : (-1f)); result.DistanceToEnable = ((_DistanceToEnable != null) ? _DistanceToEnable.Value : (-1f)); result.ZombieGruntWaitMin = ((_좀비하울링소리최소 != null) ? _좀비하울링소리최소.Value : 10f); result.ZombieGruntWaitMax = ((_좀비하울링소리최대 != null) ? _좀비하울링소리최대.Value : 20f); result.MushroomGrowTimeMin = ((_MushroomGrowTimeMin != null) ? _MushroomGrowTimeMin.Value : (-1f)); result.MushroomGrowTimeMax = ((_MushroomGrowTimeMax != null) ? _MushroomGrowTimeMax.Value : (-1f)); result.AttackHeightDelta = ((_공격높이 != null) ? _공격높이.Value : 5f); return result; } private static void CacheReflection() { _peakType = AccessTools.TypeByName("Zombies_Anywhere.ZombiesAnywhereMod"); if (_peakType == null) { Log.LogWarning((object)"Zombies_Anywhere.ZombiesAnywhereMod not found."); return; } _instanceField = AccessTools.Field(_peakType, "_instance"); _reachForceField = AccessTools.Field(_peakType, "reachForce"); _distanceBeforeWakeupField = AccessTools.Field(_peakType, "distanceBeforeWakeup"); _lookAngleBeforeWakeupField = AccessTools.Field(_peakType, "lookAngleBeforeWakeup"); _initialWakeUpTimeField = AccessTools.Field(_peakType, "initialWakeUpTime"); _distanceBeforeChaseField = AccessTools.Field(_peakType, "distanceBeforeChase"); _zombieSprintDistanceField = AccessTools.Field(_peakType, "zombieSprintDistance"); _chaseTimeBeforeSprintField = AccessTools.Field(_peakType, "chaseTimeBeforeSprint"); _zombieLungeDistanceField = AccessTools.Field(_peakType, "zombieLungeDistance"); _lungeTimeField = AccessTools.Field(_peakType, "lungeTime"); _lungeRecoveryTimeField = AccessTools.Field(_peakType, "lungeRecoveryTime"); _biteStunTimeField = AccessTools.Field(_peakType, "biteStunTime"); _biteInitialInjuryField = AccessTools.Field(_peakType, "biteInitialInjury"); _biteInitialSporesField = AccessTools.Field(_peakType, "biteInitialSpores"); _biteDelayBeforeSporesField = AccessTools.Field(_peakType, "biteDelayBeforeSpores"); _biteSporesPerSecondField = AccessTools.Field(_peakType, "biteSporesPerSecond"); _totalBiteSporesTimeField = AccessTools.Field(_peakType, "totalBiteSporesTime"); _distanceToEnableField = AccessTools.Field(_peakType, "distanceToEnable"); _zombieGruntWaitMinField = AccessTools.Field(_peakType, "zombieGruntWaitMin"); _zombieGruntWaitMaxField = AccessTools.Field(_peakType, "zombieGruntWaitMax"); _mushroomGrowTimeMinField = AccessTools.Field(_peakType, "mushroomGrowTimeMin"); _mushroomGrowTimeMaxField = AccessTools.Field(_peakType, "mushroomGrowTimeMax"); _attackHeightDeltaField = AccessTools.Field(_peakType, "attackHeightDelta"); } private static object GetPeakInstance() { try { return (_instanceField != null) ? _instanceField.GetValue(null) : null; } catch { return null; } } private static void SetFloatEntry(FieldInfo field, object instance, float value) { if (field == null || instance == null) { return; } try { if (field.GetValue(instance) is ConfigEntry<float> val) { val.Value = value; } } catch (Exception ex) { Log.LogError((object)("SetFloatEntry failed: " + ex)); } } private static void ApplyToPeakConfig(object instance, ZombieStatSet stats) { SetFloatEntry(_reachForceField, instance, stats.ReachForce); SetFloatEntry(_distanceBeforeWakeupField, instance, stats.DistanceBeforeWakeup); SetFloatEntry(_lookAngleBeforeWakeupField, instance, stats.LookAngleBeforeWakeup); SetFloatEntry(_initialWakeUpTimeField, instance, stats.InitialWakeUpTime); SetFloatEntry(_distanceBeforeChaseField, instance, stats.DistanceBeforeChase); SetFloatEntry(_zombieSprintDistanceField, instance, stats.ZombieSprintDistance); SetFloatEntry(_chaseTimeBeforeSprintField, instance, stats.ChaseTimeBeforeSprint); SetFloatEntry(_zombieLungeDistanceField, instance, stats.ZombieLungeDistance); SetFloatEntry(_lungeTimeField, instance, stats.LungeTime); SetFloatEntry(_lungeRecoveryTimeField, instance, stats.LungeRecoveryTime); SetFloatEntry(_biteStunTimeField, instance, stats.BiteStunTime); SetFloatEntry(_biteInitialInjuryField, instance, stats.BiteInitialInjury); SetFloatEntry(_biteInitialSporesField, instance, stats.BiteInitialSpores); SetFloatEntry(_biteDelayBeforeSporesField, instance, stats.BiteDelayBeforeSpores); SetFloatEntry(_biteSporesPerSecondField, instance, stats.BiteSporesPerSecond); SetFloatEntry(_totalBiteSporesTimeField, instance, stats.TotalBiteSporesTime); SetFloatEntry(_distanceToEnableField, instance, stats.DistanceToEnable); SetFloatEntry(_zombieGruntWaitMinField, instance, stats.ZombieGruntWaitMin); SetFloatEntry(_zombieGruntWaitMaxField, instance, stats.ZombieGruntWaitMax); SetFloatEntry(_mushroomGrowTimeMinField, instance, stats.MushroomGrowTimeMin); SetFloatEntry(_mushroomGrowTimeMaxField, instance, stats.MushroomGrowTimeMax); SetFloatEntry(_attackHeightDeltaField, instance, stats.AttackHeightDelta); } private static void ApplyToLiveZombie(MushroomZombie zombie, ZombieStatSet stats) { if (!((Object)(object)zombie == (Object)null)) { zombie.reachForce = stats.ReachForce; zombie.distanceBeforeWakeup = stats.DistanceBeforeWakeup; zombie.lookAngleBeforeWakeup = stats.LookAngleBeforeWakeup; zombie.initialWakeUpTime = stats.InitialWakeUpTime; zombie.distanceBeforeChase = stats.DistanceBeforeChase; zombie.zombieSprintDistance = stats.ZombieSprintDistance; zombie.chaseTimeBeforeSprint = stats.ChaseTimeBeforeSprint; zombie.zombieLungeDistance = stats.ZombieLungeDistance; zombie.lungeTime = stats.LungeTime; zombie.lungeRecoveryTime = stats.LungeRecoveryTime; zombie.biteStunTime = stats.BiteStunTime; zombie.biteInitialInjury = stats.BiteInitialInjury; zombie.biteInitialSpores = stats.BiteInitialSpores; zombie.biteDelayBeforeSpores = stats.BiteDelayBeforeSpores; zombie.biteSporesPerSecond = stats.BiteSporesPerSecond; zombie.totalBiteSporesTime = stats.TotalBiteSporesTime; if (stats.DistanceToEnable >= 0f) { zombie.distanceToEnable = stats.DistanceToEnable; } } } private static void ApplyAll(bool forceLog) { try { object peakInstance = GetPeakInstance(); if (peakInstance != null) { ApplyToPeakConfig(peakInstance, _activeStats); } MushroomZombie[] array = Object.FindObjectsByType<MushroomZombie>((FindObjectsInactive)1, (FindObjectsSortMode)0); MushroomZombie[] array2 = array; foreach (MushroomZombie zombie in array2) { ApplyToLiveZombie(zombie, _activeStats); } if (forceLog) { string text = ((!PhotonNetwork.InRoom) ? "Local(host defaults)" : (PhotonNetwork.IsMasterClient ? "Host(local+room)" : "RoomProperties")); Log.LogInfo((object)("Applied zombie stats. Source = " + text)); } } catch (Exception ex) { Log.LogError((object)("ApplyAll failed: " + ex)); } } private void PublishHostStatsToRoom(bool force) { //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_003b: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Expected O, but got Unknown //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Expected O, but got Unknown //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Expected O, but got Unknown //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Expected O, but got Unknown //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Expected O, but got Unknown //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Expected O, but got Unknown //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Expected O, but got Unknown //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Expected O, but got Unknown //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Expected O, but got Unknown //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Expected O, but got Unknown //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Expected O, but got Unknown //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Expected O, but got Unknown //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Expected O, but got Unknown //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Expected O, but got Unknown //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Expected O, but got Unknown //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Expected O, but got Unknown //IL_028f: Expected O, but got Unknown if (!PhotonNetwork.InRoom || !PhotonNetwork.IsMasterClient || PhotonNetwork.CurrentRoom == null) { return; } try { Hashtable val = new Hashtable(); ((Dictionary<object, object>)val).Add((object)"szw_stats_version", (object)1); ((Dictionary<object, object>)val).Add((object)"szw_reachForce", (object)_hostStats.ReachForce); ((Dictionary<object, object>)val).Add((object)"szw_distWake", (object)_hostStats.DistanceBeforeWakeup); ((Dictionary<object, object>)val).Add((object)"szw_lookWake", (object)_hostStats.LookAngleBeforeWakeup); ((Dictionary<object, object>)val).Add((object)"szw_initWake", (object)_hostStats.InitialWakeUpTime); ((Dictionary<object, object>)val).Add((object)"szw_distChase", (object)_hostStats.DistanceBeforeChase); ((Dictionary<object, object>)val).Add((object)"szw_sprintDist", (object)_hostStats.ZombieSprintDistance); ((Dictionary<object, object>)val).Add((object)"szw_chaseSprint", (object)_hostStats.ChaseTimeBeforeSprint); ((Dictionary<object, object>)val).Add((object)"szw_lungeDist", (object)_hostStats.ZombieLungeDistance); ((Dictionary<object, object>)val).Add((object)"szw_lungeTime", (object)_hostStats.LungeTime); ((Dictionary<object, object>)val).Add((object)"szw_lungeRecover", (object)_hostStats.LungeRecoveryTime); ((Dictionary<object, object>)val).Add((object)"szw_biteStun", (object)_hostStats.BiteStunTime); ((Dictionary<object, object>)val).Add((object)"szw_biteInjury", (object)_hostStats.BiteInitialInjury); ((Dictionary<object, object>)val).Add((object)"szw_biteSpores0", (object)_hostStats.BiteInitialSpores); ((Dictionary<object, object>)val).Add((object)"szw_biteDelay", (object)_hostStats.BiteDelayBeforeSpores); ((Dictionary<object, object>)val).Add((object)"szw_bitePerSec", (object)_hostStats.BiteSporesPerSecond); ((Dictionary<object, object>)val).Add((object)"szw_biteTotal", (object)_hostStats.TotalBiteSporesTime); ((Dictionary<object, object>)val).Add((object)"szw_distEnable", (object)_hostStats.DistanceToEnable); ((Dictionary<object, object>)val).Add((object)"szw_gruntMin", (object)_hostStats.ZombieGruntWaitMin); ((Dictionary<object, object>)val).Add((object)"szw_gruntMax", (object)_hostStats.ZombieGruntWaitMax); ((Dictionary<object, object>)val).Add((object)"szw_growMin", (object)_hostStats.MushroomGrowTimeMin); ((Dictionary<object, object>)val).Add((object)"szw_growMax", (object)_hostStats.MushroomGrowTimeMax); ((Dictionary<object, object>)val).Add((object)"szw_attackHeight", (object)_hostStats.AttackHeightDelta); Hashtable val2 = val; PhotonNetwork.CurrentRoom.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null); if (force) { Log.LogInfo((object)"Published host zombie stats to room properties."); } } catch (Exception ex) { Log.LogError((object)("PublishHostStatsToRoom failed: " + ex)); } } private void TryPullStatsFromRoom() { if (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null) { return; } Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties; if (customProperties == null || !((Dictionary<object, object>)(object)customProperties).ContainsKey((object)"szw_stats_version")) { return; } try { ZombieStatSet activeStats = default(ZombieStatSet); activeStats.ReachForce = ReadFloat(customProperties, "szw_reachForce", _hostStats.ReachForce); activeStats.DistanceBeforeWakeup = ReadFloat(customProperties, "szw_distWake", _hostStats.DistanceBeforeWakeup); activeStats.LookAngleBeforeWakeup = ReadFloat(customProperties, "szw_lookWake", _hostStats.LookAngleBeforeWakeup); activeStats.InitialWakeUpTime = ReadFloat(customProperties, "szw_initWake", _hostStats.InitialWakeUpTime); activeStats.DistanceBeforeChase = ReadFloat(customProperties, "szw_distChase", _hostStats.DistanceBeforeChase); activeStats.ZombieSprintDistance = ReadFloat(customProperties, "szw_sprintDist", _hostStats.ZombieSprintDistance); activeStats.ChaseTimeBeforeSprint = ReadFloat(customProperties, "szw_chaseSprint", _hostStats.ChaseTimeBeforeSprint); activeStats.ZombieLungeDistance = ReadFloat(customProperties, "szw_lungeDist", _hostStats.ZombieLungeDistance); activeStats.LungeTime = ReadFloat(customProperties, "szw_lungeTime", _hostStats.LungeTime); activeStats.LungeRecoveryTime = ReadFloat(customProperties, "szw_lungeRecover", _hostStats.LungeRecoveryTime); activeStats.BiteStunTime = ReadFloat(customProperties, "szw_biteStun", _hostStats.BiteStunTime); activeStats.BiteInitialInjury = ReadFloat(customProperties, "szw_biteInjury", _hostStats.BiteInitialInjury); activeStats.BiteInitialSpores = ReadFloat(customProperties, "szw_biteSpores0", _hostStats.BiteInitialSpores); activeStats.BiteDelayBeforeSpores = ReadFloat(customProperties, "szw_biteDelay", _hostStats.BiteDelayBeforeSpores); activeStats.BiteSporesPerSecond = ReadFloat(customProperties, "szw_bitePerSec", _hostStats.BiteSporesPerSecond); activeStats.TotalBiteSporesTime = ReadFloat(customProperties, "szw_biteTotal", _hostStats.TotalBiteSporesTime); activeStats.DistanceToEnable = ReadFloat(customProperties, "szw_distEnable", _hostStats.DistanceToEnable); activeStats.ZombieGruntWaitMin = ReadFloat(customProperties, "szw_gruntMin", _hostStats.ZombieGruntWaitMin); activeStats.ZombieGruntWaitMax = ReadFloat(customProperties, "szw_gruntMax", _hostStats.ZombieGruntWaitMax); activeStats.MushroomGrowTimeMin = ReadFloat(customProperties, "szw_growMin", _hostStats.MushroomGrowTimeMin); activeStats.MushroomGrowTimeMax = ReadFloat(customProperties, "szw_growMax", _hostStats.MushroomGrowTimeMax); activeStats.AttackHeightDelta = ReadFloat(customProperties, "szw_attackHeight", _hostStats.AttackHeightDelta); _activeStats = activeStats; } catch (Exception ex) { Log.LogError((object)("TryPullStatsFromRoom failed: " + ex)); } } private static float ReadFloat(Hashtable props, string key, float fallback) { if (props == null || !((Dictionary<object, object>)(object)props).ContainsKey((object)key)) { return fallback; } object obj = props[(object)key]; if (obj is float result) { return result; } if (obj is double num) { return (float)num; } if (obj is int num2) { return num2; } try { return Convert.ToSingle(obj); } catch { return fallback; } } public void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged) { if (!PhotonNetwork.IsMasterClient && propertiesThatChanged != null && ((Dictionary<object, object>)(object)propertiesThatChanged).ContainsKey((object)"szw_stats_version")) { TryPullStatsFromRoom(); ApplyAll(forceLog: true); } } public void OnPlayerEnteredRoom(Player newPlayer) { if (PhotonNetwork.IsMasterClient) { PublishHostStatsToRoom(force: true); } } public void OnPlayerLeftRoom(Player otherPlayer) { } public void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps) { } public void OnMasterClientSwitched(Player newMasterClient) { if (PhotonNetwork.LocalPlayer != null && newMasterClient != null && PhotonNetwork.LocalPlayer.ActorNumber == newMasterClient.ActorNumber) { _hostStats = CreateStatsFromConfig(); _activeStats = _hostStats; PublishHostStatsToRoom(force: true); ApplyAll(forceLog: true); } } } internal struct ZombieStatSet { public float ReachForce; public float DistanceBeforeWakeup; public float LookAngleBeforeWakeup; public float InitialWakeUpTime; public float DistanceBeforeChase; public float ZombieSprintDistance; public float ChaseTimeBeforeSprint; public float ZombieLungeDistance; public float LungeTime; public float LungeRecoveryTime; public float BiteStunTime; public float BiteInitialInjury; public float BiteInitialSpores; public float BiteDelayBeforeSpores; public float BiteSporesPerSecond; public float TotalBiteSporesTime; public float DistanceToEnable; public float ZombieGruntWaitMin; public float ZombieGruntWaitMax; public float MushroomGrowTimeMin; public float MushroomGrowTimeMax; public float AttackHeightDelta; public static ZombieStatSet CreateHostDefaults() { ZombieStatSet result = default(ZombieStatSet); result.ReachForce = -1f; result.DistanceBeforeWakeup = 50f; result.LookAngleBeforeWakeup = 360f; result.InitialWakeUpTime = 0f; result.DistanceBeforeChase = 0f; result.ZombieSprintDistance = 300000f; result.ChaseTimeBeforeSprint = 0f; result.ZombieLungeDistance = 3f; result.LungeTime = 1.5f; result.LungeRecoveryTime = 1f; result.BiteStunTime = 2f; result.BiteInitialInjury = 0.1f; result.BiteInitialSpores = 0.1f; result.BiteDelayBeforeSpores = -1f; result.BiteSporesPerSecond = -1f; result.TotalBiteSporesTime = -1f; result.DistanceToEnable = -1f; result.ZombieGruntWaitMin = 10f; result.ZombieGruntWaitMax = 20f; result.MushroomGrowTimeMin = -1f; result.MushroomGrowTimeMax = -1f; result.AttackHeightDelta = 5f; return result; } } } namespace Reload { [BepInPlugin("Reload", "장전", "4.0.0")] public class Plugin : BaseUnityPlugin, IOnEventCallback { [CompilerGenerated] private sealed class <>c__DisplayClass40_0 { public bool success; internal void <UseThenRefillRoutine>b__0(bool result) { success = result; } } [CompilerGenerated] private sealed class <LoadReloadSoundCoroutine>d__35 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Plugin <>4__this; private string <fileName>5__1; private string <pluginDir>5__2; private string <candidate>5__3; private string <url>5__4; private UnityWebRequest <req>5__5; private DownloadHandlerAudioClip <dl>5__6; private AudioClip <clip>5__7; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadReloadSoundCoroutine>d__35(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <fileName>5__1 = null; <pluginDir>5__2 = null; <candidate>5__3 = null; <url>5__4 = null; <req>5__5 = null; <dl>5__6 = null; <clip>5__7 = null; <>1__state = -2; } private bool MoveNext() { //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Invalid comparison between Unknown and I4 bool result; try { switch (<>1__state) { default: result = false; break; case 0: { <>1__state = -1; <>4__this._reloadSoundLoadTried = true; <fileName>5__1 = <>4__this.GetReloadSoundFileName(); <pluginDir>5__2 = Path.GetDirectoryName(((BaseUnityPlugin)<>4__this).Info.Location); <candidate>5__3 = Path.Combine(<pluginDir>5__2 ?? "", <fileName>5__1); <>4__this._resolvedReloadSoundPath = <candidate>5__3; if (!File.Exists(<candidate>5__3)) { <>4__this.WRN("재장전 사운드 파일을 찾지 못함: " + <candidate>5__3); result = false; break; } <url>5__4 = new Uri(<candidate>5__3).AbsoluteUri; <req>5__5 = UnityWebRequestMultimedia.GetAudioClip(<url>5__4, (AudioType)14); <>1__state = -3; ref DownloadHandlerAudioClip reference = ref <dl>5__6; DownloadHandler downloadHandler = <req>5__5.downloadHandler; reference = (DownloadHandlerAudioClip)(object)((downloadHandler is DownloadHandlerAudioClip) ? downloadHandler : null); if (<dl>5__6 != null) { <dl>5__6.streamAudio = false; } <>2__current = <req>5__5.SendWebRequest(); <>1__state = 1; result = true; break; } case 1: <>1__state = -3; if ((int)<req>5__5.result != 1) { <>4__this.ERR("장전 사운드 로드 실패: " + <req>5__5.error); result = false; } else { <clip>5__7 = DownloadHandlerAudioClip.GetContent(<req>5__5); if (!((Object)(object)<clip>5__7 == (Object)null)) { ((Object)<clip>5__7).name = "CustomReloadSound"; <>4__this._reloadSoundClip = <clip>5__7; <>4__this.DBG("장전 사운드 로드 성공: " + <candidate>5__3 + " / length=" + <clip>5__7.length); <dl>5__6 = null; <clip>5__7 = null; <>m__Finally1(); <req>5__5 = null; result = false; break; } <>4__this.ERR("장전 사운드 AudioClip 생성 실패"); result = false; } <>m__Finally1(); break; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<req>5__5 != null) { ((IDisposable)<req>5__5).Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <RefillCurrentHeldAKRoutine>d__47 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Action<bool> done; public Plugin <>4__this; private Component <heldAK>5__1; private int <totalUses>5__2; private bool <hasData>5__3; private int <usesValue>5__4; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <RefillCurrentHeldAKRoutine>d__47(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <heldAK>5__1 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>4__this.DBG("RefillCurrentHeldAKRoutine 진입"); if (!<>4__this.TryGetHeldAK(out <heldAK>5__1) || (Object)(object)<heldAK>5__1 == (Object)null) { <>4__this.ERR("현재 장착된 AK를 찾지 못함"); done(obj: false); return false; } <totalUses>5__2 = <>4__this.ReadIntMember(<heldAK>5__1, "totalUses"); if (<totalUses>5__2 <= 0) { <>4__this.ERR("AK totalUses 값을 읽지 못했거나 0 이하임"); done(obj: false); return false; } if (!<>4__this.TrySetItemUsesToMax(<heldAK>5__1, <totalUses>5__2)) { <>4__this.ERR("현재 들고 있는 AK의 ItemUses 최대치 복원 실패"); done(obj: false); return false; } <>4__this.TryRefreshUseBar(<heldAK>5__1, <totalUses>5__2); <>4__this.TrySyncItemInstanceData(<heldAK>5__1); <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; if ((<>4__this.TryReadItemUses(<heldAK>5__1, out <hasData>5__3, out <usesValue>5__4) & <hasData>5__3) && <usesValue>5__4 == <totalUses>5__2) { <>4__this.DBG("현재 들고 있는 AK 재장전 성공: " + <usesValue>5__4 + "/" + <totalUses>5__2); done(obj: true); return false; } <>4__this.ERR("재장전 후 검증 실패"); done(obj: false); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <TryMoveUseProgressUIRoutine>d__36 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Plugin <>4__this; private float <timeout>5__1; private float <elapsed>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <TryMoveUseProgressUIRoutine>d__36(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <timeout>5__1 = 10f; <elapsed>5__2 = 0f; break; case 1: <>1__state = -1; break; } if (<elapsed>5__2 < <timeout>5__1) { if (<>4__this.TryMoveUseProgressUI()) { return false; } <elapsed>5__2 += Time.unscaledDeltaTime; <>2__current = null; <>1__state = 1; return true; } <>4__this.WRN("UI_UseItemProgress를 끝내 찾지 못함"); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <UseThenRefillRoutine>d__40 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Plugin <>4__this; private Component <heldAK>5__1; private bool <prevShowUseProgress>5__2; private bool <prevOverrideForceProgress>5__3; private float <prevOverrideProgress>5__4; private float <reloadTime>5__5; private <>c__DisplayClass40_0 <>8__6; private float <elapsed>5__7; private Component <currentHeld>5__8; private float <progress>5__9; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <UseThenRefillRoutine>d__40(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 3u) { try { } finally { <>m__Finally1(); } } <heldAK>5__1 = null; <>8__6 = null; <currentHeld>5__8 = null; <>1__state = -2; } private bool MoveNext() { //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_0330: Expected O, but got Unknown //IL_0160: Unknown result type (might be due to invalid IL or missing references) bool result2; try { switch (<>1__state) { default: result2 = false; goto end_IL_0000; case 0: <>1__state = -1; <>4__this._isUsing = true; <>4__this.DBG("UseThenRefillRoutine 시작"); <heldAK>5__1 = null; <prevShowUseProgress>5__2 = true; <prevOverrideForceProgress>5__3 = false; <prevOverrideProgress>5__4 = 0f; <reloadTime>5__5 = <>4__this.GetReloadUseTime(); <>1__state = -3; <>8__6 = new <>c__DisplayClass40_0(); if (!<>4__this.TryGetHeldAK(out <heldAK>5__1) || (Object)(object)<heldAK>5__1 == (Object)null) { <>4__this.ERR("재장전 시작 시 현재 AK를 찾지 못함"); result2 = false; break; } <prevShowUseProgress>5__2 = <>4__this.ReadBoolMember(<heldAK>5__1, "showUseProgress"); <prevOverrideForceProgress>5__3 = <>4__this.ReadBoolMember(<heldAK>5__1, "overrideForceProgress"); <prevOverrideProgress>5__4 = <>4__this.ReadFloatMember(<heldAK>5__1, "overrideProgress"); <>4__this.StartNativeUseProgress(<heldAK>5__1); <>4__this.BroadcastReloadSound(<heldAK>5__1.transform.position); if (<reloadTime>5__5 > 0f) { <elapsed>5__7 = 0f; goto IL_024c; } goto IL_0264; case 1: <>1__state = -3; <currentHeld>5__8 = null; goto IL_024c; case 2: <>1__state = -3; <>8__6.success = false; <>2__current = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.RefillCurrentHeldAKRoutine(delegate(bool result) { <>8__6.success = result; })); <>1__state = 3; result2 = true; goto end_IL_0000; case 3: <>1__state = -3; if (<>8__6.success) { <>4__this.DBG("장전 성공"); } else { <>4__this.ERR("장전 실패"); } <>2__current = (object)new WaitForSecondsRealtime(0.05f); <>1__state = 4; result2 = true; goto end_IL_0000; case 4: { <>1__state = -3; <>8__6 = null; <>m__Finally1(); result2 = false; goto end_IL_0000; } IL_0264: <>4__this.UpdateNativeUseProgress(<heldAK>5__1, 1f); <>2__current = null; <>1__state = 2; result2 = true; goto end_IL_0000; IL_024c: if (!(<elapsed>5__7 < <reloadTime>5__5)) { goto IL_0264; } if (!<>4__this.TryGetHeldAK(out <currentHeld>5__8) || (Object)(object)<currentHeld>5__8 == (Object)null || (Object)(object)<currentHeld>5__8 != (Object)(object)<heldAK>5__1) { <>4__this.WRN("재장전 중 손에 든 AK가 바뀌어서 취소"); result2 = false; break; } <elapsed>5__7 += Time.unscaledDeltaTime; <progress>5__9 = Mathf.Clamp01(<elapsed>5__7 / <reloadTime>5__5); <>4__this.UpdateNativeUseProgress(<heldAK>5__1, <progress>5__9); <>2__current = null; <>1__state = 1; result2 = true; goto end_IL_0000; } <>m__Finally1(); end_IL_0000:; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result2; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if ((Object)(object)<heldAK>5__1 != (Object)null) { <>4__this.RestoreNativeUseProgress(<heldAK>5__1, <prevShowUseProgress>5__2, <prevOverrideForceProgress>5__3, <prevOverrideProgress>5__4); } <>4__this._isUsing = false; <>4__this.DBG("UseThenRefillRoutine 종료"); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } internal static Plugin Instance; private const int AK_ITEM_ID = 9351; private const byte RELOAD_SFX_EVENT_CODE = 143; private Harmony _harmony; private bool _runActionPatched; private float _lastBlockLogTime; private bool _useProgressUiMoved; private bool _isUsing; private Type _cachedCharacterType; private Type _cachedDataEntryKeyType; private Type _cachedOptionableIntItemDataType; private ConfigEntry<float> _reloadUseTime; private ConfigEntry<KeyCode> _reloadKey; private ConfigEntry<string> _reloadSoundFileName; private ConfigEntry<float> _reloadSoundVolume; private ConfigEntry<float> _reloadSoundStartOffset; private ConfigEntry<float> _reloadSoundMinDistance; private ConfigEntry<float> _reloadSoundMaxDistance; private ConfigEntry<bool> _verboseLogging; private AudioClip _reloadSoundClip; private string _resolvedReloadSoundPath; private bool _reloadSoundLoadTried; private void Awake() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown Instance = this; ((BaseUnityPlugin)this).Config.SaveOnConfigSet = true; BindConfigEntries(); DBG("Plugin Awake()"); _harmony = new Harmony("reload.akhotkey.spawninhand"); TryPatchRunAction(); SceneManager.sceneLoaded += OnSceneLoaded; PhotonNetwork.AddCallbackTarget((object)this); _useProgressUiMoved = false; ((MonoBehaviour)this).StartCoroutine(TryMoveUseProgressUIRoutine()); ((MonoBehaviour)this).StartCoroutine(LoadReloadSoundCoroutine()); } private void OnDestroy() { SceneManager.sceneLoaded -= OnSceneLoaded; PhotonNetwork.RemoveCallbackTarget((object)this); } public void OnEvent(EventData photonEvent) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) try { if (photonEvent != null && photonEvent.Code == 143 && photonEvent.CustomData is object[] array && array.Length >= 3) { float num = Convert.ToSingle(array[0]); float num2 = Convert.ToSingle(array[1]); float num3 = Convert.ToSingle(array[2]); PlayReloadSoundLocal(new Vector3(num, num2, num3)); } } catch (Exception ex) { ERR("OnEvent 예외: " + ex); } } private void BindConfigEntries() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown _reloadUseTime = ((BaseUnityPlugin)this).Config.Bind<float>("장전", "장전 시간", 3f, new ConfigDescription("AK 재장전 시간(초). 0이면 즉시 재장전.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 60f), Array.Empty<object>())); _reloadKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("장전", "장전 키", (KeyCode)114, "재장전 키"); _reloadSoundFileName = ((BaseUnityPlugin)this).Config.Bind<string>("장전소리", "장전 사운드 파일", "장전소리.ogg", "재장전 사운드 파일명. DLL과 같은 폴더에 둔다."); } private float GetReloadUseTime() { if (_reloadUseTime == null) { return 3f; } if (_reloadUseTime.Value < 0f) { return 0f; } return _reloadUseTime.Value; } private KeyCode GetReloadKey() { //IL_0019: 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_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (_reloadKey == null) { return (KeyCode)114; } return _reloadKey.Value; } private string GetReloadSoundFileName() { if (_reloadSoundFileName == null || string.IsNullOrWhiteSpace(_reloadSoundFileName.Value)) { return "장전소리.ogg"; } return _reloadSoundFileName.Value.Trim(); } private float GetReloadSoundVolume() { if (_reloadSoundVolume == null) { return 1f; } return Mathf.Clamp(_reloadSoundVolume.Value, 0f, 30f); } private float GetReloadSoundStartOffset() { if (_reloadSoundStartOffset == null) { return 0f; } return Mathf.Max(0f, _reloadSoundStartOffset.Value); } private float GetReloadSoundMinDistance() { if (_reloadSoundMinDistance == null) { return 3f; } return Mathf.Max(0f, _reloadSoundMinDistance.Value); } private float GetReloadSoundMaxDistance() { if (_reloadSoundMaxDistance == null) { return 25f; } return Mathf.Max(1f, _reloadSoundMaxDistance.Value); } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { DBG("Scene loaded: " + ((Scene)(ref scene)).name); _useProgressUiMoved = false; ((MonoBehaviour)this).StartCoroutine(TryMoveUseProgressUIRoutine()); if ((Object)(object)_reloadSoundClip == (Object)null && !_reloadSoundLoadTried) { ((MonoBehaviour)this).StartCoroutine(LoadReloadSoundCoroutine()); } } private void Update() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) if (!_runActionPatched) { TryPatchRunAction(); } if (Input.GetKeyDown(GetReloadKey()) && !_isUsing) { if (!TryGetHeldAK(out var _)) { WRN("현재 손에 든 AK가 없어서 재장전을 시작하지 않음"); return; } KeyCode reloadKey = GetReloadKey(); DBG("HOTKEY 입력 감지: " + ((object)(KeyCode)(ref reloadKey)).ToString() + " / ReloadTime = " + GetReloadUseTime()); ((MonoBehaviour)this).StartCoroutine(UseThenRefillRoutine()); } } [IteratorStateMachine(typeof(<LoadReloadSoundCoroutine>d__35))] private IEnumerator LoadReloadSoundCoroutine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LoadReloadSoundCoroutine>d__35(0) { <>4__this = this }; } [IteratorStateMachine(typeof(<TryMoveUseProgressUIRoutine>d__36))] private IEnumerator TryMoveUseProgressUIRoutine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <TryMoveUseProgressUIRoutine>d__36(0) { <>4__this = this }; } private bool TryMoveUseProgressUI() { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) if (_useProgressUiMoved) { return true; } Type type = FindTypeByName("UI_UseItemProgress"); if (type == null) { return false; } Object[] array = Resources.FindObjectsOfTypeAll(type); if (array == null || array.Length == 0) { return false; } Object[] array2 = array; foreach (Object val in array2) { Component val2 = (Component)(object)((val is Component) ? val : null); if ((Object)(object)val2 == (Object)null || (Object)(object)val2.gameObject == (Object)null) { continue; } Scene scene = val2.gameObject.scene; if (((Scene)(ref scene)).IsValid()) { RectTransform component = val2.GetComponent<RectTransform>(); if (!((Object)(object)component == (Object)null)) { component.anchoredPosition += new Vector2(180f, 0f); _useProgressUiMoved = true; Vector2 anchoredPosition = component.anchoredPosition; DBG("UI_UseItemProgress 위치 이동 완료: " + ((object)(Vector2)(ref anchoredPosition)).ToString()); return true; } } } return false; } private void TryPatchRunAction() { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown if (_runActionPatched) { return; } try { Type type = FindTypeByFullName("AK_Gun.Action_Gun"); if (type == null) { WRN("AK_Gun.Action_Gun 타입을 아직 찾지 못함"); return; } MethodInfo method = type.GetMethod("RunAction", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) { ERR("AK_Gun.Action_Gun.RunAction 메서드를 찾지 못함"); return; } MethodInfo method2 = typeof(Plugin).GetMethod("Prefix_BlockRunActionWhileReloading", BindingFlags.Static | BindingFlags.NonPublic); if (method2 == null) { ERR("Prefix_BlockRunActionWhileReloading 메서드를 찾지 못함"); return; } _harmony.Patch((MethodBase)method, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _runActionPatched = true; DBG("Harmony Patch 성공: AK_Gun.Action_Gun.RunAction"); } catch (Exception ex) { ERR("TryPatchRunAction 예외: " + ex); } } private static bool Prefix_BlockRunActionWhileReloading() { try { if ((Object)(object)Instance == (Object)null) { return true; } if (!Instance._isUsing) { return true; } if (Time.unscaledTime - Instance._lastBlockLogTime >= 0.25f) { Instance._lastBlockLogTime = Time.unscaledTime; ((BaseUnityPlugin)Instance).Logger.LogInfo((object)"[AKReloadDBG] 재장전 중 발사 차단: RunAction 스킵"); } return false; } catch { return true; } } [IteratorStateMachine(typeof(<UseThenRefillRoutine>d__40))] private IEnumerator UseThenRefillRoutine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <UseThenRefillRoutine>d__40(0) { <>4__this = this }; } private void StartNativeUseProgress(Component itemComponent) { try { WriteMemberValue(itemComponent, "showUseProgress", true); WriteMemberValue(itemComponent, "overrideForceProgress", true); WriteMemberValue(itemComponent, "overrideProgress", 0f); DBG("UI-only reload progress 시작"); } catch (Exception ex) { WRN("StartNativeUseProgress 예외: " + ex.Message); } } private void UpdateNativeUseProgress(Component itemComponent, float progress) { try { float num = Mathf.Clamp01(progress); WriteMemberValue(itemComponent, "showUseProgress", true); WriteMemberValue(itemComponent, "overrideForceProgress", true); WriteMemberValue(itemComponent, "overrideProgress", num); TryRefreshUseBar(itemComponent, ReadCurrentUsesSafe(itemComponent)); } catch (Exception ex) { WRN("UpdateNativeUseProgress 예외: " + ex.Message); } } private void RestoreNativeUseProgress(Component itemComponent, bool prevShowUseProgress, bool prevOverrideForceProgress, float prevOverrideProgress) { try { WriteMemberValue(itemComponent, "showUseProgress", prevShowUseProgress); WriteMemberValue(itemComponent, "overrideForceProgress", prevOverrideForceProgress); WriteMemberValue(itemComponent, "overrideProgress", prevOverrideProgress); DBG("UI-only reload progress 상태 복원"); } catch (Exception ex) { WRN("RestoreNativeUseProgress 예외: " + ex.Message); } } private void BroadcastReloadSound(Vector3 position) { //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_0083: 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) try { if ((Object)(object)_reloadSoundClip == (Object)null) { WRN("장전 사운드가 아직 로드되지 않아 재생하지 못함"); return; } if (!PhotonNetwork.InRoom) { PlayReloadSoundLocal(position); return; } object[] array = new object[3] { position.x, position.y, position.z }; RaiseEventOptions val = new RaiseEventOptions { Receivers = (ReceiverGroup)1 }; PhotonNetwork.RaiseEvent((byte)143, (object)array, val, SendOptions.SendReliable); } catch (Exception ex) { WRN("BroadcastReloadSound 예외: " + ex.Message); try { PlayReloadSoundLocal(position); } catch { } } } private void PlayReloadSoundLocal(Vector3 position) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0106: 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) try { if ((Object)(object)_reloadSoundClip == (Object)null) { WRN("재장전 사운드 클립이 null임"); return; } float reloadSoundStartOffset = GetReloadSoundStartOffset(); float num = Mathf.Max(0.01f, _reloadSoundClip.length - reloadSoundStartOffset); GameObject val = new GameObject("AKReloadCustomSFX"); val.transform.position = position; AudioSource val2 = val.AddComponent<AudioSource>(); val2.playOnAwake = false; val2.loop = false; val2.spatialBlend = 1f; val2.rolloffMode = (AudioRolloffMode)1; val2.minDistance = GetReloadSoundMinDistance(); val2.maxDistance = GetReloadSoundMaxDistance(); val2.volume = GetReloadSoundVolume(); val2.clip = _reloadSoundClip; if (reloadSoundStartOffset > 0f && reloadSoundStartOffset < _reloadSoundClip.length - 0.01f) { val2.time = reloadSoundStartOffset; } val2.Play(); Object.Destroy((Object)(object)val, num + 0.5f); Vector3 val3 = position; DBG("커스텀 장전 사운드 재생 / pos=" + ((object)(Vector3)(ref val3)).ToString() + " / offset=" + reloadSoundStartOffset); } catch (Exception ex) { WRN("PlayReloadSoundLocal 예외: " + ex.Message); } } private int ReadCurrentUsesSafe(Component itemComponent) { try { if (TryReadItemUses(itemComponent, out var hasData, out var value) && hasData) { return value; } } catch { } return 0; } [IteratorStateMachine(typeof(<RefillCurrentHeldAKRoutine>d__47))] private IEnumerator RefillCurrentHeldAKRoutine(Action<bool> done) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <RefillCurrentHeldAKRoutine>d__47(0) { <>4__this = this, done = done }; } private bool TryGetHeldAK(out Component heldAK) { heldAK = null; try { if (!TryGetLocalCharacter(out var localCharacter) || localCharacter == null) { return false; } heldAK = GetCurrentItemComponentFromCharacter(localCharacter); if ((Object)(object)heldAK == (Object)null) { return false; } return IsAKItem(heldAK); } catch (Exception ex) { WRN("TryGetHeldAK 예외: " + ex.Message); heldAK = null; return false; } } private Type GetCharacterType() { if (_cachedCharacterType != null) { return _cachedCharacterType; } Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { Type[] array; try { array = assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { array = ex.Types.Where((Type t) => t != null).ToArray(); } catch { continue; } Type[] array2 = array; foreach (Type type in array2) { if (type == null || type.Name != "Character") { continue; } string text = type.Namespace ?? ""; if (!text.StartsWith("UnityEngine.TextCore.Text", StringComparison.OrdinalIgnoreCase)) { BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; if (type.GetField("localCharacter", bindingAttr) != null || type.GetProperty("localCharacter", bindingAttr) != null || type.GetField("LocalCharacter", bindingAttr) != null || type.GetProperty("LocalCharacter", bindingAttr) != null) { _cachedCharacterType = type; DBG("게임 Character 타입 확정 = " + (_cachedCharacterType.FullName ?? _cachedCharacterType.Name)); return _cachedCharacterType; } } } } WRN("게임 Character 타입을 찾지 못함"); return null; } private Type GetDataEntryKeyType() { if (_cachedDataEntryKeyType != null) { return _cachedDataEntryKeyType; } _cachedDataEntryKeyType = FindTypeByName("DataEntryKey"); if (_cachedDataEntryKeyType == null) { WRN("DataEntryKey 타입을 찾지 못함"); } return _cachedDataEntryKeyType; } private Type GetOptionableIntItemDataType() { if (_cachedOptionableIntItemDataType != null) { return _cachedOptionableIntItemDataType; } _cachedOptionableIntItemDataType = FindTypeByName("OptionableIntItemData"); if (_cachedOptionableIntItemDataType == null) { WRN("OptionableIntItemData 타입을 찾지 못함"); } return _cachedOptionableIntItemDataType; } private Type FindTypeByName(string typeName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { Type[] array; try { array = assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { array = ex.Types.Where((Type t) => t != null).ToArray(); } catch { continue; } Type[] array2 = array; foreach (Type type in array2) { if (type != null && type.Name == typeName) { return type; } } } return null; } private Type FindTypeByFullName(string fullName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { Type[] array; try { array = assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { array = ex.Types.Where((Type t) => t != null).ToArray(); } catch { continue; } Type[] array2 = array; foreach (Type type in array2) { if (!(type == null) && string.Equals(type.FullName, fullName, StringComparison.Ordinal)) { return type; } } } return null; } private bool TryGetLocalCharacter(out object localCharacter) { localCharacter = null; try { Type characterType = GetCharacterType(); if (characterType == null) { return false; } BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo field = characterType.GetField("localCharacter", bindingAttr); if (field != null) { localCharacter = field.GetValue(null); if (localCharacter != null) { DBG("localCharacter 필드로 찾음"); return true; } } PropertyInfo property = characterType.GetProperty("localCharacter", bindingAttr); if (property != null) { localCharacter = property.GetValue(null, null); if (localCharacter != null) { DBG("localCharacter 프로퍼티로 찾음"); return true; } } field = characterType.GetField("LocalCharacter", bindingAttr); if (field != null) { localCharacter = field.GetValue(null); if (localCharacter != null) { DBG("LocalCharacter 필드로 찾음"); return true; } } property = characterType.GetProperty("LocalCharacter", bindingAttr); if (property != null) { localCharacter = property.GetValue(null, null); if (localCharacter != null) { DBG("LocalCharacter 프로퍼티로 찾음"); return true; } } } catch (Exception ex) { WRN("TryGetLocalCharacter 예외: " + ex.Message); } return false; } private Component GetCurrentItemComponentFromCharacter(object characterObj) { try { if (characterObj == null) { return null; } object memberValue = GetMemberValue(characterObj, "data"); if (memberValue == null) { return null; } object memberValue2 = GetMemberValue(memberValue, "currentItem"); return (Component)((memberValue2 is Component) ? memberValue2 : null); } catch (Exception ex) { WRN("GetCurrentItemComponentFromCharacter 예외: " + ex.Message); return null; } } private bool IsAKItem(Component itemComponent) { if ((Object)(object)itemComponent == (Object)null) { return false; } try { object memberValue = GetMemberValue(itemComponent, "itemID"); if (memberValue != null) { int num = Convert.ToInt32(memberValue); if (num == 9351) { return true; } } } catch { } string text = ((Object)itemComponent).name ?? ""; if (text.IndexOf("AK", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } if (text.IndexOf("com.github.TheCodinPro.AK_Gun", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } return false; } private bool TryReadItemUses(Component itemComponent, out bool hasData, out int value) { hasData = false; value = 0; try { Type type = ((object)itemComponent).GetType(); Type keyType = GetDataEntryKeyType(); Type optionableIntItemDataType = GetOptionableIntItemDataType(); if (type == null || keyType == null || optionableIntItemDataType == null) { return false; } object obj = Enum.Parse(keyType, "ItemUses"); MethodInfo methodInfo = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name == "GetData" && m.IsGenericMethodDefinition && m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == keyType); if (methodInfo == null) { WRN("GetData<T>(DataEntryKey) 메서드를 찾지 못함"); return false; } MethodInfo methodInfo2 = methodInfo.MakeGenericMethod(optionableIntItemDataType); object obj2 = methodInfo2.Invoke(itemComponent, new object[1] { obj }); if (obj2 == null) { return false; } hasData = ReadBoolMember(obj2, "HasData"); value = ReadIntMember(obj2, "Value"); return true; } catch (Exception ex) { WRN("TryReadItemUses 예외: " + ex.Message); return false; } } private bool TrySetItemUsesToMax(Component itemComponent, int totalUses) { try { Type keyType = GetDataEntryKeyType(); Type optionableIntItemDataType = GetOptionableIntItemDataType(); if (keyType == null || optionableIntItemDataType == null) { return false; } object obj = Enum.Parse(keyType, "ItemUses"); object obj2 = null; MethodInfo methodInfo = ((object)itemComponent).GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name == "GetData" && m.IsGenericMethodDefinition && m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == keyType); if (methodInfo != null) { MethodInfo methodInfo2 = methodInfo.MakeGenericMethod(optionableIntItemDataType); obj2 = methodInfo2.Invoke(itemComponent, new object[1] { obj }); } if (obj2 == null) { try { obj2 = Activator.CreateInstance(optionableIntItemDataType); } catch (Exception ex) { ERR("OptionableIntItemData 인스턴스 생성 실패: " + ex.Message); return false; } } WriteMemberValue(obj2, "HasData", true); WriteMemberValue(obj2, "Value", totalUses); bool flag = false; object memberValue = GetMemberValue(itemComponent, "data"); flag |= TrySetDataEntryViaDictionary(memberValue, obj, obj2); flag |= TryInvokePossibleSetter(memberValue, keyType, obj, optionableIntItemDataType, obj2); flag |= TryInvokePossibleSetter(itemComponent, keyType, obj, optionableIntItemDataType, obj2); if (TryReadItemUses(itemComponent, out var hasData, out var value) && hasData && value == totalUses) { DBG("ItemUses 최대치 설정 성공: " + value); return true; } if (!flag) { WRN("ItemUses 엔트리 쓰기 경로를 명시적으로 찾지 못함"); } return TryReadItemUses(itemComponent, out hasData, out value) && hasData && value == totalUses; } catch (Exception ex2) { ERR("TrySetItemUsesToMax 예외: " + ex2); return false; } } private bool TrySetDataEntryViaDictionary(object itemDataObj, object key, object value) { try { if (itemDataObj == null) { return false; } object memberValue = GetMemberValue(itemDataObj, "data"); if (!(memberValue is IDictionary dictionary)) { return false; } if (dictionary.Contains(key)) { dictionary[key] = value; } else { dictionary.Add(key, value); } return true; } catch { return false; } } private bool TryInvokePossibleSetter(object target, Type keyType, object itemUsesKey, Type dataType, object entryObj) { if (target == null) { return false; } string[] array = new string[5] { "SetDataEntry", "AddDataEntry", "SetData", "AddData", "Set" }; MethodInfo[] methods = target.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); string[] array2 = array; foreach (string text in array2) { MethodInfo[] array3 = methods; foreach (MethodInfo methodInfo in array3) { if (methodInfo.Name != text) { continue; } MethodInfo methodInfo2 = methodInfo; try { if (!methodInfo.IsGenericMethodDefinition) { goto IL_00d4; } Type[] genericArguments = methodInfo.GetGenericArguments(); if (genericArguments.Length != 1) { continue; } methodInfo2 = methodInfo.MakeGenericMethod(dataType); goto IL_00d4; IL_00d4: ParameterInfo[] parameters = methodInfo2.GetParameters(); if (parameters.Length == 2) { if (parameters[0].ParameterType == keyType && parameters[1].ParameterType.IsAssignableFrom(dataType)) { methodInfo2.Invoke(target, new object[2] { itemUsesKey, entryObj }); return true; } if (parameters[1].ParameterType == keyType && parameters[0].ParameterType.IsAssignableFrom(dataType)) { methodInfo2.Invoke(target, new object[2] { entryObj, itemUsesKey }); return true; } } if (parameters.Length == 1 && parameters[0].ParameterType.IsAssignableFrom(dataType)) { methodInfo2.Invoke(target, new object[1] { entryObj }); return true; } } catch { } } } return false; } private void TryRefreshUseBar(Component itemComponent, int currentUses) { try { int num = ReadIntMember(itemComponent, "totalUses"); if (num > 0) { MethodInfo method = ((object)itemComponent).GetType().GetMethod("SetUseRemainingPercentage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(float) }, null); if (method != null) { float num2 = Mathf.Clamp01((float)currentUses / (float)num); method.Invoke(itemComponent, new object[1] { num2 }); } } } catch (Exception ex) { WRN("TryRefreshUseBar 예외: " + ex.Message); } } private bool TrySyncItemInstanceData(Component itemComponent) { try { MethodInfo method = ((object)itemComponent).GetType().GetMethod("ForceSyncForFrames", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(int) }, null); if (method != null) { method.Invoke(itemComponent, new object[1] { 10 }); } if (!PhotonNetwork.InRoom) { DBG("Photon 룸 밖 상태. 로컬 갱신만 수행"); return true; } PhotonView component = itemComponent.GetComponent<PhotonView>(); if ((Object)(object)component == (Object)null) { WRN("PhotonView를 찾지 못해 동기화 스킵"); return false; } object memberValue = GetMemberValue(itemComponent, "data"); if (memberValue == null) { WRN("item.data가 null이라 동기화 스킵"); return false; } component.RPC("SetItemInstanceDataRPC", (RpcTarget)1, new object[1] { memberValue }); DBG("현재 AK ItemInstanceData 동기화 완료"); return true; } catch (Exception ex) { WRN("TrySyncItemInstanceData 예외: " + ex.Message); return false; } } private object GetMemberValue(object target, string memberName) { if (target == null) { return null; } BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; PropertyInfo property = target.GetType().GetProperty(memberName, bindingAttr); if (property != null) { return property.GetValue(target, null); } FieldInfo field = target.GetType().GetField(memberName, bindingAttr); if (field != null) { return field.GetValue(target); } FieldInfo field2 = target.GetType().GetField("<" + memberName + ">k__BackingField", bindingAttr); if (field2 != null) { return field2.GetValue(target); } return null; } private void WriteMemberValue(object target, string memberName, object value) { if (target == null) { return; } BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; PropertyInfo property = target.GetType().GetProperty(memberName, bindingAttr); if (property != null) { MethodInfo setMethod = property.GetSetMethod(nonPublic: true); if (setMethod != null) { setMethod.Invoke(target, new object[1] { value }); return; } } FieldInfo field = target.GetType().GetField(memberName, bindingAttr); if (field != null) { field.SetValue(target, value); return; } FieldInfo field2 = target.GetType().GetField("<" + memberName + ">k__BackingField", bindingAttr); if (field2 != null) { field2.SetValue(target, value); } } private bool ReadBoolMember(object target, string memberName) { object memberValue = GetMemberValue(target, memberName); if (memberValue == null) { return false; } try { return Convert.ToBoolean(memberValue); } catch { return false; } } private int ReadIntMember(object target, string memberName) { object memberValue = GetMemberValue(target, memberName); if (memberValue == null) { return 0; } try { return Convert.ToInt32(memberValue); } catch { return 0; } } private float ReadFloatMember(object target, string memberName) { object memberValue = GetMemberValue(target, memberName); if (memberValue == null) { return 0f; } try { return Convert.ToSingle(memberValue); } catch { return 0f; } } private void DBG(string msg) { if (_verboseLogging == null || _verboseLogging.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("[AKReloadDBG] " + msg)); } } private void WRN(string msg) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[AKReloadDBG] " + msg)); } private void ERR(string msg) { ((BaseUnityPlugin)this).Logger.LogError((object)("[AKReloadDBG] " + msg)); } } } namespace AutoSpawn { [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.Sapphire009.AutoSpawn", "최대좀비수 및 타격횟수", "1.3.0")] public class Plugin : BaseUnityPlugin { [CompilerGenerated] private sealed class <HandleSegmentChangedRoutine>d__64 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Segment targetSegment; public Plugin <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <HandleSegmentChangedRoutine>d__64(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.35f); <>1__state = 2; return true; case 2: <>1__state = -1; SyncExternalZombieCaps(forceLog: true); DestroyAllOwnedZombies(forceLog: true); <>2__current = (object)new WaitForSeconds(0.25f); <>1__state = 3; return true; case 3: <>1__state = -1; SyncExternalZombieCaps(forceLog: true); RestartPeakZombiesSpawningForCurrentSegment(forceLog: true); <>2__current = (object)new WaitForSeconds(0.25f); <>1__state = 4; return true; case 4: <>1__state = -1; SyncExternalZombieCaps(forceLog: true); TrimZombieCountToSegmentCap(forceLog: true); <>4__this._segmentTransitionRoutine = null; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } internal static ManualLogSource Log; internal static Plugin Instance; private Harmony _harmony; private static ConfigEntry<int> _해변좀비수; private static ConfigEntry<int> _해변모닥불좀비수; private static ConfigEntry<int> _열대뿌리숲좀비수; private static ConfigEntry<int> _메사고산지대좀비수; private static ConfigEntry<int> _칼데라좀비수; private static ConfigEntry<int> _가마좀비수; private static ConfigEntry<int> _정상좀비수; private static ConfigEntry<float> _해변좀비타격횟수; private static ConfigEntry<float> _해변모닥불좀비타격횟수; private static ConfigEntry<float> _열대뿌리숲좀비타격횟수; private static ConfigEntry<float> _메사고산지대좀비타격횟수; private static ConfigEntry<float> _칼데라좀비타격횟수; private static ConfigEntry<float> _가마좀비타격횟수; private static ConfigEntry<float> _정상좀비타격횟수; private static ConfigEntry<bool> _verboseLogging; private static FieldInfo _akCharacterGettingShotField; private static FieldInfo _akShotTimeField; private static FieldInfo _akShotDirectionField; private static FieldInfo _mushroomZombieAchievementTestTickField; private static MethodInfo _mushroomZombieDieMethod; private static Type _peakZombiesType; private static FieldInfo _peakZombiesInstanceField; private static FieldInfo _peakZombiesCustomMaxZombiesField; private static FieldInfo _peakZombiesBypassMaxZombieLimitField; private static FieldInfo _peakZombiesInitialSpawnCountField; private static FieldInfo _peakZombiesAutoSpawnIntervalField; private static FieldInfo _peakZombiesAutoSpawnRadiusField; private static MethodInfo _peakZombiesGetSpawnCenterMethod; private static MethodInfo _peakZombiesSpawnZombiesAroundMethod; private static MethodInfo _peakZombiesStartAutoSpawningMethod; private static MethodInfo _peakZombiesStopAutoSpawningMethod; private static MethodInfo _peakZombiesSpawnInitialZombiesMethod; private static object _lastPeakZombiesInstance; private static int _lastAppliedExternalCap = -1; private static Segment? _lastAppliedSegment = null; private static int _beachVisitCount = 0; private float _nextExternalSyncTime; private Segment? _lastObservedSegment; private Coroutine _segmentTransitionRoutine; private void Awake() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Expected O, but got Unknown //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; ((BaseUnityPlugin)this).Config.SaveOnConfigSet = true; BindConfigs(); _harmony = new Harmony("com.Sapphire009.AutoSpawn"); try { _mushroomZombieAchievementTestTickField = AccessTools.Field(typeof(MushroomZombie), "achievementTestTick"); _mushroomZombieDieMethod = AccessTools.Method(typeof(MushroomZombie), "Die", (Type[])null, (Type[])null); if (_mushroomZombieAchievementTestTickField != null) { Log.LogInfo((object)"Found MushroomZombie.achievementTestTick"); } else { Log.LogWarning((object)"Could not find MushroomZombie.achievementTestTick"); } if (_mushroomZombieDieMethod != null) { Log.LogInfo((object)"Found MushroomZombie.Die()"); } else { Log.LogWarning((object)"Could not find MushroomZombie.Die()"); } CachePeakZombiesReflection(); MethodInfo methodInfo = AccessTools.Method(typeof(MushroomZombieSpawner), "Spawn", (Type[])null, (Type[])null); if (methodInfo != null) { _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(Plugin), "MushroomZombieSpawner_Spawn_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"Patched MushroomZombieSpawner.Spawn"); } else { Log.LogWarning((object)"Could not find MushroomZombieSpawner.Spawn"); } MethodInfo methodInfo2 = AccessTools.Method(typeof(MapHandler), "JumpToSegmentLogic", new Type[4] { typeof(Segment), typeof(HashSet<int>), typeof(bool), typeof(bool) }, (Type[])null); if (methodInfo2 != null) { _harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "MapHandler_JumpToSegmentLogic_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"Patched MapHandler.JumpToSegmentLogic"); } else { Log.LogWarning((object)"Could not find MapHandler.JumpToSegmentLogic"); } PatchExternalMethod("Zombies_Anywhere.ZombiesAnywhereMod", "SpawnZombieAt", new Type[3] { typeof(Vector3), typeof(Quaternion), typeof(MushroomZombie) }, "PeakZombies_SpawnZombieAt_Prefix"); PatchExternalMethod("Zombies_Anywhere.ZombiesAnywhereMod", "SpawnZombiesAround", new Type[3] { typeof(Vector3), typeof(float), typeof(int) }, "PeakZombies_SpawnZombiesAround_Prefix"); PatchExternalMethod("Zombies_Anywhere.ZombiesAnywhereMod", "SpawnInitialZombies", Type.EmptyTypes, "PeakZombies_SpawnInitialZombies_Prefix"); PatchExternalMethod("AK_Gun.GunCharacterLaunch", "RPC_ShootSelfT", new Type[3] { typeof(float), typeof(int), typeof(Vector3) }, "AKGun_RPC_ShootSelfT_Prefix"); Log.LogInfo((object)"========================================"); Log.LogInfo((object)"Segment Zombie Rules loaded"); Log.LogInfo((object)"Config-driven zombie cap enabled"); Log.LogInfo((object)"Fixed hit progression enabled"); Log.LogInfo((object)"Map transition zombie resync enabled"); Log.LogInfo((object)"PEAK_Zombies auto-spawn restart on segment change enabled"); LogCurrentConfigValues(); Log.LogInfo((object)"========================================"); } catch (Exception ex) { Log.LogError((object)("Plugin Awake exception: " + ex)); } } private void Update() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) try { if (!PhotonNetwork.IsMasterClient) { return; } if (MapHandler.Exists) { Segment currentSegmentNumber = MapHandler.CurrentSegmentNumber; if (!_lastObservedSegment.HasValue) { _lastObservedSegment = currentSegmentNumber; } else if (_lastObservedSegment.Value != currentSegmentNumber) { _lastObservedSegment = currentSegmentNumber; HandleSegmentChanged(currentSegmentNumber, "UpdateFallback"); } } if (!(Time.time < _nextExternalSyncTime)) { _nextExternalSyncTime = Time.time + 0.5f; SyncExternalZombieCaps(forceLog: false); TrimZombieCountToSegmentCap(forceLog: false); } } catch (Exception ex) { Log.LogError((object)("Plugin Update exception: " + ex)); } } private void OnDestroy() { try { if (_segmentTransitionRoutine != null) { ((MonoBehaviour)this).StopCoroutine(_segmentTransitionRoutine); _segmentTransitionRoutine = null; } Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } catch (Exception ex) { Log.LogError((object)("Plugin OnDestroy exception: " + ex)); } } private void BindConfigs() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Expected O, but got Unknown //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Expected O, but got Unknown //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Expected O, but got Unknown //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Expected O, but got Unknown //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Expected O, but got Unknown //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Expected O, but got Unknown //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Expected O, but got Unknown //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Expected O, but got Unknown //IL_029a: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Expected O, but got Unknown //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Expected O, but got Unknown //IL_0314: Unknown result type (might be due to invalid IL or missing references) //IL_031e: Expected O, but got Unknown _해변좀비수 = ((BaseUnityPlugin)this).Config.Bind<int>("좀비 수 제한", "해변 좀비 수", 3, new ConfigDescription("해변 세그먼트 최대 좀비 수", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200), Array.Empty<object>())); _해변모닥불좀비수 = ((BaseUnityPlugin)this).Config.Bind<int>("좀비 수 제한", "해변 모닥불 좀비 수", 5, new ConfigDescription("해변 모닥불 구간 최대 좀비 수", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200), Array.Empty<object>())); _열대뿌리숲좀비수 = ((BaseUnityPlugin)this).Config.Bind<int>("좀비 수 제한", "열대뿌리숲 좀비 수", 7, new ConfigDescription("열대뿌리숲 세그먼트 최대 좀비 수", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200), Array.Empty<object>())); _메사고산지대좀비수 = ((BaseUnityPlugin)this).Config.Bind<int>("좀비 수 제한", "메사고산지대 좀비 수", 9, new ConfigDescription("메사고산지대 세그먼트 최대 좀비 수", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200), Array.Empty<object>())); _칼데라좀비수 = ((BaseUnityPlugin)this).Config.Bind<int>("좀비 수 제한", "칼데라 좀비 수", 11, new ConfigDescription("칼데라 세그먼트 최대 좀비 수", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200), Array.Empty<object>())); _가마좀비수 = ((BaseUnityPlugin)this).Config.Bind<int>("좀비 수 제한", "가마 좀비 수", 13, new ConfigDescription("가마 세그먼트 최대 좀비 수", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200), Array.Empty<object>())); _정상좀비수 = ((BaseUnityPlugin)this).Config.Bind<int>("좀비 수 제한", "정상 좀비 수", 15, new ConfigDescription("정상 세그먼트 최대 좀비 수", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200), Array.Empty<object>())); _해변좀비타격횟수 = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 타격 횟수", "해변 좀비 타격 횟수", 5f, new ConfigDescription("해변 첫 방문 시 좀비 처치까지 필요한 타격 횟수", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 200f), Array.Empty<object>())); _해변모닥불좀비타격횟수 = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 타격 횟수", "해변 모닥불 좀비 타격 횟수", 8f, new ConfigDescription("해변 모닥불 구간 좀비 처치까지 필요한 타격 횟수", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 200f), Array.Empty<object>())); _열대뿌리숲좀비타격횟수 = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 타격 횟수", "열대뿌리숲 좀비 타격 횟수", 10f, new ConfigDescription("열대뿌리숲 좀비 처치까지 필요한 타격 횟수", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 200f), Array.Empty<object>())); _메사고산지대좀비타격횟수 = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 타격 횟수", "메사고산지대 좀비 타격 횟수", 13f, new ConfigDescription("메사고산지대 좀비 처치까지 필요한 타격 횟수", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 200f), Array.Empty<object>())); _칼데라좀비타격횟수 = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 타격 횟수", "칼데라 좀비 타격 횟수", 15f, new ConfigDescription("칼데라 좀비 처치까지 필요한 타격 횟수", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 200f), Array.Empty<object>())); _가마좀비타격횟수 = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 타격 횟수", "가마 좀비 타격 횟수", 18f, new ConfigDescription("가마 좀비 처치까지 필요한 타격 횟수", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 200f), Array.Empty<object>())); _정상좀비타격횟수 = ((BaseUnityPlugin)this).Config.Bind<float>("좀비 타격 횟수", "정상 좀비 타격 횟수", 20f, new ConfigDescription("정상 좀비 처치까지 필요한 타격 횟수", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 200f), Array.Empty<object>())); } private static void LogCurrentConfigValues() { Log.LogInfo((object)"Zombie max by segment:"); Log.LogInfo((object)$"Beach={ReadMaxZombieValue(_해변좀비수, 3)}, BeachCampfire={ReadMaxZombieValue(_해변모닥불좀비수, 5)}, Tropics={ReadMaxZombieValue(_열대뿌리숲좀비수, 7)}, Alpine={ReadMaxZombieValue(_메사고산지대좀비수, 9)}, Caldera={ReadMaxZombieValue(_칼데라좀비수, 11)}, TheKiln={ReadMaxZombieValue(_가마좀비수, 13)}, Peak={ReadMaxZombieValue(_정상좀비수, 15)}"); Log.LogInfo((object)$"Hits-to-kill: Beach={ReadHitsValue(_해변좀비타격횟수, 5f)}, BeachCampfire={ReadHitsValue(_해변모닥불좀비타격횟수, 8f)}, Tropics={ReadHitsValue(_열대뿌리숲좀비타격횟수, 1f)}, Alpine={ReadHitsValue(_메사고산지대좀비타격횟수, 13f)}, Caldera={ReadHitsValue(_칼데라좀비타격횟수, 15f)}, TheKiln={ReadHitsValue(_가마좀비타격횟수, 18f)}, Peak={ReadHitsValue(_정상좀비타격횟수, 20f)}"); } private void PatchExternalMethod(string typeName, string methodName, Type[] argTypes, string prefixMethodName) { //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown try { Type type = AccessTools.TypeByName(typeName); if (type == null) { Log.LogWarning((object)("Type not found: " + typeName)); return; } MethodInfo methodInfo = AccessTools.Method(type, methodName, argTypes, (Type[])null); if (methodInfo == null) { Log.LogWarning((object)("Method not found: " + typeName + "." + methodName)); return; } MethodInfo methodInfo2 = AccessTools.Method(typeof(Plugin), prefixMethodName, (Type[])null, (Type[])null); if (methodInfo2 == null) { Log.LogWarning((object)("Prefix method not found: " + prefixMethodName)); return; } _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)("Patched " + typeName + "." + methodName)); } catch (Exception ex) { Log.LogError((object)("PatchExternalMethod exception for " + typeName + "." + methodName + ": " + ex)); } } private static void CachePeakZombiesReflection() { try { _peakZombiesType = AccessTools.TypeByName("Zombies_Anywhere.ZombiesAnywhereMod"); if (_peakZombiesType == null) { Log.LogWarning((object)"PEAK_Zombies type not found: Zombies_Anywhere.ZombiesAnywhereMod"); return; } _peakZombiesInstanceField = AccessTools.Field(_peakZombiesType, "_instance"); _peakZombiesCustomMaxZombiesField = AccessTools.Field(_peakZombiesType, "customMaxZombies"); _peakZombiesBypassMaxZombieLimitField = AccessTools.Field(_peakZombiesType, "bypassMaxZombieLimit"); _peakZombiesInitialSpawnCountField = AccessTools.Field(_peakZombiesType, "initialSpawnCount"); _peakZombiesAutoSpawnIntervalField = AccessTools.Field(_peakZombiesType, "autoSpawnInterval"); _peakZombiesAutoSpawnRadiusField = AccessTools.Field(_peakZombiesType, "autoSpawnRadius"); _peakZombiesGetSpawnCenterMethod = AccessTools.Method(_peakZombiesType, "GetSpawnCenter", Type.EmptyTypes, (Type[])null); _peakZombiesSpawnZombiesAroundMethod = AccessTools.Method(_peakZombiesType, "SpawnZombiesAround", new Type[3] { typeof(Vector3), typeof(float), typeof(int) }, (Type[])null); _peakZombiesStartAutoSpawningMethod = AccessTools.Method(_peakZombiesType, "StartAutoSpawning", new Type[2] { typeof(float), typeof(float) }, (Type[])null); _peakZombiesStopAutoSpawningMethod = AccessTools.Method(_peakZombiesType, "StopAutoSpawning", Type.EmptyTypes, (Type[])null); _peakZombiesSpawnInitialZombiesMethod = AccessTools.Method(_peakZombiesType, "SpawnInitialZombies", Type.EmptyTypes, (Type[])null); } catch (Exception ex) { Log.LogError((object)("CachePeakZombiesReflection exception: " + ex)); } } private static bool IsBeachCampfirePhase() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 if (!MapHandler.Exists || (int)MapHandler.CurrentSegmentNumber > 0) { re