Decompiled source of GynxzRepoChallenges v1.2.3

plugins\GynxzRepoChallenges\GynxzRepoChallenges.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using GynxzRepoChallenges.Challenges;
using GynxzRepoChallenges.Network;
using GynxzRepoChallenges.UI;
using HarmonyLib;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("GynxzRepoChallenges")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0")]
[assembly: AssemblyProduct("GynxzRepoChallenges")]
[assembly: AssemblyTitle("GynxzRepoChallenges")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
namespace GynxzRepoChallenges
{
	public static class ChallengeManager
	{
		public static bool NoCrouchActive = false;

		public static bool NoSprintActive = false;

		public static bool NoMapActive = false;

		public static bool NoHealthPackActive = false;

		public static bool NoUpgradesActive = false;

		public static bool CartLeashActive = false;

		public static bool FlawlessActive = false;

		public static bool FrugalActive = false;

		public static bool ExpensiveOnlyActive = false;

		public static bool PacifistActive = false;

		public static bool EmpathyActive = false;

		public static bool NitroFingersActive = false;

		public static bool ShortRangeActive = false;

		public static float ShortRangeOriginalValue = -1f;

		public static float ShortRangeCurrentValue = -1f;

		public static bool InLevel = false;

		public static bool InMapLevel = false;

		private static int _cycleIndex = -1;

		public static int FlawlessViolations = 0;

		public static int CartLeashViolations = 0;

		private static readonly List<Transform> _cartTransforms = new List<Transform>();

		private static float _leashTimer = 0f;

		private const float LEASH_INTERVAL = 1f;

		public static float CartLeashSlowFactor = 0f;

		public static Vector3 NearestCartPos = Vector3.zero;

		public static BaseChallenge ActiveChallenge { get; private set; }

		public static bool AssignById(string id)
		{
			BaseChallenge baseChallenge = ChallengeRegistry.Get(id);
			if (baseChallenge == null)
			{
				Plugin.Log.LogWarning((object)("[ChallengeManager] Unknown challenge id: '" + id + "'"));
				return false;
			}
			Assign(baseChallenge);
			return true;
		}

		public static void AssignRandom()
		{
			Assign(ChallengeRegistry.GetRandom());
		}

		public static void Assign(BaseChallenge challenge)
		{
			if (challenge != null)
			{
				ClearChallenge();
				ActiveChallenge = challenge;
				ResetViolations();
				challenge.Apply();
				Plugin.Log.LogInfo((object)("[ChallengeManager] Challenge assigned → " + challenge.DisplayName));
				ChallengeHUD.Dirty = true;
			}
		}

		public static void ClearChallenge()
		{
			if (ActiveChallenge != null)
			{
				ActiveChallenge.Remove();
				ActiveChallenge = null;
				ResetViolations();
				Plugin.Log.LogInfo((object)"[ChallengeManager] Challenge cleared.");
				ChallengeHUD.Dirty = true;
			}
		}

		public static void CycleChallenge()
		{
			_cycleIndex = (_cycleIndex + 1) % ChallengeRegistry.Count;
			BaseChallenge byIndex = ChallengeRegistry.GetByIndex(_cycleIndex);
			Assign(byIndex);
			Plugin.Log.LogInfo((object)string.Format("[ChallengeManager] Cycled to: {0} (index {1})", byIndex?.DisplayName ?? "none", _cycleIndex));
		}

		public static void OnRoundStart()
		{
			if (!Plugin.Ready)
			{
				Plugin.Log.LogInfo((object)"[ChallengeManager] OnRoundStart — plugin not ready yet, skipping.");
				return;
			}
			Plugin.Log.LogInfo((object)"[ChallengeManager] OnRoundStart triggered.");
			InLevel = true;
			ItemDamagePatch.ClearDestroyedSet();
			HeldItemTicker.OnRoundStart();
			CacheCartPositions();
			Type type = Type.GetType("ValuableObject, Assembly-CSharp");
			Object[] array = ((type != null) ? Object.FindObjectsOfType(type) : null);
			InMapLevel = array != null && array.Length != 0;
			Plugin.Log.LogInfo((object)$"[ChallengeManager] InMapLevel = {InMapLevel} ({((array != null) ? array.Length : 0)} valuables found)");
			if (!InMapLevel)
			{
				Plugin.Log.LogInfo((object)"[ChallengeManager] Not a map level — challenge state unchanged.");
			}
			else if (Plugin.AutoAssignOnRoundStart.Value)
			{
				AssignRandom();
			}
			else if (Plugin.ChallengeScopePerRound.Value && ActiveChallenge != null)
			{
				Plugin.Log.LogInfo((object)"[ChallengeManager] New round — clearing per-round challenge.");
				ClearChallenge();
			}
		}

		public static void OnSceneLoad()
		{
			InLevel = false;
			InMapLevel = false;
			_cartTransforms.Clear();
			_leashTimer = 0f;
			ChallengeHUD.ClearPersistentMessage();
			Plugin.Log.LogInfo((object)"[ChallengeManager] Scene changed — cart leash suspended.");
		}

		private static void CacheCartPositions()
		{
			_cartTransforms.Clear();
			_leashTimer = 0f;
			Type type = Type.GetType("PhysGrabObject, Assembly-CSharp");
			if (type != null)
			{
				FieldInfo field = type.GetField("isCart", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					Component[] array = Object.FindObjectsOfType(type) as Component[];
					bool flag = default(bool);
					foreach (Component val in array)
					{
						if (!((Object)(object)val == (Object)null))
						{
							object value = field.GetValue(val);
							int num;
							if (value is bool)
							{
								flag = (bool)value;
								num = 1;
							}
							else
							{
								num = 0;
							}
							if (((uint)num & (flag ? 1u : 0u)) != 0)
							{
								_cartTransforms.Add(val.transform);
								Plugin.Log.LogInfo((object)("[CartLeash] Cached cart: " + ((Object)val.gameObject).name));
							}
						}
					}
					Plugin.Log.LogInfo((object)$"[CartLeash] {_cartTransforms.Count} cart(s) cached via isCart.");
					return;
				}
			}
			GameObject[] array2 = Object.FindObjectsOfType<GameObject>();
			foreach (GameObject val2 in array2)
			{
				if (!((Object)(object)val2.transform.parent != (Object)null))
				{
					string text = ((Object)val2).name.ToLowerInvariant();
					if (text.Contains("cart") || text.Contains("trolley"))
					{
						_cartTransforms.Add(val2.transform);
						Plugin.Log.LogInfo((object)("[CartLeash] Cached (fallback): " + ((Object)val2).name));
					}
				}
			}
			Plugin.Log.LogInfo((object)$"[CartLeash] {_cartTransforms.Count} cart(s) cached (fallback).");
		}

		public static void CheckCartLeash(Vector3 playerPos)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			if (!CartLeashActive || !InLevel || !InMapLevel)
			{
				CartLeashSlowFactor = 0f;
			}
			else
			{
				if (_cartTransforms.Count == 0)
				{
					return;
				}
				float num = float.MaxValue;
				Vector3 nearestCartPos = Vector3.zero;
				foreach (Transform cartTransform in _cartTransforms)
				{
					if (!((Object)(object)cartTransform == (Object)null))
					{
						float num2 = Vector3.Distance(playerPos, cartTransform.position);
						if (num2 < num)
						{
							num = num2;
							nearestCartPos = cartTransform.position;
						}
					}
				}
				if (num == float.MaxValue)
				{
					return;
				}
				NearestCartPos = nearestCartPos;
				float value = Plugin.CartLeashSlowStartDistance.Value;
				float value2 = Plugin.CartLeashMaxDistance.Value;
				float num3 = (float)Plugin.CartLeashSlowPercent.Value / 100f;
				if (num <= value)
				{
					CartLeashSlowFactor = 0f;
					return;
				}
				if (num >= value2)
				{
					CartLeashSlowFactor = 1f;
				}
				else
				{
					float num4 = (num - value) / (value2 - value);
					CartLeashSlowFactor = Mathf.Lerp(0f, num3, num4);
				}
				if (!(CartLeashSlowFactor < 1f))
				{
					_leashTimer += Time.deltaTime;
					if (!(_leashTimer < 1f))
					{
						_leashTimer = 0f;
						CartLeashViolations++;
						Plugin.Log.LogWarning((object)$"[CartLeash] Too far! {num:F1}u");
						ChallengeHUD.ShowViolation("CART LEASH! Return to cart!");
					}
				}
			}
		}

		public static void OnItemDamaged(string itemName)
		{
			if (FlawlessActive)
			{
				FlawlessViolations++;
				Plugin.Log.LogWarning((object)$"[Flawless] Item damaged: {itemName} (violation #{FlawlessViolations})");
				ChallengeHUD.ShowViolation("FLAWLESS BROKEN! Damaged: " + itemName);
			}
		}

		public static void OnEmpathyHit()
		{
			if (EmpathyActive)
			{
				ChallengeHUD.ShowViolation("EMPATHETIC! -5HP!");
			}
		}

		private static void ResetViolations()
		{
			FlawlessViolations = 0;
			CartLeashViolations = 0;
		}
	}
	public static class Patches
	{
		public static void PatchAll(Harmony harmony)
		{
			PatchPlayerController(harmony);
			PatchMethod(harmony, "MapToolController", "Update", typeof(MapPatch), "Prefix");
			PatchHealthPack(harmony);
			PatchUpgrade(harmony);
			PatchMethod(harmony, "PhysGrabber", "PhysGrabLogic", typeof(GrabPatch), "Prefix");
			PatchItemDamage(harmony);
			PatchShortRange(harmony);
			PatchLevelStart(harmony);
		}

		private static void PatchMethod(Harmony harmony, string typeName, string methodName, Type patchClass, string patchMethodName)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			try
			{
				Type gameType = GetGameType(typeName);
				if (gameType == null)
				{
					Plugin.Log.LogError((object)("[Patches] Type not found: " + typeName));
					return;
				}
				MethodInfo method = gameType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (method == null)
				{
					Plugin.Log.LogError((object)("[Patches] Method not found: " + typeName + "." + methodName));
					return;
				}
				MethodInfo method2 = patchClass.GetMethod(patchMethodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				harmony.Patch((MethodBase)method, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Plugin.Log.LogInfo((object)("[Patches] ✓ " + typeName + "." + methodName + "()"));
				Plugin.Log.LogInfo((object)("[Patches] Applied: " + patchClass.Name));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[Patches] Failed to patch " + typeName + "." + methodName + ": " + ex.Message));
			}
		}

		private static void PatchPlayerController(Harmony harmony)
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Expected O, but got Unknown
			//IL_0097: Expected O, but got Unknown
			try
			{
				Type gameType = GetGameType("PlayerController");
				if (gameType == null)
				{
					Plugin.Log.LogError((object)"[Patches] Type not found: PlayerController");
					return;
				}
				MethodInfo method = gameType.GetMethod("Update", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (method == null)
				{
					Plugin.Log.LogError((object)"[Patches] Method not found: PlayerController.Update");
					return;
				}
				MethodInfo method2 = typeof(PlayerControllerPatch).GetMethod("Prefix", BindingFlags.Static | BindingFlags.Public);
				MethodInfo method3 = typeof(PlayerControllerPatch).GetMethod("Postfix", BindingFlags.Static | BindingFlags.Public);
				harmony.Patch((MethodBase)method, new HarmonyMethod(method2), new HarmonyMethod(method3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Plugin.Log.LogInfo((object)"[Patches] ✓ PlayerController.Update() (prefix + postfix)");
				Plugin.Log.LogInfo((object)"[Patches] Applied: PlayerControllerPatch");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[Patches] Failed to patch PlayerController.Update: " + ex.Message));
			}
		}

		private static void PatchItemDamage(Harmony harmony)
		{
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_00ca: Expected O, but got Unknown
			try
			{
				Type gameType = GetGameType("PhysGrabObjectImpactDetector");
				if (gameType == null)
				{
					Plugin.Log.LogError((object)"[Patches] PhysGrabObjectImpactDetector not found");
					return;
				}
				MethodInfo method = typeof(ItemDamagePatch).GetMethod("Prefix", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				MethodInfo method2 = typeof(ItemDamagePatch).GetMethod("Postfix", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				string[] array = new string[3] { "ImpactHeavy", "ImpactMedium", "ImpactLight" };
				foreach (string text in array)
				{
					MethodInfo method3 = gameType.GetMethod(text, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (method3 == null)
					{
						Plugin.Log.LogWarning((object)("[Patches] " + text + " not found"));
						continue;
					}
					harmony.Patch((MethodBase)method3, new HarmonyMethod(method), new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Plugin.Log.LogInfo((object)("[Patches] ✓ PhysGrabObjectImpactDetector." + text + "()"));
				}
				Plugin.Log.LogInfo((object)"[Patches] Applied: ItemDamagePatch");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[Patches] ItemDamage patch failed: " + ex.Message));
			}
		}

		private static void PatchShortRange(Harmony harmony)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Expected O, but got Unknown
			try
			{
				Type gameType = GetGameType("PhysGrabber");
				if (gameType == null)
				{
					Plugin.Log.LogError((object)"[Patches] PhysGrabber not found for ShortRange");
					return;
				}
				MethodInfo method = gameType.GetMethod("Update", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (method == null)
				{
					Plugin.Log.LogError((object)"[Patches] PhysGrabber.Update not found");
					return;
				}
				MethodInfo method2 = typeof(ShortRangePatch).GetMethod("Postfix", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Plugin.Log.LogInfo((object)"[Patches] ✓ PhysGrabber.Update() (postfix)");
				Plugin.Log.LogInfo((object)"[Patches] Applied: ShortRangePatch");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[Patches] ShortRange patch failed: " + ex.Message));
			}
		}

		private static void PatchLevelStart(Harmony harmony)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			try
			{
				Type gameType = GetGameType("GameDirector");
				if (gameType == null)
				{
					Plugin.Log.LogError((object)"[Patches] GameDirector not found");
					return;
				}
				MethodInfo method = gameType.GetMethod("SetStart", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (method == null)
				{
					Plugin.Log.LogError((object)"[Patches] GameDirector.SetStart not found");
					return;
				}
				HarmonyMethod val = new HarmonyMethod(typeof(LevelStartPatch).GetMethod("Postfix", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic));
				val.priority = 0;
				harmony.Patch((MethodBase)method, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Plugin.Log.LogInfo((object)"[Patches] ✓ GameDirector.SetStart() (Priority.Last)");
				Plugin.Log.LogInfo((object)"[Patches] Applied: LevelStartPatch");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[Patches] LevelStart patch failed: " + ex.Message));
			}
		}

		private static void PatchHealthPack(Harmony harmony)
		{
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Expected O, but got Unknown
			try
			{
				Type gameType = GetGameType("ItemHealthPack");
				if (gameType == null)
				{
					Plugin.Log.LogError((object)"[Patches] ItemHealthPack not found");
					return;
				}
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("[Patches] ItemHealthPack methods:");
				MethodInfo[] methods = gameType.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					string text = string.Join(", ", Array.ConvertAll(methodInfo.GetParameters(), (ParameterInfo p) => p.ParameterType.Name + " " + p.Name));
					stringBuilder.AppendLine("  " + methodInfo.ReturnType.Name + " " + methodInfo.Name + "(" + text + ")");
				}
				Plugin.Log.LogInfo((object)stringBuilder.ToString());
				MethodInfo method = typeof(HealthPackPatch).GetMethod("Prefix", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				int num = 0;
				string[] array = new string[21]
				{
					"Update", "UsedRPC", "Used", "UseItem", "Use", "Interact", "OnInteract", "Activate", "TryUse", "UseLocal",
					"OnUse", "PickUp", "Heal", "HealRPC", "UseHealthPack", "PickupActivate", "ItemActivate", "UseActivate", "SetUsed", "ActivateItem",
					"ApplyHeal"
				};
				foreach (string text2 in array)
				{
					MethodInfo method2 = gameType.GetMethod(text2, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (!(method2 == null))
					{
						harmony.Patch((MethodBase)method2, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						Plugin.Log.LogInfo((object)("[Patches] ✓ ItemHealthPack." + text2 + "()"));
						num++;
					}
				}
				if (num == 0)
				{
					Plugin.Log.LogError((object)"[Patches] No ItemHealthPack methods matched — check dump above");
				}
				Plugin.Log.LogInfo((object)"[Patches] Applied: HealthPackPatch");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[Patches] HealthPack patch failed: " + ex.Message));
			}
		}

		private static void PatchUpgrade(Harmony harmony)
		{
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Expected O, but got Unknown
			try
			{
				Type gameType = GetGameType("ItemUpgrade");
				if (gameType == null)
				{
					Plugin.Log.LogError((object)"[Patches] ItemUpgrade not found");
					return;
				}
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("[Patches] ItemUpgrade methods:");
				MethodInfo[] methods = gameType.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					string text = string.Join(", ", Array.ConvertAll(methodInfo.GetParameters(), (ParameterInfo p) => p.ParameterType.Name + " " + p.Name));
					stringBuilder.AppendLine("  " + methodInfo.ReturnType.Name + " " + methodInfo.Name + "(" + text + ")");
				}
				Plugin.Log.LogInfo((object)stringBuilder.ToString());
				MethodInfo method = typeof(UpgradePatch).GetMethod("Prefix", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				int num = 0;
				string[] array = new string[12]
				{
					"ButtonToggle", "PlayerUpgrade", "Interact", "Use", "Toggle", "UpgradePlayer", "PressButton", "Purchase", "Buy", "OnInteract",
					"Activate", "Press"
				};
				foreach (string text2 in array)
				{
					MethodInfo method2 = gameType.GetMethod(text2, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (!(method2 == null))
					{
						harmony.Patch((MethodBase)method2, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						Plugin.Log.LogInfo((object)("[Patches] ✓ ItemUpgrade." + text2 + "()"));
						num++;
					}
				}
				if (num == 0)
				{
					Plugin.Log.LogError((object)"[Patches] No ItemUpgrade methods matched — check dump above");
				}
				Plugin.Log.LogInfo((object)"[Patches] Applied: UpgradePatch");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[Patches] Upgrade patch failed: " + ex.Message));
			}
		}

		private static Type GetGameType(string name)
		{
			return Type.GetType(name + ", Assembly-CSharp");
		}
	}
	public static class PlayerControllerPatch
	{
		public static void Prefix(object __instance)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			Plugin.EnsureUpdaterCreated();
			try
			{
				if (ChallengeManager.CartLeashActive)
				{
					Component val = (Component)((__instance is Component) ? __instance : null);
					if ((Object)(object)val != (Object)null)
					{
						ChallengeManager.CheckCartLeash(val.transform.position);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[PlayerControllerPatch.Prefix] " + ex.Message));
			}
		}

		public static void Postfix(object __instance)
		{
			//IL_00ca: 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_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: 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_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Type type = __instance.GetType();
				if (ChallengeManager.NoCrouchActive && ChallengeManager.InMapLevel)
				{
					SetBool(__instance, type, "Crouching", val: false);
					SetBool(__instance, type, "Crawling", val: false);
					SetBool(__instance, type, "toggleCrouch", val: false);
					SetBool(__instance, type, "previousCrouchingState", val: false);
					SetBool(__instance, type, "previousCrawlingState", val: false);
				}
				if (ChallengeManager.NoSprintActive && ChallengeManager.InMapLevel)
				{
					SetBool(__instance, type, "sprinting", val: false);
					SetBool(__instance, type, "toggleSprint", val: false);
					SetBool(__instance, type, "previousSprintingState", val: false);
					SetFloat(__instance, type, "SprintSpeedLerp", 0f);
				}
				float cartLeashSlowFactor = ChallengeManager.CartLeashSlowFactor;
				if (!ChallengeManager.CartLeashActive || !(cartLeashSlowFactor > 0f))
				{
					return;
				}
				Component val = (Component)((__instance is Component) ? __instance : null);
				if (!((Object)(object)val != (Object)null))
				{
					return;
				}
				Vector3 val2 = ChallengeManager.NearestCartPos - val.transform.position;
				val2.y = 0f;
				float magnitude = ((Vector3)(ref val2)).magnitude;
				float value = Plugin.CartLeashMaxDistance.Value;
				if (cartLeashSlowFactor >= 1f && magnitude > value && magnitude > 0.001f)
				{
					Vector3 position = ChallengeManager.NearestCartPos - ((Vector3)(ref val2)).normalized * value;
					position.y = val.transform.position.y;
					val.transform.position = position;
				}
				else
				{
					if (!(cartLeashSlowFactor > 0f) || !(cartLeashSlowFactor < 1f) || !(magnitude > 0.001f))
					{
						return;
					}
					Rigidbody component = val.GetComponent<Rigidbody>();
					if ((Object)(object)component != (Object)null)
					{
						Vector3 normalized = ((Vector3)(ref val2)).normalized;
						Vector3 velocity = component.velocity;
						Vector3 val3 = default(Vector3);
						((Vector3)(ref val3))..ctor(velocity.x, 0f, velocity.z);
						float num = Vector3.Dot(val3, -normalized);
						if (num > 0f)
						{
							val3 -= -normalized * num * cartLeashSlowFactor;
							component.velocity = new Vector3(val3.x, velocity.y, val3.z);
						}
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[PlayerControllerPatch.Postfix] " + ex.Message));
			}
		}

		private static void SetBool(object inst, Type t, string name, bool val)
		{
			t.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(inst, val);
		}

		private static void SetFloat(object inst, Type t, string name, float val)
		{
			t.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(inst, val);
		}
	}
	public static class MapPatch
	{
		public static bool Prefix()
		{
			if (ChallengeManager.NoMapActive)
			{
				return !ChallengeManager.InMapLevel;
			}
			return true;
		}
	}
	public static class HealthPackPatch
	{
		public static bool Prefix()
		{
			if (!ChallengeManager.NoHealthPackActive)
			{
				return true;
			}
			ChallengeHUD.ShowViolation("NO HEALTH PACK! Challenge active!");
			return false;
		}
	}
	public static class UpgradePatch
	{
		public static bool Prefix(MethodBase __originalMethod, object[] __args)
		{
			if (!ChallengeManager.NoUpgradesActive)
			{
				return true;
			}
			if (__originalMethod?.Name == "PlayerUpgrade" && __args != null && __args.Length != 0)
			{
				try
				{
					object obj = __args[0];
					object obj2 = obj?.GetType().GetProperty("Sender")?.GetValue(obj);
					if (obj2?.GetType().GetProperty("IsLocal")?.GetValue(obj2) as bool? == false)
					{
						return true;
					}
				}
				catch
				{
				}
			}
			Plugin.Log.LogInfo((object)("[UpgradePatch] Blocked: " + __originalMethod?.Name));
			ChallengeHUD.ShowViolation("NO UPGRADES! Challenge active!");
			return false;
		}
	}
	public static class GrabPatch
	{
		private static readonly HashSet<int> _violatedItems = new HashSet<int>();

		private static bool _disengageDumped = false;

		private static bool _weaponDumped = false;

		public static bool Prefix(object __instance)
		{
			bool flag = ChallengeManager.FrugalActive && ChallengeManager.InMapLevel;
			bool flag2 = ChallengeManager.ExpensiveOnlyActive && ChallengeManager.InMapLevel;
			bool pacifistActive = ChallengeManager.PacifistActive;
			if (!flag && !flag2 && !pacifistActive)
			{
				return true;
			}
			try
			{
				GameObject grabbedObject = GetGrabbedObject(__instance);
				if ((Object)(object)grabbedObject == (Object)null)
				{
					return true;
				}
				int instanceID = ((Object)grabbedObject).GetInstanceID();
				if (flag || flag2)
				{
					int itemValue = GetItemValue(grabbedObject);
					if (itemValue >= 0)
					{
						int value = Plugin.ExpensiveItemThreshold.Value;
						if ((!flag || itemValue < value) && (!flag2 || itemValue >= value))
						{
							_violatedItems.Remove(instanceID);
						}
						else
						{
							if (_violatedItems.Add(instanceID))
							{
								string text = (ChallengeManager.FrugalActive ? $"FRUGAL: Too expensive! (${itemValue})" : $"EXPENSIVE ONLY: Too cheap! (${itemValue})");
								Plugin.Log.LogInfo((object)("[GrabPatch] " + text));
								ChallengeHUD.ShowViolation(text);
							}
							ForceRelease(__instance);
						}
					}
				}
				if (pacifistActive && IsWeapon(grabbedObject))
				{
					if (_violatedItems.Add(instanceID))
					{
						Plugin.Log.LogInfo((object)("[GrabPatch] PACIFIST: weapon grab blocked (" + ((Object)grabbedObject).name + ")"));
						ChallengeHUD.ShowViolation("PACIFIST! No weapons!");
					}
					ForceRelease(__instance);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[GrabPatch] " + ex.Message));
			}
			return true;
		}

		private static void ForceRelease(object grabber)
		{
			try
			{
				Type type = grabber.GetType();
				FieldInfo field = type.GetField("grabbedPhysGrabObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				MethodInfo methodInfo = null;
				MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo2 in methods)
				{
					if (methodInfo2.Name == "disengagePhysGrabObject")
					{
						methodInfo = methodInfo2;
						break;
					}
				}
				if (methodInfo != null)
				{
					ParameterInfo[] parameters = methodInfo.GetParameters();
					if (!_disengageDumped)
					{
						_disengageDumped = true;
						string text = string.Join(", ", Array.ConvertAll(parameters, (ParameterInfo p) => p.ParameterType.Name + " " + p.Name));
						Plugin.Log.LogInfo((object)("[GrabPatch] disengagePhysGrabObject(" + text + ")"));
					}
					if (parameters.Length == 0)
					{
						methodInfo.Invoke(grabber, null);
						return;
					}
					if (parameters.Length == 1)
					{
						object obj = field?.GetValue(grabber);
						methodInfo.Invoke(grabber, new object[1] { obj });
						return;
					}
				}
				field?.SetValue(grabber, null);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[ForceRelease] " + ex.GetType().Name + ": " + ex.Message));
			}
		}

		private static GameObject GetGrabbedObject(object grabber)
		{
			Type type = grabber.GetType();
			string[] array = new string[5] { "grabbedPhysGrabObject", "physGrabObject", "grabObject", "currentGrabObject", "grabbedObject" };
			foreach (string name in array)
			{
				FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (!(field == null))
				{
					object value = field.GetValue(grabber);
					Component val = (Component)((value is Component) ? value : null);
					if (val != null)
					{
						return val.gameObject;
					}
					GameObject val2 = (GameObject)((value is GameObject) ? value : null);
					if (val2 != null)
					{
						return val2;
					}
				}
			}
			return null;
		}

		private static int GetItemValue(GameObject go)
		{
			Type type = Type.GetType("ValuableObject, Assembly-CSharp");
			if (type == null)
			{
				return -1;
			}
			Component component = go.GetComponent(type);
			if ((Object)(object)component == (Object)null)
			{
				return -1;
			}
			FieldInfo field = type.GetField("dollarValueCurrent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				object value = field.GetValue(component);
				if (value is float num)
				{
					return (int)num;
				}
				if (value is int)
				{
					return (int)value;
				}
			}
			return -1;
		}

		private static bool IsWeapon(GameObject go)
		{
			string[] array = new string[9] { "ItemGun", "ItemWeapon", "ItemMelee", "ItemRevolver", "ItemShotgun", "ItemRifle", "ItemCrossbow", "ItemGrenade", "ItemGrenadeStun" };
			for (int i = 0; i < array.Length; i++)
			{
				Type type = Type.GetType(array[i] + ", Assembly-CSharp");
				if (type != null && (Object)(object)go.GetComponent(type) != (Object)null)
				{
					return true;
				}
			}
			if (!_weaponDumped)
			{
				_weaponDumped = true;
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("[GrabPatch] Components on '" + ((Object)go).name + "' (pacifist dump):");
				Component[] components = go.GetComponents<Component>();
				for (int i = 0; i < components.Length; i++)
				{
					stringBuilder.AppendLine("  " + ((object)components[i])?.GetType().Name);
				}
				Plugin.Log.LogInfo((object)stringBuilder.ToString());
			}
			return false;
		}
	}
	public static class ItemDamagePatch
	{
		private static readonly HashSet<int> _warnedThisRound = new HashSet<int>();

		private static bool _playerDamageDumped = false;

		private static bool _explosionDumped = false;

		private static bool _prefixWasHeld = false;

		private static float _flawlessLastBreak = -10f;

		private static float _empathyNextHit = 0f;

		private static float _nitroLastExplosion = -10f;

		public static void ClearDestroyedSet()
		{
			_warnedThisRound.Clear();
		}

		public static bool Prefix(object __instance, MethodBase __originalMethod, ref float __state)
		{
			__state = -1f;
			_prefixWasHeld = false;
			if (__originalMethod?.Name != "ImpactHeavy")
			{
				return true;
			}
			if ((!ChallengeManager.FlawlessActive && !ChallengeManager.NitroFingersActive && !ChallengeManager.EmpathyActive) || !ChallengeManager.InMapLevel)
			{
				return true;
			}
			try
			{
				Type type = __instance.GetType();
				object? obj = type.GetField("physGrabObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(__instance);
				Component val = (Component)((obj is Component) ? obj : null);
				if ((Object)(object)val == (Object)null)
				{
					return true;
				}
				object obj2 = ((object)val).GetType().GetField("isValuable", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(val);
				bool flag = default(bool);
				int num;
				if (obj2 is bool)
				{
					flag = (bool)obj2;
					num = 1;
				}
				else
				{
					num = 0;
				}
				if (((uint)num & (flag ? 1u : 0u)) == 0)
				{
					return true;
				}
				if (!(_prefixWasHeld = IsHeldByLocalPlayer(val)))
				{
					return true;
				}
				if (ChallengeManager.FlawlessActive)
				{
					int instanceID = ((Object)val.gameObject).GetInstanceID();
					if (_warnedThisRound.Add(instanceID))
					{
						float time = Time.time;
						if (time - _flawlessLastBreak >= 0.3f)
						{
							_flawlessLastBreak = time;
							DestroyValuable(__instance, type, val);
							Plugin.Log.LogWarning((object)("[Flawless] Destroyed " + ((Object)val.gameObject).name));
							ChallengeManager.OnItemDamaged(((Object)val.gameObject).name);
						}
					}
					return false;
				}
				__state = 1f;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[ItemDamagePatch.Prefix] " + ex.Message));
			}
			return true;
		}

		public static void Postfix(object __instance, MethodBase __originalMethod, float __state)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			if (!_prefixWasHeld || __state < 0f || __originalMethod?.Name != "ImpactHeavy")
			{
				return;
			}
			try
			{
				object? obj = __instance.GetType().GetField("physGrabObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(__instance);
				Component val = (Component)((obj is Component) ? obj : null);
				Vector3 val2 = (((Object)(object)val != (Object)null) ? val.transform.position : Vector3.zero);
				if (ChallengeManager.NitroFingersActive)
				{
					float time = Time.time;
					if (time - _nitroLastExplosion >= 0.5f)
					{
						_nitroLastExplosion = time;
						TrySpawnExplosion(val2);
						if ((Object)(object)val != (Object)null)
						{
							ChallengeHUD.ShowViolation("BOOM! " + ((Object)val.gameObject).name);
						}
						Plugin.Log.LogInfo((object)$"[NitroFingers] Explosion at {val2}");
					}
				}
				if (ChallengeManager.EmpathyActive && Time.time >= _empathyNextHit)
				{
					_empathyNextHit = Time.time + 0.5f;
					DamageLocalPlayer(5f);
					ChallengeManager.OnEmpathyHit();
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[ItemDamagePatch.Postfix] " + ex.Message));
			}
		}

		private static void DestroyValuable(object detector, Type detType, Component pg)
		{
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			MethodInfo method = detType.GetMethod("DestroyObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(bool) }, null);
			if (method != null)
			{
				try
				{
					method.Invoke(detector, new object[1] { true });
					return;
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("[Flawless] DestroyObject threw: " + ex.Message));
				}
			}
			MethodInfo method2 = detType.GetMethod("Break", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[4]
			{
				typeof(float),
				typeof(Vector3),
				typeof(int),
				typeof(bool)
			}, null);
			if (method2 != null)
			{
				try
				{
					method2.Invoke(detector, new object[4]
					{
						999999f,
						pg.transform.position,
						0,
						true
					});
					return;
				}
				catch (Exception ex2)
				{
					Plugin.Log.LogWarning((object)("[Flawless] Break() threw: " + ex2.Message));
				}
			}
			try
			{
				Object.Destroy((Object)(object)pg.gameObject);
			}
			catch (Exception ex3)
			{
				Plugin.Log.LogWarning((object)("[Flawless] GameObject destroy threw: " + ex3.Message));
			}
		}

		internal static void TrySpawnExplosion(Vector3 pos)
		{
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			string[] array = new string[6] { "Explosion", "ExplosionCustom", "ExplosionManager", "GrenadeBoom", "GrenadeExplosion", "ItemExplosion" };
			foreach (string text in array)
			{
				Type type = Type.GetType(text + ", Assembly-CSharp");
				if (type == null)
				{
					continue;
				}
				MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					if (methodInfo.Name != "Spawn" && methodInfo.Name != "Create" && methodInfo.Name != "SpawnExplosion" && methodInfo.Name != "CreateExplosion" && methodInfo.Name != "Explode")
					{
						continue;
					}
					ParameterInfo[] parameters = methodInfo.GetParameters();
					if (parameters.Length != 0 && !(parameters[0].ParameterType != typeof(Vector3)))
					{
						try
						{
							methodInfo.Invoke(null, (parameters.Length != 1) ? new object[2] { pos, 10f } : new object[1] { pos });
							Plugin.Log.LogInfo((object)("[Flawless] Explosion via " + text + "." + methodInfo.Name + "()"));
							return;
						}
						catch (Exception ex)
						{
							Plugin.Log.LogWarning((object)("[Flawless] " + text + "." + methodInfo.Name + " threw: " + ex.Message));
						}
					}
				}
			}
			Collider[] array2 = Physics.OverlapSphere(pos, 3f);
			int num = 0;
			Collider[] array3 = array2;
			foreach (Collider val in array3)
			{
				if (!((Object)(object)val == (Object)null))
				{
					Rigidbody attachedRigidbody = val.attachedRigidbody;
					if ((Object)(object)attachedRigidbody != (Object)null && !attachedRigidbody.isKinematic)
					{
						attachedRigidbody.AddExplosionForce(600f, pos, 3f, 1f, (ForceMode)1);
						num++;
					}
				}
			}
			if (num > 0)
			{
				Plugin.Log.LogInfo((object)$"[Flawless] Physics explosion — pushed {num} rigidbodies");
			}
			else
			{
				if (_explosionDumped)
				{
					return;
				}
				_explosionDumped = true;
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("[Flawless] No explosion API found. Explosion-related types in Assembly-CSharp:");
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					if (assembly.GetName().Name != "Assembly-CSharp")
					{
						continue;
					}
					Type[] types = assembly.GetTypes();
					foreach (Type type2 in types)
					{
						string text2 = type2.Name.ToLowerInvariant();
						if (text2.Contains("explo") || text2.Contains("boom") || text2.Contains("blast") || text2.Contains("detonat") || text2.Contains("grenade"))
						{
							stringBuilder.AppendLine("  " + type2.Name);
						}
					}
					break;
				}
				Plugin.Log.LogInfo((object)stringBuilder.ToString());
			}
		}

		private static float ReadItemDollarValue(object impactDetector)
		{
			try
			{
				Component val = (Component)((impactDetector is Component) ? impactDetector : null);
				if ((Object)(object)val == (Object)null)
				{
					return -1f;
				}
				Type type = Type.GetType("ValuableObject, Assembly-CSharp");
				if (type == null)
				{
					return -1f;
				}
				Transform val2 = val.transform;
				while ((Object)(object)val2.parent != (Object)null)
				{
					val2 = val2.parent;
				}
				Component componentInChildren = ((Component)val2).GetComponentInChildren(type);
				if ((Object)(object)componentInChildren == (Object)null)
				{
					return -1f;
				}
				FieldInfo field = type.GetField("dollarValueCurrent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field == null)
				{
					return -1f;
				}
				object value = field.GetValue(componentInChildren);
				if (value is float result)
				{
					return result;
				}
				if (value is int)
				{
					int num = (int)value;
					return num;
				}
			}
			catch
			{
			}
			return -1f;
		}

		private static bool IsHeldByLocalPlayer(Component physGrabObject)
		{
			try
			{
				Type type = Type.GetType("PhysGrabber, Assembly-CSharp");
				if (type == null)
				{
					return false;
				}
				FieldInfo field = type.GetField("grabbedPhysGrabObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field == null)
				{
					return false;
				}
				FieldInfo field2 = type.GetField("isLocal", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				Component[] array = Object.FindObjectsOfType(type) as Component[];
				foreach (Component val in array)
				{
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					if (field2 != null)
					{
						object value = field2.GetValue(val);
						if (value is bool && !(bool)value)
						{
							continue;
						}
					}
					object? value2 = field.GetValue(val);
					Component val2 = (Component)((value2 is Component) ? value2 : null);
					if ((Object)(object)val2 != (Object)null && (Object)(object)val2 == (Object)(object)physGrabObject)
					{
						return true;
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[IsHeldByLocalPlayer] " + ex.Message));
			}
			return false;
		}

		internal static void DamageLocalPlayer(float amount)
		{
			try
			{
				Type type = Type.GetType("PlayerAvatar, Assembly-CSharp");
				if (type == null)
				{
					Plugin.Log.LogWarning((object)"[Empathy] PlayerAvatar type not found");
					return;
				}
				FieldInfo field = type.GetField("isLocal", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				Component val = null;
				Component[] array = Object.FindObjectsOfType(type) as Component[];
				foreach (Component val2 in array)
				{
					if ((Object)(object)val2 == (Object)null)
					{
						continue;
					}
					if (field != null)
					{
						object value = field.GetValue(val2);
						if (value is bool && !(bool)value)
						{
							continue;
						}
					}
					val = val2;
					break;
				}
				if ((Object)(object)val == (Object)null)
				{
					Plugin.Log.LogWarning((object)"[Empathy] Local PlayerAvatar not found");
					return;
				}
				array = val.gameObject.GetComponents<Component>();
				foreach (Component val3 in array)
				{
					if ((Object)(object)val3 == (Object)null)
					{
						continue;
					}
					Type type2 = ((object)val3).GetType();
					if (!_playerDamageDumped)
					{
						_playerDamageDumped = true;
						StringBuilder stringBuilder = new StringBuilder();
						stringBuilder.AppendLine("[Empathy] All components on local player GO:");
						Component[] components = val.gameObject.GetComponents<Component>();
						foreach (Component val4 in components)
						{
							if ((Object)(object)val4 == (Object)null)
							{
								continue;
							}
							stringBuilder.AppendLine("  [" + ((object)val4).GetType().Name + "]");
							MethodInfo[] methods = ((object)val4).GetType().GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
							foreach (MethodInfo methodInfo in methods)
							{
								string text = string.Join(", ", Array.ConvertAll(methodInfo.GetParameters(), (ParameterInfo p) => p.ParameterType.Name));
								stringBuilder.AppendLine("    " + methodInfo.Name + "(" + text + ")");
							}
						}
						Plugin.Log.LogInfo((object)stringBuilder.ToString());
					}
					string[] array2 = new string[7] { "HurtLocal", "Hurt", "TakeDamage", "DealDamage", "HurtPlayer", "ApplyDamage", "Damage" };
					foreach (string text2 in array2)
					{
						MethodInfo method = type2.GetMethod(text2, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(float) }, null);
						if (method != null)
						{
							method.Invoke(val3, new object[1] { amount });
							Plugin.Log.LogInfo((object)$"[Empathy] -{amount}hp via {type2.Name}.{text2}(float)");
							return;
						}
						method = type2.GetMethod(text2, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(int) }, null);
						if (method != null)
						{
							method.Invoke(val3, new object[1] { (int)amount });
							Plugin.Log.LogInfo((object)$"[Empathy] -{amount}hp via {type2.Name}.{text2}(int)");
							return;
						}
					}
					array2 = new string[7] { "health", "hp", "currentHealth", "playerHealth", "hitPoints", "HP", "maxHealth" };
					foreach (string text3 in array2)
					{
						FieldInfo field2 = type2.GetField(text3, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						if (!(field2 == null))
						{
							object value2 = field2.GetValue(val3);
							if (value2 is float num)
							{
								field2.SetValue(val3, Mathf.Max(0f, num - amount));
								Plugin.Log.LogInfo((object)$"[Empathy] -{amount}hp via field {type2.Name}.{text3}");
								return;
							}
							if (value2 is int num2)
							{
								field2.SetValue(val3, Mathf.Max(0, num2 - (int)amount));
								Plugin.Log.LogInfo((object)$"[Empathy] -{amount}hp via field {type2.Name}.{text3}");
								return;
							}
						}
					}
				}
				Plugin.Log.LogWarning((object)"[Empathy] No damage method/field found — check log dump above");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[DamageLocalPlayer] " + ex.Message));
			}
		}
	}
	public static class ShortRangePatch
	{
		private const string RANGE_FIELD = "grabRange";

		private static float _originalRange = -1f;

		private static float _preChallengeRange = -1f;

		private static float _targetRange = -1f;

		private static bool _challengeWasActive = false;

		public static void Postfix(object __instance)
		{
			try
			{
				Type type = __instance.GetType();
				FieldInfo field = type.GetField("isLocal", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					object value = field.GetValue(__instance);
					if (value is bool && !(bool)value)
					{
						return;
					}
				}
				FieldInfo field2 = type.GetField("grabRange", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field2 == null)
				{
					return;
				}
				float num = (float)field2.GetValue(__instance);
				if (_originalRange < 0f)
				{
					_originalRange = num;
					ChallengeManager.ShortRangeOriginalValue = num;
					Plugin.Log.LogInfo((object)string.Format("[ShortRange] Base grab range = {0:F2} (field: {1})", num, "grabRange"));
				}
				bool shortRangeActive = ChallengeManager.ShortRangeActive;
				if (!shortRangeActive)
				{
					ChallengeManager.ShortRangeCurrentValue = num;
				}
				if (!shortRangeActive)
				{
					if (_challengeWasActive)
					{
						_challengeWasActive = false;
						if (_preChallengeRange >= 0f)
						{
							field2.SetValue(__instance, _preChallengeRange);
						}
						Plugin.Log.LogInfo((object)$"[ShortRange] Ended — range restored to {_preChallengeRange:F2}");
						_targetRange = -1f;
						_preChallengeRange = -1f;
					}
					return;
				}
				if (!_challengeWasActive)
				{
					_challengeWasActive = true;
					_preChallengeRange = num;
					float num2 = (float)Plugin.ShortRangeReductionPercent.Value / 100f;
					_targetRange = (Plugin.ShortRangeUseOriginal.Value ? _originalRange : num) * (1f - num2);
					Plugin.Log.LogInfo((object)($"[ShortRange] Activated — original={_originalRange:F2} " + $"current={num:F2} useOriginal={Plugin.ShortRangeUseOriginal.Value} " + $"reduction={num2 * 100f:F0}% target={_targetRange:F2}"));
				}
				if (num != _targetRange)
				{
					field2.SetValue(__instance, _targetRange);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[ShortRangePatch] " + ex.Message));
			}
		}
	}
	public static class LevelStartPatch
	{
		public static void Postfix()
		{
			try
			{
				Plugin.Log.LogInfo((object)"[LevelStartPatch] GameDirector.SetStart fired.");
				ChallengeManager.OnRoundStart();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[LevelStartPatch] FAILED: " + ex.Message + "\n" + ex.StackTrace));
			}
		}
	}
	internal static class HeldItemTicker
	{
		public static void Tick()
		{
		}

		public static void OnRoundStart()
		{
		}

		public static void OnSceneLoad()
		{
		}
	}
	[BepInPlugin("com.gynxz.repochallenges", "Gynxz: RepoChallenges", "1.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string GUID = "com.gynxz.repochallenges";

		public const string MOD_NAME = "Gynxz: RepoChallenges";

		public const string VERSION = "1.1.0";

		internal static ManualLogSource Log;

		internal static Plugin Instance;

		internal static bool Ready = false;

		internal static bool UpdaterCreated = false;

		internal static ConfigEntry<bool> DebugKeysEnabled;

		internal static ConfigEntry<KeyboardShortcut> CycleKey;

		internal static ConfigEntry<KeyboardShortcut> ClearKey;

		internal static ConfigEntry<bool> ChallengeScopePerRound;

		internal static ConfigEntry<float> CartLeashMaxDistance;

		internal static ConfigEntry<float> CartLeashSlowStartDistance;

		internal static ConfigEntry<int> CartLeashSlowPercent;

		internal static ConfigEntry<int> ExpensiveItemThreshold;

		internal static ConfigEntry<bool> EnableNetworkSync;

		internal static ConfigEntry<bool> AutoAssignOnRoundStart;

		internal static ConfigEntry<bool> ShortRangeUseOriginal;

		internal static ConfigEntry<int> ShortRangeReductionPercent;

		internal static ConfigEntry<bool> HudEnabled;

		internal static ConfigEntry<int> HudPositionX;

		internal static ConfigEntry<int> HudPositionY;

		internal static ConfigEntry<int> HudFontSize;

		internal static ConfigEntry<bool> HudShowDescription;

		internal static ConfigEntry<bool> HudShowOtherPlayers;

		internal static ConfigEntry<bool> SbEnabled;

		private static readonly string BASE_PATH = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Thunderstore Mod Manager\\DataFolder\\REPO\\profiles\\REPO");

		public static readonly string CMD_FILE = Path.Combine(BASE_PATH, "challenge_cmd.txt");

		public static readonly string STATUS_FILE = Path.Combine(BASE_PATH, "challenge_status.txt");

		public static readonly string LIST_FILE = Path.Combine(BASE_PATH, "challenge_list.txt");

		public static readonly string PLAYERS_FILE = Path.Combine(BASE_PATH, "challenge_players.txt");

		public static readonly string IDS_FILE = Path.Combine(BASE_PATH, "challenge_ids.txt");

		private Harmony _harmony;

		private float _pollTimer;

		private string _lastCmd = "";

		private bool _updateOnce;

		private const float POLL_INTERVAL = 0.5f;

		private void Awake()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			try
			{
				Instance = this;
				Log = ((BaseUnityPlugin)this).Logger;
				BindConfig();
				Log.LogInfo((object)"[Plugin] Config bound.");
				ChallengeRegistry.RegisterAll();
				Log.LogInfo((object)("[Plugin] Registered: " + string.Join(", ", ChallengeRegistry.AllIds())));
				_harmony = new Harmony("com.gynxz.repochallenges");
				Patches.PatchAll(_harmony);
				Log.LogInfo((object)"[Plugin] Patches applied.");
				if (SbEnabled.Value)
				{
					WriteListFile();
					TryClearCmd();
					WriteStatus();
					Log.LogInfo((object)("[Plugin] File bridge ready. CMD: " + CMD_FILE));
				}
				Ready = true;
				Log.LogInfo((object)"Gynxz: RepoChallenges v1.1.0 ready.");
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogError((object)("[Plugin] Awake() FAILED: " + ex.Message + "\n" + ex.StackTrace));
				}
			}
		}

		private void OnDestroy()
		{
			Log.LogWarning((object)"[Plugin] OnDestroy() — BepInEx lifecycle, ignoring.");
		}

		private void Update()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			if (!Ready)
			{
				return;
			}
			if (!_updateOnce)
			{
				_updateOnce = true;
				Log.LogInfo((object)"[Plugin] Update() is alive.");
			}
			if (DebugKeysEnabled.Value)
			{
				KeyboardShortcut value = CycleKey.Value;
				if (IsKeyDown(((KeyboardShortcut)(ref value)).MainKey))
				{
					Log.LogInfo((object)"[Plugin] Cycle key pressed.");
					ChallengeManager.CycleChallenge();
				}
				value = ClearKey.Value;
				if (IsKeyDown(((KeyboardShortcut)(ref value)).MainKey))
				{
					Log.LogInfo((object)"[Plugin] Clear key pressed.");
					ChallengeManager.ClearChallenge();
				}
			}
			if (!SbEnabled.Value)
			{
				return;
			}
			_pollTimer += Time.unscaledDeltaTime;
			if (_pollTimer < 0.5f)
			{
				return;
			}
			_pollTimer = 0f;
			try
			{
				if (File.Exists(CMD_FILE))
				{
					string text = File.ReadAllText(CMD_FILE);
					string text2 = ((text == null) ? "" : text.Trim().ToLowerInvariant());
					if (!string.IsNullOrEmpty(text2) && !(text2 == _lastCmd))
					{
						_lastCmd = text2;
						File.WriteAllText(CMD_FILE, "");
						Log.LogInfo((object)("[Plugin] Command received: '" + text2 + "'"));
						ExecuteCommand(text2);
					}
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("[Plugin] Poll error: " + ex.Message));
			}
		}

		private void ExecuteCommand(string cmd)
		{
			string targetName = ParseField(cmd, "player:");
			if (cmd == "clear" || cmd.Contains(",clear") || cmd.StartsWith("clear,"))
			{
				ChallengeSync.SendClear(targetName);
			}
			else if (cmd == "random")
			{
				ChallengeSync.SendChallenge(targetName, ChallengeRegistry.GetRandom()?.Id ?? "");
			}
			else
			{
				string text = ParseField(cmd, "challenge:") ?? cmd;
				if (!ChallengeRegistry.Has(text))
				{
					Log.LogWarning((object)("[Plugin] Unknown challenge id: '" + text + "'"));
				}
				else
				{
					ChallengeSync.SendChallenge(targetName, text);
				}
			}
			WriteStatus();
		}

		internal static string ParseField(string cmd, string key)
		{
			int num = cmd.IndexOf(key, StringComparison.Ordinal);
			if (num < 0)
			{
				return null;
			}
			return cmd.Substring(num + key.Length).Split(new char[1] { ',' })[0].Trim();
		}

		private void WriteListFile()
		{
			try
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("# Valid challenge ids — write one to: " + CMD_FILE);
				stringBuilder.AppendLine("# Special commands: clear, random");
				stringBuilder.AppendLine();
				foreach (BaseChallenge item in ChallengeRegistry.All)
				{
					stringBuilder.AppendLine($"{item.Id,-20} # {item.DisplayName}");
				}
				File.WriteAllText(LIST_FILE, stringBuilder.ToString());
				StringBuilder stringBuilder2 = new StringBuilder();
				foreach (BaseChallenge item2 in ChallengeRegistry.All)
				{
					stringBuilder2.AppendLine(item2.Id);
				}
				File.WriteAllText(IDS_FILE, stringBuilder2.ToString());
			}
			catch (Exception ex)
			{
				Log.LogError((object)("[Plugin] WriteListFile: " + ex.Message));
			}
		}

		public static void WriteStatus()
		{
			try
			{
				BaseChallenge activeChallenge = ChallengeManager.ActiveChallenge;
				string contents = ((activeChallenge == null) ? "active: none" : ("active: " + activeChallenge.Id + " | " + activeChallenge.DisplayName));
				File.WriteAllText(STATUS_FILE, contents);
			}
			catch
			{
			}
		}

		private static void TryClearCmd()
		{
			try
			{
				File.WriteAllText(CMD_FILE, "");
			}
			catch
			{
			}
		}

		internal static void EnsureUpdaterCreated()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			//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_002a: Expected O, but got Unknown
			if (UpdaterCreated)
			{
				return;
			}
			UpdaterCreated = true;
			try
			{
				if (HudEnabled.Value)
				{
					GameObject val = new GameObject("GynxzChallengeHUD");
					Object.DontDestroyOnLoad((Object)val);
					val.AddComponent<ChallengeHUD>();
					Log.LogInfo((object)"[Plugin] HUD created from gameplay context.");
				}
				GameObject val2 = new GameObject("GynxzChallengeUpdater_Live");
				Object.DontDestroyOnLoad((Object)val2);
				val2.AddComponent<ChallengeUpdater>();
				Log.LogInfo((object)"[Plugin] Updater created from gameplay context.");
				ChallengeSync.Create();
				Log.LogInfo((object)"[Plugin] ChallengeSync created.");
			}
			catch (Exception ex)
			{
				Log.LogError((object)("[Plugin] EnsureUpdaterCreated failed: " + ex.Message));
			}
		}

		internal static bool IsKeyDown(KeyCode kc)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Expected I4, but got Unknown
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Keyboard current = Keyboard.current;
				if (current != null)
				{
					switch (kc - 256)
					{
					case 26:
						return ((ButtonControl)current.f1Key).wasPressedThisFrame;
					case 27:
						return ((ButtonControl)current.f2Key).wasPressedThisFrame;
					case 28:
						return ((ButtonControl)current.f3Key).wasPressedThisFrame;
					case 29:
						return ((ButtonControl)current.f4Key).wasPressedThisFrame;
					case 30:
						return ((ButtonControl)current.f5Key).wasPressedThisFrame;
					case 31:
						return ((ButtonControl)current.f6Key).wasPressedThisFrame;
					case 32:
						return ((ButtonControl)current.f7Key).wasPressedThisFrame;
					case 33:
						return ((ButtonControl)current.f8Key).wasPressedThisFrame;
					case 34:
						return ((ButtonControl)current.f9Key).wasPressedThisFrame;
					case 35:
						return ((ButtonControl)current.f10Key).wasPressedThisFrame;
					case 36:
						return ((ButtonControl)current.f11Key).wasPressedThisFrame;
					case 37:
						return ((ButtonControl)current.f12Key).wasPressedThisFrame;
					case 0:
						return ((ButtonControl)current.numpad0Key).wasPressedThisFrame;
					case 1:
						return ((ButtonControl)current.numpad1Key).wasPressedThisFrame;
					case 2:
						return ((ButtonControl)current.numpad2Key).wasPressedThisFrame;
					case 3:
						return ((ButtonControl)current.numpad3Key).wasPressedThisFrame;
					case 4:
						return ((ButtonControl)current.numpad4Key).wasPressedThisFrame;
					case 5:
						return ((ButtonControl)current.numpad5Key).wasPressedThisFrame;
					case 6:
						return ((ButtonControl)current.numpad6Key).wasPressedThisFrame;
					case 7:
						return ((ButtonControl)current.numpad7Key).wasPressedThisFrame;
					case 8:
						return ((ButtonControl)current.numpad8Key).wasPressedThisFrame;
					case 9:
						return ((ButtonControl)current.numpad9Key).wasPressedThisFrame;
					case 10:
					case 11:
					case 12:
					case 13:
					case 14:
					case 15:
					case 16:
					case 17:
					case 18:
					case 19:
					case 20:
					case 21:
					case 22:
					case 23:
					case 24:
					case 25:
						break;
					}
				}
			}
			catch
			{
			}
			return Input.GetKeyDown(kc);
		}

		private void BindConfig()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Expected O, but got Unknown
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Expected O, but got Unknown
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Expected O, but got Unknown
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Expected O, but got Unknown
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Expected O, but got Unknown
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Expected O, but got Unknown
			DebugKeysEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Debug", "DebugKeysEnabled", true, "Enable F8 (cycle challenge) and F9 (clear challenge) hotkeys.");
			CycleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("0 - Debug", "CycleKey", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Cycle through challenges.");
			ClearKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("0 - Debug", "ClearKey", new KeyboardShortcut((KeyCode)290, Array.Empty<KeyCode>()), "Clear active challenge.");
			ChallengeScopePerRound = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Challenges", "ChallengeScopePerRound", true, "true = challenge clears at the start of each new level.");
			CartLeashMaxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("1 - Challenges", "CartLeashMaxDistance", 5f, new ConfigDescription("Distance from cart for full stop.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), Array.Empty<object>()));
			CartLeashSlowStartDistance = ((BaseUnityPlugin)this).Config.Bind<float>("1 - Challenges", "CartLeashSlowStartDistance", 3f, new ConfigDescription("Distance from cart where slowdown begins (must be less than CartLeashMaxDistance).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), Array.Empty<object>()));
			CartLeashSlowPercent = ((BaseUnityPlugin)this).Config.Bind<int>("1 - Challenges", "CartLeashSlowPercent", 50, new ConfigDescription("Speed reduction % in the slow zone between SlowStart and MaxDistance.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			ExpensiveItemThreshold = ((BaseUnityPlugin)this).Config.Bind<int>("1 - Challenges", "ExpensiveItemThreshold", 5000, new ConfigDescription("Value threshold for Frugal/ExpensiveOnly.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(100, 100000), Array.Empty<object>()));
			ShortRangeUseOriginal = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Challenges", "ShortRangeUseOriginal", true, "true = reduction is based on the original base grab range (ignores upgrades). false = reduction is based on the current grab range at the time the challenge is assigned.");
			ShortRangeReductionPercent = ((BaseUnityPlugin)this).Config.Bind<int>("1 - Challenges", "ShortRangeReductionPercent", 50, new ConfigDescription("Percentage to reduce grab range for the Short Range challenge.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 99), Array.Empty<object>()));
			EnableNetworkSync = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Challenges", "EnableNetworkSync", false, "Sync via Photon (not yet implemented).");
			AutoAssignOnRoundStart = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Challenges", "AutoAssignOnRoundStart", false, "Auto-assign random challenge each level.");
			HudEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - HUD", "Enabled", true, "Show challenge HUD.");
			HudPositionX = ((BaseUnityPlugin)this).Config.Bind<int>("2 - HUD", "PositionX", 12, "Horizontal offset.");
			HudPositionY = ((BaseUnityPlugin)this).Config.Bind<int>("2 - HUD", "PositionY", 12, "Vertical offset.");
			HudFontSize = ((BaseUnityPlugin)this).Config.Bind<int>("2 - HUD", "FontSize", 18, new ConfigDescription("HUD font size.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 40), Array.Empty<object>()));
			HudShowDescription = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - HUD", "ShowDescription", true, "Show challenge description.");
			HudShowOtherPlayers = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - HUD", "ShowOtherPlayers", true, "Show other players challenges.");
			SbEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Streamer.bot Integration", "Enabled", true, "Watch challenge_cmd.txt for commands.");
		}
	}
	public class ChallengeUpdater : MonoBehaviour
	{
		private bool _firstUpdate = true;

		private float _pollTimer;

		private string _lastCmd = "";

		private const float POLL_INTERVAL = 0.5f;

		private void Awake()
		{
			Plugin.Log.LogInfo((object)"[ChallengeUpdater] Awake — standalone updater alive.");
			SceneManager.sceneLoaded += OnSceneLoaded;
		}

		private void OnDestroy()
		{
			SceneManager.sceneLoaded -= OnSceneLoaded;
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			Plugin.Log.LogInfo((object)("[ChallengeUpdater] Scene loaded: " + ((Scene)(ref scene)).name));
			ChallengeManager.OnSceneLoad();
			HeldItemTicker.OnSceneLoad();
		}

		private void Update()
		{
			//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_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			if (_firstUpdate)
			{
				_firstUpdate = false;
				Plugin.Log.LogInfo((object)$"[ChallengeUpdater] *** FIRST UPDATE *** Ready={Plugin.Ready}");
			}
			if (!Plugin.Ready)
			{
				return;
			}
			HeldItemTicker.Tick();
			if (Plugin.DebugKeysEnabled.Value)
			{
				KeyboardShortcut value = Plugin.CycleKey.Value;
				if (Plugin.IsKeyDown(((KeyboardShortcut)(ref value)).MainKey))
				{
					Plugin.Log.LogInfo((object)"[ChallengeUpdater] Cycle key pressed.");
					ChallengeManager.CycleChallenge();
					Plugin.WriteStatus();
				}
				value = Plugin.ClearKey.Value;
				if (Plugin.IsKeyDown(((KeyboardShortcut)(ref value)).MainKey))
				{
					Plugin.Log.LogInfo((object)"[ChallengeUpdater] Clear key pressed.");
					ChallengeManager.ClearChallenge();
					Plugin.WriteStatus();
				}
			}
			if (!Plugin.SbEnabled.Value)
			{
				return;
			}
			_pollTimer += Time.unscaledDeltaTime;
			if (_pollTimer < 0.5f)
			{
				return;
			}
			_pollTimer = 0f;
			try
			{
				if (File.Exists(Plugin.CMD_FILE))
				{
					string text = File.ReadAllText(Plugin.CMD_FILE);
					string text2 = ((text == null) ? "" : text.Trim().ToLowerInvariant());
					if (!string.IsNullOrEmpty(text2) && !(text2 == _lastCmd))
					{
						_lastCmd = text2;
						File.WriteAllText(Plugin.CMD_FILE, "");
						Plugin.Log.LogInfo((object)("[ChallengeUpdater] Command: '" + text2 + "'"));
						ExecuteCommand(text2);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[ChallengeUpdater] Poll error: " + ex.Message));
			}
		}

		private void ExecuteCommand(string cmd)
		{
			string targetName = Plugin.ParseField(cmd, "player:");
			if (cmd == "clear" || cmd.Contains(",clear") || cmd.StartsWith("clear,"))
			{
				ChallengeSync.SendClear(targetName);
			}
			else if (cmd == "random")
			{
				ChallengeSync.SendChallenge(targetName, ChallengeRegistry.GetRandom()?.Id ?? "");
			}
			else
			{
				string text = Plugin.ParseField(cmd, "challenge:") ?? cmd;
				if (!ChallengeRegistry.Has(text))
				{
					Plugin.Log.LogWarning((object)("[ChallengeUpdater] Unknown id: '" + text + "'"));
				}
				else
				{
					ChallengeSync.SendChallenge(targetName, text);
				}
			}
			Plugin.WriteStatus();
		}
	}
}
namespace GynxzRepoChallenges.UI
{
	public class ChallengeHUD : MonoBehaviour
	{
		public static bool Dirty;

		private static string _violationText;

		private static float _violationTimer;

		private const float VIOLATION_DURATION = 3f;

		private static string _persistentText;

		private GUIStyle _boxStyle;

		private GUIStyle _titleStyle;

		private GUIStyle _descStyle;

		private GUIStyle _violationStyle;

		private bool _stylesInitialised;

		public static void ShowPersistentMessage(string message)
		{
			_persistentText = message;
		}

		public static void ClearPersistentMessage()
		{
			_persistentText = null;
		}

		public static void ShowViolation(string message)
		{
			_violationText = message;
			_violationTimer = 3f;
		}

		private void Update()
		{
			if (_violationTimer > 0f)
			{
				_violationTimer -= Time.unscaledDeltaTime;
			}
		}

		private void OnGUI()
		{
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Expected O, but got Unknown
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_037d: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.HudEnabled.Value)
			{
				return;
			}
			InitStyles();
			int value = Plugin.HudPositionX.Value;
			int value2 = Plugin.HudPositionY.Value;
			int value3 = Plugin.HudFontSize.Value;
			int num = 8;
			int num2 = 260;
			if (_violationTimer > 0f && _violationText != null)
			{
				float num3 = Mathf.Clamp01(_violationTimer / 3f);
				Color color = GUI.color;
				GUI.color = new Color(1f, 0.2f, 0.2f, num3);
				Vector2 val = _violationStyle.CalcSize(new GUIContent(_violationText));
				float num4 = (float)Screen.width * 0.5f - val.x * 0.5f;
				float num5 = (float)Screen.height * 0.35f;
				GUI.Label(new Rect(num4 - (float)num, num5 - (float)num, val.x + (float)(num * 2), val.y + (float)(num * 2)), _violationText, _violationStyle);
				GUI.color = color;
			}
			if (_persistentText != null)
			{
				Vector2 val2 = _violationStyle.CalcSize(new GUIContent(_persistentText));
				float num6 = (float)Screen.width * 0.5f - val2.x * 0.5f;
				float num7 = (float)Screen.height * 0.5f - val2.y * 0.5f;
				Color color2 = GUI.color;
				GUI.color = new Color(1f, 0.55f, 0f, 1f);
				GUI.Label(new Rect(num6 - (float)num, num7 - (float)num, val2.x + (float)(num * 2), val2.y + (float)(num * 2)), _persistentText, _violationStyle);
				GUI.color = color2;
			}
			if (ChallengeManager.ActiveChallenge == null)
			{
				GUI.Box(new Rect((float)value, (float)value2, (float)num2, (float)(30 + num * 2)), "", _boxStyle);
				GUI.Label(new Rect((float)(value + num), (float)(value2 + num), (float)(num2 - num * 2), 26f), "No challenge active  |  F8 to cycle", _descStyle);
				return;
			}
			BaseChallenge activeChallenge = ChallengeManager.ActiveChallenge;
			string text = "⚠ " + activeChallenge.DisplayName;
			string text2 = (Plugin.HudShowDescription.Value ? activeChallenge.Description : "");
			float num8 = value3 + 6;
			float num9 = (Plugin.HudShowDescription.Value ? ((value3 - 2) * 2 + 4) : 0);
			float num10 = num8 + num9 + (float)(num * 3);
			GUI.Box(new Rect((float)value, (float)value2, (float)num2, num10), "", _boxStyle);
			_titleStyle.fontSize = value3;
			GUI.Label(new Rect((float)(value + num), (float)(value2 + num), (float)(num2 - num * 2), num8), text, _titleStyle);
			if (Plugin.HudShowDescription.Value && !string.IsNullOrEmpty(text2))
			{
				_descStyle.fontSize = value3 - 2;
				GUI.Label(new Rect((float)(value + num), (float)(value2 + num) + num8 + 2f, (float)(num2 - num * 2), num9), text2, _descStyle);
			}
			int num11 = 0;
			string text3 = "";
			if (ChallengeManager.FlawlessActive)
			{
				num11 = ChallengeManager.FlawlessViolations;
				text3 = "Damage events";
			}
			else if (ChallengeManager.CartLeashActive)
			{
				num11 = ChallengeManager.CartLeashViolations;
				text3 = "Leash breaks";
			}
			if (text3 != "" && num11 > 0)
			{
				string text4 = $"{text3}: {num11}";
				GUI.Label(new Rect((float)(value + num), (float)value2 + num10, (float)(num2 - num * 2), 20f), text4, _descStyle);
			}
		}

		private void InitStyles()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Expected O, but got Unknown
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: 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_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Expected O, but got Unknown
			if (!_stylesInitialised)
			{
				_stylesInitialised = true;
				Texture2D val = new Texture2D(1, 1);
				val.SetPixel(0, 0, new Color(0f, 0f, 0f, 0.65f));
				val.Apply();
				GUIStyle val2 = new GUIStyle(GUI.skin.box);
				val2.normal.background = val;
				_boxStyle = val2;
				GUIStyle val3 = new GUIStyle(GUI.skin.label)
				{
					fontStyle = (FontStyle)1
				};
				val3.normal.textColor = new Color(1f, 0.85f, 0.2f);
				val3.wordWrap = false;
				_titleStyle = val3;
				GUIStyle val4 = new GUIStyle(GUI.skin.label)
				{
					fontStyle = (FontStyle)0
				};
				val4.normal.textColor = new Color(0.9f, 0.9f, 0.9f);
				val4.wordWrap = true;
				_descStyle = val4;
				GUIStyle val5 = new GUIStyle(GUI.skin.label)
				{
					fontStyle = (FontStyle)1,
					fontSize = 24,
					alignment = (TextAnchor)4
				};
				val5.normal.textColor = Color.red;
				_violationStyle = val5;
			}
		}
	}
}
namespace GynxzRepoChallenges.SB
{
	public class SBBridge : MonoBehaviour
	{
		private static readonly string BASE = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Thunderstore Mod Manager\\DataFolder\\REPO\\profiles\\REPO");

		public static readonly string CMD_FILE = Path.Combine(BASE, "challenge_cmd.txt");

		public static readonly string STATUS_FILE = Path.Combine(BASE, "challenge_status.txt");

		public static readonly string LIST_FILE = Path.Combine(BASE, "challenge_list.txt");

		private string _lastCmd = "";

		private float _pollTimer;

		private const float POLL_INTERVAL = 0.5f;

		public static SBBridge Create()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			GameObject val = new GameObject("GynxzSBBridge");
			Object.DontDestroyOnLoad((Object)val);
			return val.AddComponent<SBBridge>();
		}

		private void Awake()
		{
			try
			{
				WriteListFile();
				TryClearCmd();
				WriteStatus();
				Plugin.Log.LogInfo((object)"[SBBridge] File bridge ready.");
				Plugin.Log.LogInfo((object)("[SBBridge] Command file: " + CMD_FILE));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[SBBridge] Awake failed: " + ex.Message));
			}
		}

		private void Update()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.DebugKeysEnabled.Value)
			{
				KeyboardShortcut value = Plugin.CycleKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					Plugin.Log.LogInfo((object)"[SBBridge] Cycle key pressed.");
					ChallengeManager.CycleChallenge();
				}
				value = Plugin.ClearKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					Plugin.Log.LogInfo((object)"[SBBridge] Clear key pressed.");
					ChallengeManager.ClearChallenge();
				}
			}
			_pollTimer += Time.unscaledDeltaTime;
			if (_pollTimer < 0.5f)
			{
				return;
			}
			_pollTimer = 0f;
			try
			{
				if (File.Exists(CMD_FILE))
				{
					string text = File.ReadAllText(CMD_FILE);
					string text2 = ((text == null) ? "" : text.Trim().ToLowerInvariant());
					if (!string.IsNullOrEmpty(text2) && !(text2 == _lastCmd))
					{
						_lastCmd = text2;
						File.WriteAllText(CMD_FILE, "");
						Plugin.Log.LogInfo((object)("[SBBridge] Command received: '" + text2 + "'"));
						ExecuteCommand(text2);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[SBBridge] Poll error: " + ex.Message));
			}
		}

		private void ExecuteCommand(string cmd)
		{
			if (cmd == "clear")
			{
				ChallengeManager.ClearChallenge();
			}
			else if (cmd == "random")
			{
				ChallengeManager.AssignRandom();
			}
			else
			{
				string text = cmd;
				if (cmd.Contains("challenge:"))
				{
					int num = cmd.IndexOf("challenge:", StringComparison.Ordinal);
					text = cmd.Substring(num + 10).Split(new char[1] { ',' })[0].Trim();
				}
				if (!ChallengeManager.AssignById(text))
				{
					Plugin.Log.LogWarning((object)("[SBBridge] Unknown id: '" + text + "'"));
				}
			}
			WriteStatus();
		}

		private void WriteListFile()
		{
			try
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("# Valid challenge ids — write one to: " + CMD_FILE);
				stringBuilder.AppendLine("# Special commands: clear, random");
				stringBuilder.AppendLine();
				foreach (BaseChallenge item in ChallengeRegistry.All)
				{
					stringBuilder.AppendLine($"{item.Id,-20} # {item.DisplayName}");
				}
				File.WriteAllText(LIST_FILE, stringBuilder.ToString());
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[SBBridge] WriteListFile failed: " + ex.Message));
			}
		}

		public static void WriteStatus()
		{
			try
			{
				BaseChallenge activeChallenge = ChallengeManager.ActiveChallenge;
				string contents = ((activeChallenge == null) ? "active: none" : ("active: " + activeChallenge.Id + " | " + activeChallenge.DisplayName));
				File.WriteAllText(STATUS_FILE, contents);
			}
			catch
			{
			}
		}

		private static void TryClearCmd()
		{
			try
			{
				File.WriteAllText(CMD_FILE, "");
			}
			catch
			{
			}
		}
	}
	public class MainThreadDispatcher : MonoBehaviour
	{
		private static MainThreadDispatcher _instance;

		private static readonly Queue<Action> _queue = new Queue<Action>();

		private static readonly object _lock = new object();

		public static void Enqueue(Action action)
		{
			lock (_lock)
			{
				_queue.Enqueue(action);
			}
		}

		public static void EnsureExists()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			if (!((Object)(object)_instance != (Object)null))
			{
				GameObject val = new GameObject("GynxzMainThreadDispatcher");
				Object.DontDestroyOnLoad((Object)val);
				_instance = val.AddComponent<MainThreadDispatcher>();
			}
		}

		private void Awake()
		{
			_instance = this;
		}

		private void Update()
		{
			while (true)
			{
				Action action;
				lock (_lock)
				{
					if (_queue.Count == 0)
					{
						break;
					}
					action = _queue.Dequeue();
				}
				try
				{
					action();
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)("[Dispatcher] " + ex.Message));
				}
			}
		}
	}
}
namespace GynxzRepoChallenges.Network
{
	public class ChallengeSync : MonoBehaviour, IOnEventCallback
	{
		private const byte EVENT_ASSIGN = 77;

		private const byte EVENT_CLEAR = 78;

		private float _playerListTimer;

		private const float PLAYER_LIST_INTERVAL = 5f;

		public static ChallengeSync Instance { get; private set; }

		public static void Create()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			if (!((Object)(object)Instance != (Object)null))
			{
				GameObject val = new GameObject("GynxzChallengeSync");
				Object.DontDestroyOnLoad((Object)val);
				Instance = val.AddComponent<ChallengeSync>();
			}
		}

		private void Awake()
		{
			Instance = this;
			PhotonNetwork.AddCallbackTarget((object)this);
			Plugin.Log.LogInfo((object)"[ChallengeSync] Awake — listening for events.");
			WritePlayerList();
		}

		private void OnDestroy()
		{
			PhotonNetwork.RemoveCallbackTarget((object)this);
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		private void Update()
		{
			_playerListTimer -= Time.unscaledDeltaTime;
			if (_playerListTimer <= 0f)
			{
				_playerListTimer = 5f;
				WritePlayerList();
			}
		}

		public static void SendChallenge(string targetName, string challengeId)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(challengeId))
			{
				return;
			}
			if (!PhotonNetwork.InRoom || string.IsNullOrEmpty(targetName))
			{
				AssignLocal(challengeId);
				return;
			}
			Player val = FindPlayer(targetName);
			if (val == null)
			{
				Plugin.Log.LogWarning((object)("[ChallengeSync] Player '" + targetName + "' not found — assigning locally."));
				AssignLocal(challengeId);
				return;
			}
			if (val.IsLocal)
			{
				AssignLocal(challengeId);
				return;
			}
			RaiseEventOptions val2 = new RaiseEventOptions();
			val2.TargetActors = new int[1] { val.ActorNumber };
			RaiseEventOptions val3 = val2;
			PhotonNetwork.RaiseEvent((byte)77, (object)challengeId, val3, SendOptions.SendReliable);
			Plugin.Log.LogInfo((object)$"[ChallengeSync] Sent '{challengeId}' → {val.NickName} (actor {val.ActorNumber})");
		}

		public static void SendClear(string targetName)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.InRoom || string.IsNullOrEmpty(targetName))
			{
				ClearLocal();
				return;
			}
			Player val = FindPlayer(targetName);
			if (val == null || val.IsLocal)
			{
				ClearLocal();
				return;
			}
			RaiseEventOptions val2 = new RaiseEventOptions();
			val2.TargetActors = new int[1] { val.ActorNumber };
			RaiseEventOptions val3 = val2;
			PhotonNetwork.RaiseEvent((byte)78, (object)null, val3, SendOptions.SendReliable);
			Plugin.Log.LogInfo((object)("[ChallengeSync] Sent clear → " + val.NickName));
		}

		public void OnEvent(EventData photonEvent)
		{
			try
			{
				if (photonEvent.Code == 77)
				{
					string text = photonEvent.CustomData as string;
					Plugin.Log.LogInfo((object)("[ChallengeSync] Received assign: '" + text + "'"));
					AssignLocal(text);
				}
				else if (photonEvent.Code == 78)
				{
					Plugin.Log.LogInfo((object)"[ChallengeSync] Received clear.");
					ClearLocal();
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[ChallengeSync] OnEvent error: " + ex.Message));
			}
		}

		private static void AssignLocal(string id)
		{
			ChallengeManager.AssignById(id);
			Plugin.WriteStatus();
		}

		private static void ClearLocal()
		{
			ChallengeManager.ClearChallenge();
			Plugin.WriteStatus();
		}

		private static Player FindPlayer(string name)
		{
			Player[] playerList = PhotonNetwork.PlayerList;
			foreach (Player val in playerList)
			{
				if (string.Equals(val.NickName, name, StringComparison.OrdinalIgnoreCase))
				{
					return val;
				}
			}
			return null;
		}

		internal static void WritePlayerList()
		{
			try
			{
				StringBuilder stringBuilder = new StringBuilder();
				if (PhotonNetwork.InRoom)
				{
					Room currentRoom = PhotonNetwork.CurrentRoom;
					stringBuilder.AppendLine("# Room: " + (((currentRoom != null) ? currentRoom.Name : null) ?? "unknown"));
					Player[] playerList = PhotonNetwork.PlayerList;
					foreach (Player val in playerList)
					{
						stringBuilder.AppendLine(string.Format("{0}{1}  actor={2}", val.NickName, val.IsLocal ? " (you)" : "", val.ActorNumber));
					}
				}
				else
				{
					stringBuilder.AppendLine("# Not in room (solo or main menu)");
					Player localPlayer = PhotonNetwork.LocalPlayer;
					stringBuilder.AppendLine((((localPlayer != null) ? localPlayer.NickName : null) ?? "local") + " (you)");
				}
				File.WriteAllText(Plugin.PLAYERS_FILE, stringBuilder.ToString());
			}
			catch
			{
			}
		}
	}
}
namespace GynxzRepoChallenges.Challenges
{
	public class NoCrouchChallenge : BaseChallenge
	{
		public override string Id => "no_crouch";

		public override string DisplayName => "No Crouch";

		public override string Description => "You cannot crouch. Stand tall, suffer fully.";

		public override void Apply()
		{
			ChallengeManager.NoCrouchActive = true;
		}

		public override void Remove()
		{
			ChallengeManager.NoCrouchActive = false;
		}
	}
	public class NoSprintChallenge : BaseChallenge
	{
		public override string Id => "no_sprint";

		public override string DisplayName => "No Sprint";

		public override string Description => "Walk only. No running. Enjoy the leisurely pace.";

		public override void Apply()
		{
			ChallengeManager.NoSprintActive = true;
		}

		public override void Remove()
		{
			ChallengeManager.NoSprintActive = false;
		}
	}
	public class NoMapChallenge : BaseChallenge
	{
		public override string Id => "no_map";

		public override string DisplayName => "No Map";

		public override string Description => "The map tool is disabled. Navigate by memory.";

		public override void Apply()
		{
			ChallengeManager.NoMapActive = true;
		}

		public override void Remove()
		{
			ChallengeManager.NoMapActive = false;
		}
	}
	public class NoHealthPackChallenge : BaseChallenge
	{
		public override string Id => "no_healthpack";

		public override string DisplayName => "No Health Pack";

		public override string Description => "Health packs cannot be used. Hope you don't get hurt.";

		public override void Apply()
		{
			ChallengeManager.NoHealthPackActive = true;
		}

		public override void Remove()
		{
			ChallengeManager.NoHealthPackActive = false;
		}
	}
	public class NoUpgradesChallenge : BaseChallenge
	{
		public override string Id => "no_upgrades";

		public override string DisplayName => "No Upgrades";

		public override string Description => "Upgrade stations are off-limits. Stay baseline.";

		public override void Apply()
		{
			ChallengeManager.NoUpgradesActive = true;
		}

		public override void Remove()
		{
			ChallengeManager.NoUpgradesActive = false;
		}
	}
	public class TextOnlyChallenge : BaseChallenge
	{
		public override string Id => "text_only";

		public override string DisplayName => "Text Only";

		public override string Description => "Communicate using text chat only. No voice.";

		public override void Apply()
		{
		}

		public override void Remove()
		{
		}
	}
	public class CartLeashChallenge : BaseChallenge
	{
		public override string Id => "cart_leash";

		public override string DisplayName => "Cart Leash";

		public override string Description => $"Stay within {Plugin.CartLeashMaxDistance.Value} units of the nearest cart at all times.";

		public override void Apply()
		{
			ChallengeManager.CartLeashActive = true;
		}

		public override void Remove()
		{
			ChallengeManager.CartLeashActive = false;
		}
	}
	public class FlawlessChallenge : BaseChallenge
	{
		public override string Id => "flawless";

		public override string DisplayName => "Flawless Items";

		public override string Description => "You must not damage any item. Handle with care.";

		public override void Apply()
		{
			ChallengeManager.FlawlessActive = true;
		}

		public override void Remove()
		{
			ChallengeManager.FlawlessActive = false;
		}
	}
	public class FrugalChallenge : BaseChallenge
	{
		public override string Id => "frugal";

		public override string DisplayName => "Frugal";

		public override string Description => $"Only grab items worth less than ${Plugin.ExpensiveItemThreshold.Value:N0}. No splurging.";

		public override void Apply()
		{
			ChallengeManager.FrugalActive = true;
		}

		public override void Remove()
		{
			ChallengeManager.FrugalActive = false;
		}
	}
	public class ExpensiveOnlyChallenge : BaseChallenge
	{
		public override string Id => "expensive_only";

		public override string DisplayName => "Expensive Only";

		public override string Description => $"Only grab items worth ${Plugin.ExpensiveItemThreshold.Value:N0} or more. High standards only.";

		public override void Apply()
		{
			ChallengeManager.ExpensiveOnlyActive = true;
		}

		public override void Remove()
		{
			ChallengeManager.ExpensiveOnlyActive = false;
		}
	}
	public class PacifistChallenge : BaseChallenge
	{
		public override string Id => "pacifist";

		public override string DisplayName => "Pacifist";

		public override string Description => "No grabbing weapons. Violence is not the answer.";

		public override void Apply()
		{
			ChallengeManager.PacifistActive = true;
		}

		public override void Remove()
		{
			ChallengeManager.PacifistActive = false;
		}
	}
	public class EmpathyChallenge : BaseChallenge
	{
		public override string Id => "empathetic";

		public override string DisplayName => "Empathetic";

		public override string Description => "You feel everything. Items you hold share their pain — every hit deals 5HP to you.";

		public override void Apply()
		{
			ChallengeManager.EmpathyActive = true;
		}

		public override void Remove()
		{
			ChallengeManager.EmpathyActive = false;
		}
	}
	public class NitroFingersChallenge : BaseChallenge
	{
		public override string Id => "nitro_fingers";

		public override string DisplayName => "Nitro Fingers";

		public override string Description => "Everything you touch that takes damage EXPLODES. Handle with extreme care.";

		public override void Apply()
		{
			ChallengeManager.NitroFingersActive = true;
		}

		public override void Remove()
		{
			ChallengeManager.NitroFingersActive = false;
		}
	}
	public class ShortRangeChallenge : BaseChallenge
	{
		public override string Id => "t_rex";

		public override string DisplayName => "T-Rex";

		public override string Description
		{
			get
			{
				int value = Plugin.ShortRangeReductionPercent.Value;
				float shortRangeOriginalValue = ChallengeManager.ShortRangeOriginalValue;
				float shortRangeCurrentValue = ChallengeManager.ShortRangeCurrentValue;
				if (shortRangeOriginalValue >= 0f && shortRangeCurrentValue >= 0f)
				{
					float num = (Plugin.ShortRangeUseOriginal.Value ? shortRangeOriginalValue : shortRangeCurrentValue) * (1f - (float)value / 100f);
					return $"Short arms, big heart. Range -{value}%  " + $"(base {shortRangeOriginalValue:F1}  current {shortRangeCurrentValue:F1}  →  {num:F1})";
				}
				return $"Short arms, big heart. Grab range reduced by {value}%.";
			}
		}

		public override void Apply()
		{
			ChallengeManager.ShortRangeActive = true;
		}

		public override void Remove()
		{
			ChallengeManager.ShortRangeActive = false;
		}
	}
	public abstract class BaseChallenge
	{
		public abstract string Id { get; }

		public abstract string DisplayName { get; }

		public abstract string Description { get; }

		public virtual void Apply()
		{
		}

		public virtual void Remove()
		{
		}

		public override string ToString()
		{
			return DisplayName + " (" + Id + ")";
		}
	}
	public static class ChallengeRegistry
	{
		private static readonly Dictionary<string, BaseChallenge> _challenges = new Dictionary<string, BaseChallenge>(StringComparer.OrdinalIgnoreCase);

		private static readonly Random _rng = new Random();

		public static int Count => _challenges.Count;

		public static IEnumerable<BaseChallenge> All => _challenges.Values;

		public static void RegisterAll()
		{
			Register(new NoCrouchChallenge());
			Register(new NoSprintChallenge());
			Register(new NoMapChallenge());
			Register(new NoHealthPackChallenge());
			Register(new NoUpgradesChallenge());
			Register(new TextOnlyChallenge());
			Register(new CartLeashChallenge());
			Register(new FlawlessChallenge());
			Register(new FrugalChallenge());
			Register(new ExpensiveOnlyChallenge());
			Register(new PacifistChallenge());
			Register(new EmpathyChallenge());
			Register(new NitroFingersChallenge());
			Register(new ShortRangeChallenge());
		}

		public static void Register(BaseChallenge challenge)
		{
			_challenges[challenge.Id] = challenge;
		}

		public static BaseChallenge Get(string id)
		{
			if (!_challenges.TryGetValue(id, out var value))
			{
				return null;
			}
			return value;
		}

		public static bool Has(string id)
		{
			return _challenges.ContainsKey(id);
		}

		public static BaseChallenge GetRandom()
		{
			if (_challenges.Count == 0)
			{
				return null;
			}
			List<BaseChallenge> list = _challenges.Values.ToList();
			return list[_rng.Next(list.Count)];
		}

		public static BaseChallenge GetByIndex(int index)
		{
			List<BaseChallenge> list = _challenges.Values.ToList();
			if (list.Count == 0)
			{
				return null;
			}
			return list[index % list.Count];
		}

		public static IEnumerable<string> AllIds()
		{
			return _challenges.Keys;
		}
	}
}