Decompiled source of Zombie Survival World v1.0.0

plugins/Zombie_Survival.dll

Decompiled a day ago
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 Reload
{
	[BepInPlugin("reload.akhotkey.spawninhand", "AK Reload NativeUseUI", "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
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			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());
			((BaseUnityPlugin)this).Logger.LogInfo((object)"========================================");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[AKReloadDBG] AK Reload NativeUseUI loaded");
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AKReloadDBG] Reload Time = " + GetReloadUseTime() + " sec"));
			ManualLogSource logger = ((BaseUnityPlugin)this).Logger;
			KeyCode reloadKey = GetReloadKey();
			logger.LogInfo((object)("[AKReloadDBG] Reload Key = " + ((object)(KeyCode)(ref reloadKey)).ToString()));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AKReloadDBG] Reload Sound File = " + GetReloadSoundFileName()));
			((BaseUnityPlugin)this).Logger.LogInfo((object)"========================================");
		}

		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
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Expected O, but got Unknown
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Expected O, but got Unknown
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Expected O, but got Unknown
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Expected O, but got Unknown
			_reloadUseTime = ((BaseUnityPlugin)this).Config.Bind<float>("Reload", "Reload Time", 3f, new ConfigDescription("AK 재장전 시간(초). 0이면 즉시 재장전.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 60f), Array.Empty<object>()));
			_reloadKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Reload", "Reload Key", (KeyCode)114, "재장전 키");
			_reloadSoundFileName = ((BaseUnityPlugin)this).Config.Bind<string>("Reload Sound", "Reload Sound File", "장전소리.ogg", "재장전 사운드 파일명. DLL과 같은 폴더에 둔다.");
			_reloadSoundVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Reload Sound", "Reload Sound Volume", 1f, new ConfigDescription("재장전 사운드 볼륨", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			_reloadSoundStartOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Reload Sound", "Reload Sound Start Offset", 0.78f, new ConfigDescription("사운드 시작 오프셋(초). 파일 앞 무음을 건너뛸 때 사용", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
			_reloadSoundMinDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Reload Sound", "Reload Sound Min Distance", 3f, new ConfigDescription("3D 사운드 최소 거리", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>()));
			_reloadSoundMaxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Reload Sound", "Reload Sound Max Distance", 25f, new ConfigDescription("3D 사운드 최대 거리", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 200f), Array.Empty<object>()));
			_verboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Verbose Logging", true, "상세 재장전 로그 출력 여부");
		}

		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, 2f);
		}

		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 AKGun_RuntimePatch
{
	[BepInPlugin("com.sol.akgunruntimepatch", "AK Gun Runtime Patch", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			_harmony = new Harmony("com.sol.akgunruntimepatch");
			_harmony.PatchAll();
			Log.LogInfo((object)"AK Gun Runtime Patch loaded.");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	internal static class PatchCache
	{
		internal static readonly FieldInfo CharacterGettingShotField = AccessTools.Field(typeof(GunCharacterLaunch), "characterGettingShot");

		internal static readonly FieldInfo ShotDirectionField = AccessTools.Field(typeof(GunCharacterLaunch), "shotDirection");

		private static Type _mushroomZombieType;

		private static FieldInfo _achievementTestTickField;

		private static MethodInfo _dieMethod;

		private static bool _searchedZombieType;

		internal static bool TryGetCharacterGettingShot(GunCharacterLaunch instance, out Character target)
		{
			target = null;
			try
			{
				if (CharacterGettingShotField == null)
				{
					return false;
				}
				object? value = CharacterGettingShotField.GetValue(instance);
				target = (Character)((value is Character) ? value : null);
				return (Object)(object)target != (Object)null;
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"[PatchCache] TryGetCharacterGettingShot failed: {arg}");
				return false;
			}
		}

		internal static bool TryGetShotDirection(GunCharacterLaunch instance, out Vector3 direction)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: 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)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			direction = default(Vector3);
			try
			{
				if (ShotDirectionField == null)
				{
					return false;
				}
				if (ShotDirectionField.GetValue(instance) is Vector3 val)
				{
					direction = val;
					return true;
				}
				return false;
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"[PatchCache] TryGetShotDirection failed: {arg}");
				return false;
			}
		}

		internal static bool TryResolveMushroomZombieMembers()
		{
			if (_searchedZombieType)
			{
				return _mushroomZombieType != null && _achievementTestTickField != null && _dieMethod != null;
			}
			_searchedZombieType = true;
			try
			{
				_mushroomZombieType = AccessTools.TypeByName("MushroomZombie");
				if (_mushroomZombieType == null)
				{
					Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
					foreach (Assembly assembly in assemblies)
					{
						Type type = null;
						try
						{
							type = assembly.GetTypes().FirstOrDefault((Type t) => t.Name == "MushroomZombie");
						}
						catch
						{
						}
						if (type != null)
						{
							_mushroomZombieType = type;
							break;
						}
					}
				}
				if (_mushroomZombieType == null)
				{
					Plugin.Log.LogWarning((object)"[PatchCache] MushroomZombie type not found.");
					return false;
				}
				_achievementTestTickField = AccessTools.Field(_mushroomZombieType, "achievementTestTick");
				_dieMethod = AccessTools.Method(_mushroomZombieType, "Die", (Type[])null, (Type[])null);
				if (_achievementTestTickField == null)
				{
					Plugin.Log.LogWarning((object)"[PatchCache] achievementTestTick field not found.");
					return false;
				}
				if (_dieMethod == null)
				{
					Plugin.Log.LogWarning((object)"[PatchCache] Die() method not found.");
					return false;
				}
				return true;
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"[PatchCache] TryResolveMushroomZombieMembers failed: {arg}");
				return false;
			}
		}

		internal static Component GetMushroomZombieComponent(Character target)
		{
			try
			{
				if ((Object)(object)target == (Object)null)
				{
					return null;
				}
				if (!TryResolveMushroomZombieMembers())
				{
					return null;
				}
				return ((Component)target).GetComponent(_mushroomZombieType);
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"[PatchCache] GetMushroomZombieComponent failed: {arg}");
				return null;
			}
		}

		internal static bool TryAddAchievementTickAndKill(Component mushroomZombieComponent)
		{
			try
			{
				if ((Object)(object)mushroomZombieComponent == (Object)null)
				{
					return false;
				}
				if (!TryResolveMushroomZombieMembers())
				{
					return false;
				}
				object value = _achievementTestTickField.GetValue(mushroomZombieComponent);
				float num = 0f;
				if (value != null)
				{
					num = Convert.ToSingle(value);
				}
				num += 1f;
				_achievementTestTickField.SetValue(mushroomZombieComponent, num);
				if (num >= 10f)
				{
					_dieMethod.Invoke(mushroomZombieComponent, null);
				}
				return true;
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"[PatchCache] TryAddAchievementTickAndKill failed: {arg}");
				return false;
			}
		}
	}
	[HarmonyPatch(typeof(GunCharacterLaunch), "RPC_ShootSelfT")]
	internal static class Patch_RPC_ShootSelfT
	{
		[HarmonyPostfix]
		private static void Postfix(GunCharacterLaunch __instance)
		{
			try
			{
				if (PatchCache.TryGetCharacterGettingShot(__instance, out var target) && !((Object)(object)target == (Object)null))
				{
					Component mushroomZombieComponent = PatchCache.GetMushroomZombieComponent(target);
					if (!((Object)(object)mushroomZombieComponent == (Object)null))
					{
						PatchCache.TryAddAchievementTickAndKill(mushroomZombieComponent);
					}
				}
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"[Patch_RPC_ShootSelfT] Postfix failed: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(GunCharacterLaunch), "UpdateShotPhysicsT")]
	internal static class Patch_UpdateShotPhysicsT
	{
		[HarmonyPrefix]
		private static bool Prefix(GunCharacterLaunch __instance)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!PatchCache.TryGetCharacterGettingShot(__instance, out var target))
				{
					return false;
				}
				if ((Object)(object)target == (Object)null)
				{
					return false;
				}
				if (!PatchCache.TryGetShotDirection(__instance, out var direction))
				{
					return false;
				}
				Vector3 val = direction * 25f * -1f;
				CharacterExtensions.AddForce(target, val, 1f, 1f, (ForceMode)5);
				return false;
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"[Patch_UpdateShotPhysicsT] Prefix failed: {arg}");
				return false;
			}
		}
	}
}
namespace SegmentZombieRules
{
	[BepInPlugin("com.sol.segmentzombierules", "Segment Zombie Rules", "1.3.0")]
	public class Plugin : BaseUnityPlugin
	{
		[CompilerGenerated]
		private sealed class <HandleSegmentChangedRoutine>d__61 : 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__61(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> _beachMaxZombies;

		private static ConfigEntry<int> _tropicsMaxZombies;

		private static ConfigEntry<int> _alpineMaxZombies;

		private static ConfigEntry<int> _calderaMaxZombies;

		private static ConfigEntry<int> _theKilnMaxZombies;

		private static ConfigEntry<int> _peakMaxZombies;

		private static ConfigEntry<int> _beachHitsToKill;

		private static ConfigEntry<int> _tropicsHitsToKill;

		private static ConfigEntry<int> _alpineHitsToKill;

		private static ConfigEntry<int> _calderaHitsToKill;

		private static ConfigEntry<int> _theKilnHitsToKill;

		private static ConfigEntry<int> _peakHitsToKill;

		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 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.sol.segmentzombierules");
			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 values 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Expected O, but got Unknown
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Expected O, but got Unknown
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Expected O, but got Unknown
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Expected O, but got Unknown
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Expected O, but got Unknown
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Expected O, but got Unknown
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Expected O, but got Unknown
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Expected O, but got Unknown
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Expected O, but got Unknown
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Expected O, but got Unknown
			_verboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Verbose Logging", true, "세그먼트별 스폰 차단/피격/전환 로그를 자세히 출력할지 여부");
			_beachMaxZombies = ((BaseUnityPlugin)this).Config.Bind<int>("Zombie Cap", "Beach Max Zombies", 3, new ConfigDescription("Beach 세그먼트 최대 좀비 수", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200), Array.Empty<object>()));
			_tropicsMaxZombies = ((BaseUnityPlugin)this).Config.Bind<int>("Zombie Cap", "Tropics Max Zombies", 5, new ConfigDescription("Tropics 세그먼트 최대 좀비 수", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200), Array.Empty<object>()));
			_alpineMaxZombies = ((BaseUnityPlugin)this).Config.Bind<int>("Zombie Cap", "Alpine Max Zombies", 7, new ConfigDescription("Alpine 세그먼트 최대 좀비 수", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200), Array.Empty<object>()));
			_calderaMaxZombies = ((BaseUnityPlugin)this).Config.Bind<int>("Zombie Cap", "Caldera Max Zombies", 10, new ConfigDescription("Caldera 세그먼트 최대 좀비 수", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200), Array.Empty<object>()));
			_theKilnMaxZombies = ((BaseUnityPlugin)this).Config.Bind<int>("Zombie Cap", "TheKiln Max Zombies", 10, new ConfigDescription("TheKiln 세그먼트 최대 좀비 수", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200), Array.Empty<object>()));
			_peakMaxZombies = ((BaseUnityPlugin)this).Config.Bind<int>("Zombie Cap", "Peak Max Zombies", 15, new ConfigDescription("Peak 세그먼트 최대 좀비 수", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200), Array.Empty<object>()));
			_beachHitsToKill = ((BaseUnityPlugin)this).Config.Bind<int>("Hits To Kill", "Beach Hits To Kill", 3, new ConfigDescription("Beach 세그먼트 좀비 처치 타수", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 200), Array.Empty<object>()));
			_tropicsHitsToKill = ((BaseUnityPlugin)this).Config.Bind<int>("Hits To Kill", "Tropics Hits To Kill", 5, new ConfigDescription("Tropics 세그먼트 좀비 처치 타수", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 200), Array.Empty<object>()));
			_alpineHitsToKill = ((BaseUnityPlugin)this).Config.Bind<int>("Hits To Kill", "Alpine Hits To Kill", 7, new ConfigDescription("Alpine 세그먼트 좀비 처치 타수", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 200), Array.Empty<object>()));
			_calderaHitsToKill = ((BaseUnityPlugin)this).Config.Bind<int>("Hits To Kill", "Caldera Hits To Kill", 10, new ConfigDescription("Caldera 세그먼트 좀비 처치 타수", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 200), Array.Empty<object>()));
			_theKilnHitsToKill = ((BaseUnityPlugin)this).Config.Bind<int>("Hits To Kill", "TheKiln Hits To Kill", 10, new ConfigDescription("TheKiln 세그먼트 좀비 처치 타수", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 200), Array.Empty<object>()));
			_peakHitsToKill = ((BaseUnityPlugin)this).Config.Bind<int>("Hits To Kill", "Peak Hits To Kill", 15, new ConfigDescription("Peak 세그먼트 좀비 처치 타수", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 200), Array.Empty<object>()));
		}

		private static void LogCurrentConfigValues()
		{
			Log.LogInfo((object)"Zombie max by segment:");
			Log.LogInfo((object)$"Beach={ReadMaxZombieValue(_beachMaxZombies, 3)}, Tropics={ReadMaxZombieValue(_tropicsMaxZombies, 5)}, Alpine={ReadMaxZombieValue(_alpineMaxZombies, 7)}, Caldera={ReadMaxZombieValue(_calderaMaxZombies, 10)}, TheKiln={ReadMaxZombieValue(_theKilnMaxZombies, 10)}, Peak={ReadMaxZombieValue(_peakMaxZombies, 15)}");
			Log.LogInfo((object)"Hits-to-kill by segment:");
			Log.LogInfo((object)$"Beach={ReadHitsToKillValue(_beachHitsToKill, 3)}, Tropics={ReadHitsToKillValue(_tropicsHitsToKill, 5)}, Alpine={ReadHitsToKillValue(_alpineHitsToKill, 7)}, Caldera={ReadHitsToKillValue(_calderaHitsToKill, 10)}, TheKiln={ReadHitsToKillValue(_theKilnHitsToKill, 10)}, Peak={ReadHitsToKillValue(_peakHitsToKill, 15)}");
		}

		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);
				Log.LogInfo((object)"PEAK_Zombies reflection cache result:");
				Log.LogInfo((object)(" - _instance: " + (_peakZombiesInstanceField != null)));
				Log.LogInfo((object)(" - customMaxZombies: " + (_peakZombiesCustomMaxZombiesField != null)));
				Log.LogInfo((object)(" - bypassMaxZombieLimit: " + (_peakZombiesBypassMaxZombieLimitField != null)));
				Log.LogInfo((object)(" - initialSpawnCount: " + (_peakZombiesInitialSpawnCountField != null)));
				Log.LogInfo((object)(" - autoSpawnInterval: " + (_peakZombiesAutoSpawnIntervalField != null)));
				Log.LogInfo((object)(" - autoSpawnRadius: " + (_peakZombiesAutoSpawnRadiusField != null)));
				Log.LogInfo((object)(" - GetSpawnCenter(): " + (_peakZombiesGetSpawnCenterMethod != null)));
				Log.LogInfo((object)(" - SpawnZombiesAround(): " + (_peakZombiesSpawnZombiesAroundMethod != null)));
				Log.LogInfo((object)(" - StartAutoSpawning(): " + (_peakZombiesStartAutoSpawningMethod != null)));
				Log.LogInfo((object)(" - StopAutoSpawning(): " + (_peakZombiesStopAutoSpawningMethod != null)));
			}
			catch (Exception ex)
			{
				Log.LogError((object)("CachePeakZombiesReflection exception: " + ex));
			}
		}

		private static int ReadMaxZombieValue(ConfigEntry<int> entry, int fallback)
		{
			if (entry == null)
			{
				return fallback;
			}
			return Mathf.Max(0, entry.Value);
		}

		private static int ReadHitsToKillValue(ConfigEntry<int> entry, int fallback)
		{
			if (entry == null)
			{
				return fallback;
			}
			return Mathf.Max(1, entry.Value);
		}

		private static int GetSegmentMaxZombies()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected I4, but got Unknown
			if (!MapHandler.Exists)
			{
				return ReadMaxZombieValue(_beachMaxZombies, 3);
			}
			Segment currentSegmentNumber = MapHandler.CurrentSegmentNumber;
			Segment val = currentSegmentNumber;
			return (int)val switch
			{
				0 => ReadMaxZombieValue(_beachMaxZombies, 3), 
				1 => ReadMaxZombieValue(_tropicsMaxZombies, 5), 
				2 => ReadMaxZombieValue(_alpineMaxZombies, 7), 
				3 => ReadMaxZombieValue(_calderaMaxZombies, 10), 
				4 => ReadMaxZombieValue(_theKilnMaxZombies, 10), 
				5 => ReadMaxZombieValue(_peakMaxZombies, 15), 
				_ => ReadMaxZombieValue(_beachMaxZombies, 3), 
			};
		}

		private static float GetHitsToKillBySegment()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected I4, but got Unknown
			if (!MapHandler.Exists)
			{
				return ReadHitsToKillValue(_beachHitsToKill, 3);
			}
			Segment currentSegmentNumber = MapHandler.CurrentSegmentNumber;
			Segment val = currentSegmentNumber;
			return (int)val switch
			{
				0 => ReadHitsToKillValue(_beachHitsToKill, 3), 
				1 => ReadHitsToKillValue(_tropicsHitsToKill, 5), 
				2 => ReadHitsToKillValue(_alpineHitsToKill, 7), 
				3 => ReadHitsToKillValue(_calderaHitsToKill, 10), 
				4 => ReadHitsToKillValue(_theKilnHitsToKill, 10), 
				5 => ReadHitsToKillValue(_peakHitsToKill, 15), 
				_ => ReadHitsToKillValue(_beachHitsToKill, 3), 
			};
		}

		private static string GetCurrentSegmentName()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (!MapHandler.Exists)
			{
				return "Unknown";
			}
			Segment currentSegmentNumber = MapHandler.CurrentSegmentNumber;
			return ((object)(Segment)(ref currentSegmentNumber)).ToString();
		}

		private static int GetCurrentZombieCount()
		{
			try
			{
				if ((Object)(object)ZombieManager.Instance != (Object)null && ZombieManager.Instance.zombies != null)
				{
					return ZombieManager.Instance.zombies.Count;
				}
			}
			catch
			{
			}
			try
			{
				MushroomZombie[] array = Object.FindObjectsByType<MushroomZombie>((FindObjectsInactive)0, (FindObjectsSortMode)0);
				return array.Length;
			}
			catch
			{
				return 0;
			}
		}

		private static int GetRemainingSpawnSlots()
		{
			int segmentMaxZombies = GetSegmentMaxZombies();
			int currentZombieCount = GetCurrentZombieCount();
			return Mathf.Max(0, segmentMaxZombies - currentZombieCount);
		}

		private static object GetPeakZombiesInstance()
		{
			if (_peakZombiesInstanceField == null)
			{
				return null;
			}
			try
			{
				return _peakZombiesInstanceField.GetValue(null);
			}
			catch
			{
				return null;
			}
		}

		private static int ReadPeakIntConfig(FieldInfo field, object instance, int fallback)
		{
			try
			{
				if (field == null || instance == null)
				{
					return fallback;
				}
				if (!(field.GetValue(instance) is ConfigEntry<int> val))
				{
					return fallback;
				}
				return val.Value;
			}
			catch
			{
				return fallback;
			}
		}

		private static float ReadPeakFloatConfig(FieldInfo field, object instance, float fallback)
		{
			try
			{
				if (field == null || instance == null)
				{
					return fallback;
				}
				if (!(field.GetValue(instance) is ConfigEntry<float> val))
				{
					return fallback;
				}
				return val.Value;
			}
			catch
			{
				return fallback;
			}
		}

		private static void SyncExternalZombieCaps(bool forceLog)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.IsMasterClient)
			{
				return;
			}
			int segmentMaxZombies = GetSegmentMaxZombies();
			Segment val = (Segment)(MapHandler.Exists ? ((int)MapHandler.CurrentSegmentNumber) : 0);
			try
			{
				if ((Object)(object)ZombieManager.Instance != (Object)null && ZombieManager.Instance.maxActiveZombies != segmentMaxZombies)
				{
					ZombieManager.Instance.maxActiveZombies = segmentMaxZombies;
					if ((_verboseLogging != null && _verboseLogging.Value) || forceLog)
					{
						Log.LogInfo((object)$"[ZombieCapSync] ZombieManager.maxActiveZombies -> {segmentMaxZombies} ({val})");
					}
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("SyncExternalZombieCaps ZombieManager exception: " + ex));
			}
			try
			{
				if (_peakZombiesType == null || _peakZombiesInstanceField == null || _peakZombiesCustomMaxZombiesField == null || _peakZombiesBypassMaxZombieLimitField == null)
				{
					return;
				}
				object value = _peakZombiesInstanceField.GetValue(null);
				if (value == null)
				{
					return;
				}
				ConfigEntry<int> val2 = _peakZombiesCustomMaxZombiesField.GetValue(value) as ConfigEntry<int>;
				ConfigEntry<bool> val3 = _peakZombiesBypassMaxZombieLimitField.GetValue(value) as ConfigEntry<bool>;
				if (val2 == null || val3 == null)
				{
					Log.LogWarning((object)"[ZombieCapSync] PEAK_Zombies config entries not found");
					return;
				}
				bool flag = false;
				if (val3.Value)
				{
					val3.Value = false;
					flag = true;
				}
				if (val2.Value != segmentMaxZombies)
				{
					val2.Value = segmentMaxZombies;
					flag = true;
				}
				if ((forceLog || flag || _lastPeakZombiesInstance != value || _lastAppliedExternalCap != segmentMaxZombies || !_lastAppliedSegment.HasValue || _lastAppliedSegment.Value != val) && ((_verboseLogging != null && _verboseLogging.Value) || forceLog))
				{
					Log.LogInfo((object)$"[ZombieCapSync] PEAK_Zombies override applied | Segment={val} | customMaxZombies={val2.Value} | bypassMaxZombieLimit={val3.Value}");
				}
				_lastPeakZombiesInstance = value;
				_lastAppliedExternalCap = segmentMaxZombies;
				_lastAppliedSegment = val;
			}
			catch (Exception ex2)
			{
				Log.LogError((object)("SyncExternalZombieCaps PEAK_Zombies exception: " + ex2));
			}
		}

		private static bool IsSpawnBlockedBySegmentCap()
		{
			int currentZombieCount = GetCurrentZombieCount();
			int segmentMaxZombies = GetSegmentMaxZombies();
			if (currentZombieCount >= segmentMaxZombies)
			{
				if (_verboseLogging != null && _verboseLogging.Value)
				{
					Log.LogInfo((object)$"[ZombieCap] Blocked spawn in {GetCurrentSegmentName()} ({currentZombieCount}/{segmentMaxZombies})");
				}
				return true;
			}
			return false;
		}

		private static void TrimZombieCountToSegmentCap(bool forceLog)
		{
			try
			{
				if (!PhotonNetwork.IsMasterClient)
				{
					return;
				}
				int segmentMaxZombies = GetSegmentMaxZombies();
				MushroomZombie[] array = Object.FindObjectsByType<MushroomZombie>((FindObjectsInactive)1, (FindObjectsSortMode)0);
				if (array == null || array.Length <= segmentMaxZombies)
				{
					return;
				}
				int num = array.Length - segmentMaxZombies;
				int num2 = 0;
				int num3 = array.Length - 1;
				while (num3 >= 0 && num2 < num)
				{
					MushroomZombie val = array[num3];
					if (!((Object)(object)val == (Object)null))
					{
						PhotonView component = ((Component)val).GetComponent<PhotonView>();
						if (!((Object)(object)component != (Object)null) || component.IsMine)
						{
							val.DestroyZombie();
							num2++;
						}
					}
					num3--;
				}
				if (((_verboseLogging != null && _verboseLogging.Value) || forceLog) && num2 > 0)
				{
					Log.LogInfo((object)$"[ZombieTrim] Removed {num2} excess zombies in {GetCurrentSegmentName()} (limit={segmentMaxZombies})");
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("TrimZombieCountToSegmentCap exception: " + ex));
			}
		}

		private static void DestroyAllOwnedZombies(bool forceLog)
		{
			try
			{
				if (!PhotonNetwork.IsMasterClient)
				{
					return;
				}
				MushroomZombie[] array = Object.FindObjectsByType<MushroomZombie>((FindObjectsInactive)1, (FindObjectsSortMode)0);
				int num = 0;
				MushroomZombie[] array2 = array;
				foreach (MushroomZombie val in array2)
				{
					if (!((Object)(object)val == (Object)null))
					{
						PhotonView component = ((Component)val).GetComponent<PhotonView>();
						if (!((Object)(object)component != (Object)null) || component.IsMine)
						{
							val.DestroyZombie();
							num++;
						}
					}
				}
				if (((_verboseLogging != null && _verboseLogging.Value) || forceLog) && num > 0)
				{
					Log.LogInfo((object)("[ZombieReset] Destroyed zombies on segment change = " + num));
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("DestroyAllOwnedZombies exception: " + ex));
			}
		}

		private void HandleSegmentChanged(Segment targetSegment, string reason)
		{
			//IL_0033: 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)
			if (PhotonNetwork.IsMasterClient)
			{
				if (_verboseLogging != null && _verboseLogging.Value)
				{
					Log.LogInfo((object)$"[SegmentChange] {reason} -> {targetSegment}");
				}
				if (_segmentTransitionRoutine != null)
				{
					((MonoBehaviour)this).StopCoroutine(_segmentTransitionRoutine);
					_segmentTransitionRoutine = null;
				}
				_segmentTransitionRoutine = ((MonoBehaviour)this).StartCoroutine(HandleSegmentChangedRoutine(targetSegment));
			}
		}

		[IteratorStateMachine(typeof(<HandleSegmentChangedRoutine>d__61))]
		private IEnumerator HandleSegmentChangedRoutine(Segment targetSegment)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <HandleSegmentChangedRoutine>d__61(0)
			{
				<>4__this = this,
				targetSegment = targetSegment
			};
		}

		private static void RestartPeakZombiesSpawningForCurrentSegment(bool forceLog)
		{
			//IL_00d0: 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_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: 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)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!PhotonNetwork.IsMasterClient)
				{
					return;
				}
				object peakZombiesInstance = GetPeakZombiesInstance();
				if (peakZombiesInstance == null)
				{
					if ((_verboseLogging != null && _verboseLogging.Value) || forceLog)
					{
						Log.LogInfo((object)"[SegmentChange] PEAK_Zombies instance not found, skipping restart");
					}
					return;
				}
				try
				{
					_peakZombiesStopAutoSpawningMethod?.Invoke(peakZombiesInstance, null);
				}
				catch (Exception ex)
				{
					Log.LogError((object)("StopAutoSpawning invoke exception: " + ex));
				}
				SyncExternalZombieCaps(forceLog);
				float num = ReadPeakFloatConfig(_peakZombiesAutoSpawnRadiusField, peakZombiesInstance, 50f);
				float num2 = ReadPeakFloatConfig(_peakZombiesAutoSpawnIntervalField, peakZombiesInstance, 10f);
				int num3 = ReadPeakIntConfig(_peakZombiesInitialSpawnCountField, peakZombiesInstance, 0);
				Vector3 val = Vector3.zero;
				try
				{
					if (_peakZombiesGetSpawnCenterMethod != null)
					{
						object obj = _peakZombiesGetSpawnCenterMethod.Invoke(peakZombiesInstance, null);
						if (obj is Vector3)
						{
							Vector3 val2 = (Vector3)obj;
							if (true)
							{
								val = val2;
							}
						}
					}
				}
				catch (Exception ex2)
				{
					Log.LogError((object)("GetSpawnCenter invoke exception: " + ex2));
				}
				if (val != Vector3.zero && num3 > 0)
				{
					int num4 = Mathf.Min(num3, GetSegmentMaxZombies());
					if ((_verboseLogging != null && _verboseLogging.Value) || forceLog)
					{
						Log.LogInfo((object)$"[SegmentChange] Respawning initial zombies | Segment={GetCurrentSegmentName()} | Requested={num3} | Clamped={num4} | Radius={num}");
					}
					_peakZombiesSpawnZombiesAroundMethod?.Invoke(null, new object[3] { val, num, num4 });
				}
				else if (_peakZombiesSpawnInitialZombiesMethod != null)
				{
					if ((_verboseLogging != null && _verboseLogging.Value) || forceLog)
					{
						Log.LogInfo((object)"[SegmentChange] Fallback invoking SpawnInitialZombies()");
					}
					_peakZombiesSpawnInitialZombiesMethod.Invoke(peakZombiesInstance, null);
				}
				if (num2 > 0f)
				{
					_peakZombiesStartAutoSpawningMethod?.Invoke(null, new object[2] { num2, num });
					if ((_verboseLogging != null && _verboseLogging.Value) || forceLog)
					{
						Log.LogInfo((object)$"[SegmentChange] Restarted auto spawn | Interval={num2} | Radius={num}");
					}
				}
			}
			catch (Exception ex3)
			{
				Log.LogError((object)("RestartPeakZombiesSpawningForCurrentSegment exception: " + ex3));
			}
		}

		public static void MapHandler_JumpToSegmentLogic_Postfix(Segment segment)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!((Object)(object)Instance == (Object)null))
				{
					Instance._lastObservedSegment = segment;
					Instance.HandleSegmentChanged(segment, "JumpToSegmentLogic");
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("MapHandler_JumpToSegmentLogic_Postfix exception: " + ex));
			}
		}

		public static bool MushroomZombieSpawner_Spawn_Prefix()
		{
			try
			{
				if (!PhotonNetwork.IsMasterClient)
				{
					return true;
				}
				SyncExternalZombieCaps(forceLog: false);
				if (IsSpawnBlockedBySegmentCap())
				{
					return false;
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("MushroomZombieSpawner_Spawn_Prefix exception: " + ex));
			}
			return true;
		}

		public static bool PeakZombies_SpawnInitialZombies_Prefix()
		{
			try
			{
				if (!PhotonNetwork.IsMasterClient)
				{
					return true;
				}
				SyncExternalZombieCaps(forceLog: false);
			}
			catch (Exception ex)
			{
				Log.LogError((object)("PeakZombies_SpawnInitialZombies_Prefix exception: " + ex));
			}
			return true;
		}

		public static bool PeakZombies_SpawnZombieAt_Prefix(ref MushroomZombie __result)
		{
			try
			{
				if (!PhotonNetwork.IsMasterClient)
				{
					return true;
				}
				SyncExternalZombieCaps(forceLog: false);
				if (IsSpawnBlockedBySegmentCap())
				{
					__result = null;
					return false;
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("PeakZombies_SpawnZombieAt_Prefix exception: " + ex));
			}
			return true;
		}

		public static bool PeakZombies_SpawnZombiesAround_Prefix(ref List<MushroomZombie> __result, ref int count)
		{
			try
			{
				if (!PhotonNetwork.IsMasterClient)
				{
					return true;
				}
				SyncExternalZombieCaps(forceLog: false);
				int currentZombieCount = GetCurrentZombieCount();
				int segmentMaxZombies = GetSegmentMaxZombies();
				int num = Mathf.Max(0, segmentMaxZombies - currentZombieCount);
				if (num <= 0)
				{
					if (_verboseLogging != null && _verboseLogging.Value)
					{
						Log.LogInfo((object)$"[ZombieCap] Blocked SpawnZombiesAround in {GetCurrentSegmentName()} ({currentZombieCount}/{segmentMaxZombies})");
					}
					__result = new List<MushroomZombie>();
					return false;
				}
				if (count > num)
				{
					if (_verboseLogging != null && _verboseLogging.Value)
					{
						Log.LogInfo((object)$"[ZombieCap] Clamp SpawnZombiesAround count in {GetCurrentSegmentName()}: requested={count}, remaining={num}, current={currentZombieCount}, limit={segmentMaxZombies}");
					}
					count = num;
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("PeakZombies_SpawnZombiesAround_Prefix exception: " + ex));
			}
			return true;
		}

		private static void EnsureAKFields(Type gunLaunchType)
		{
			if (!(gunLaunchType == null))
			{
				if (_akCharacterGettingShotField == null)
				{
					_akCharacterGettingShotField = AccessTools.Field(gunLaunchType, "characterGettingShot");
				}
				if (_akShotTimeField == null)
				{
					_akShotTimeField = AccessTools.Field(gunLaunchType, "shotTime");
				}
				if (_akShotDirectionField == null)
				{
					_akShotDirectionField = AccessTools.Field(gunLaunchType, "shotDirection");
				}
			}
		}

		public static bool AKGun_RPC_ShootSelfT_Prefix(object __instance, float howLongToFly, int CharacterViewID, Vector3 whichDirectionShooting)
		{
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (__instance == null)
				{
					return true;
				}
				EnsureAKFields(__instance.GetType());
				Character val = null;
				PhotonView val2 = PhotonView.Find(CharacterViewID);
				if ((Object)(object)val2 != (Object)null)
				{
					Character component = ((Component)val2).GetComponent<Character>();
					if ((Object)(object)component != (Object)null)
					{
						val = component;
					}
					else
					{
						Debug.LogError((object)$"Character {CharacterViewID} not found");
						val = Character.localCharacter;
					}
				}
				else
				{
					Debug.LogError((object)$"PhotonView {CharacterViewID} not found");
					val = Character.localCharacter;
				}
				_akCharacterGettingShotField?.SetValue(__instance, val);
				_akShotTimeField?.SetValue(__instance, howLongToFly);
				_akShotDirectionField?.SetValue(__instance, whichDirectionShooting);
				if ((Object)(object)val != (Object)null)
				{
					Component component2 = ((Component)val).GetComponent(typeof(MushroomZombie));
					MushroomZombie val3 = (MushroomZombie)(object)((component2 is MushroomZombie) ? component2 : null);
					if ((Object)(object)val3 != (Object)null)
					{
						float hitsToKillBySegment = GetHitsToKillBySegment();
						if (_mushroomZombieAchievementTestTickField == null)
						{
							Log.LogError((object)"achievementTestTick field not found");
							return false;
						}
						float num = 0f;
						if (_mushroomZombieAchievementTestTickField.GetValue(val3) is float num2)
						{
							num = num2;
						}
						num += 1f;
						_mushroomZombieAchievementTestTickField.SetValue(val3, num);
						if (_verboseLogging != null && _verboseLogging.Value)
						{
							Log.LogInfo((object)$"[ZombieHit] {GetCurrentSegmentName()}: {num}/{hitsToKillBySegment}");
						}
						if (num >= hitsToKillBySegment)
						{
							Log.LogInfo((object)$"[ZombieKill] {GetCurrentSegmentName()}: zombie killed at {hitsToKillBySegment} hits");
							if (_mushroomZombieDieMethod != null)
							{
								_mushroomZombieDieMethod.Invoke(val3, null);
							}
							else
							{
								Log.LogWarning((object)"Die() not found, fallback to DestroyZombie()");
								val3.DestroyZombie();
							}
						}
					}
				}
				return false;
			}
			catch (Exception ex)
			{
				Log.LogError((object)("AKGun_RPC_ShootSelfT_Prefix exception: " + ex));
				return true;
			}
		}
	}
}
namespace AutoSegmentCycle
{
	[BepInPlugin("com.sol.autosegmentcycle", "Auto Segment Cycle", "1.4.0")]
	public class Plugin : BaseUnityPlugin
	{
		[HarmonyPatch]
		private static class MapHandlerJumpToSegmentLogicPatch
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(typeof(MapHandler), "JumpToSegmentLogic", new Type[4]
				{
					typeof(Segment),
					typeof(HashSet<int>),
					typeof(bool),
					typeof(bool)
				}, (Type[])null);
			}

			private static void Prefix(Segment segment)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					OverrideSpawnPoint(segment);
				}
				catch (Exception ex)
				{
					Log.LogError((object)("[SpawnOverride] Exception: " + ex));
				}
				try
				{
					if (PhotonNetwork.IsMasterClient)
					{
						DestroyAllOwnedZombies();
					}
				}
				catch (Exception ex2)
				{
					Log.LogError((object)("[ZombieCleanup] Exception: " + ex2));
				}
			}

			private static void OverrideSpawnPoint(Segment segment)
			{
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Invalid comparison between Unknown and I4
				//IL_009e: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a0: Expected I4, but got Unknown
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_0065: Unknown result type (might be due to invalid IL or missing references)
				//IL_006a: Unknown result type (might be due to invalid IL or missing references)
				//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
				//IL_021f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0224: Unknown result type (might be due to invalid IL or missing references)
				if (!MapHandler.Exists)
				{
					return;
				}
				MapHandler instance = Singleton<MapHandler>.Instance;
				if ((Object)(object)instance == (Object)null)
				{
					return;
				}
				Vector3 val;
				if ((int)segment == 5)
				{
					if ((Object)(object)instance.respawnThePeak != (Object)null)
					{
						instance.respawnThePeak.position = FinalPeakSpawnPosition;
						ManualLogSource log = Log;
						val = FinalPeakSpawnPosition;
						log.LogInfo((object)("[SpawnOverride] Peak respawnThePeak -> " + ((object)(Vector3)(ref val)).ToString()));
					}
					else
					{
						Log.LogWarning((object)"[SpawnOverride] respawnThePeak is null");
					}
					return;
				}
				int num = (int)segment;
				if (num < 0 || num >= instance.segments.Length)
				{
					Log.LogWarning((object)("[SpawnOverride] Invalid segment index: " + num));
					return;
				}
				MapSegment val2 = instance.segments[num];
				if (val2 == null)
				{
					Log.LogWarning((object)("[SpawnOverride] mapSegment is null for " + ((object)(Segment)(ref segment)).ToString()));
					return;
				}
				if ((Object)(object)val2.segmentCampfire == (Object)null)
				{
					Log.LogWarning((object)("[SpawnOverride] segmentCampfire is null for " + ((object)(Segment)(ref segment)).ToString()));
					return;
				}
				Campfire componentInChildren = val2.segmentCampfire.GetComponentInChildren<Campfire>(true);
				if ((Object)(object)componentInChildren == (Object)null)
				{
					Log.LogWarning((object)("[SpawnOverride] Campfire component not found for " + ((object)(Segment)(ref segment)).ToString()));
					return;
				}
				if ((Object)(object)val2.reconnectSpawnPos == (Object)null)
				{
					Log.LogWarning((object)("[SpawnOverride] reconnectSpawnPos is null for " + ((object)(Segment)(ref segment)).ToString()));
					return;
				}
				val2.reconnectSpawnPos.position = ((Component)componentInChildren).transform.position;
				if (_verboseLogging != null && _verboseLogging.V