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 _cartTransforms = new List(); 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(); 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(); 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 _violatedItems = new HashSet(); 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(); 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 _warnedThisRound = new HashSet(); 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(); 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(); 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 DebugKeysEnabled; internal static ConfigEntry CycleKey; internal static ConfigEntry ClearKey; internal static ConfigEntry ChallengeScopePerRound; internal static ConfigEntry CartLeashMaxDistance; internal static ConfigEntry CartLeashSlowStartDistance; internal static ConfigEntry CartLeashSlowPercent; internal static ConfigEntry ExpensiveItemThreshold; internal static ConfigEntry EnableNetworkSync; internal static ConfigEntry AutoAssignOnRoundStart; internal static ConfigEntry ShortRangeUseOriginal; internal static ConfigEntry ShortRangeReductionPercent; internal static ConfigEntry HudEnabled; internal static ConfigEntry HudPositionX; internal static ConfigEntry HudPositionY; internal static ConfigEntry HudFontSize; internal static ConfigEntry HudShowDescription; internal static ConfigEntry HudShowOtherPlayers; internal static ConfigEntry 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(); Log.LogInfo((object)"[Plugin] HUD created from gameplay context."); } GameObject val2 = new GameObject("GynxzChallengeUpdater_Live"); Object.DontDestroyOnLoad((Object)val2); val2.AddComponent(); 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("0 - Debug", "DebugKeysEnabled", true, "Enable F8 (cycle challenge) and F9 (clear challenge) hotkeys."); CycleKey = ((BaseUnityPlugin)this).Config.Bind("0 - Debug", "CycleKey", new KeyboardShortcut((KeyCode)289, Array.Empty()), "Cycle through challenges."); ClearKey = ((BaseUnityPlugin)this).Config.Bind("0 - Debug", "ClearKey", new KeyboardShortcut((KeyCode)290, Array.Empty()), "Clear active challenge."); ChallengeScopePerRound = ((BaseUnityPlugin)this).Config.Bind("1 - Challenges", "ChallengeScopePerRound", true, "true = challenge clears at the start of each new level."); CartLeashMaxDistance = ((BaseUnityPlugin)this).Config.Bind("1 - Challenges", "CartLeashMaxDistance", 5f, new ConfigDescription("Distance from cart for full stop.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 50f), Array.Empty())); CartLeashSlowStartDistance = ((BaseUnityPlugin)this).Config.Bind("1 - Challenges", "CartLeashSlowStartDistance", 3f, new ConfigDescription("Distance from cart where slowdown begins (must be less than CartLeashMaxDistance).", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 50f), Array.Empty())); CartLeashSlowPercent = ((BaseUnityPlugin)this).Config.Bind("1 - Challenges", "CartLeashSlowPercent", 50, new ConfigDescription("Speed reduction % in the slow zone between SlowStart and MaxDistance.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); ExpensiveItemThreshold = ((BaseUnityPlugin)this).Config.Bind("1 - Challenges", "ExpensiveItemThreshold", 5000, new ConfigDescription("Value threshold for Frugal/ExpensiveOnly.", (AcceptableValueBase)(object)new AcceptableValueRange(100, 100000), Array.Empty())); ShortRangeUseOriginal = ((BaseUnityPlugin)this).Config.Bind("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("1 - Challenges", "ShortRangeReductionPercent", 50, new ConfigDescription("Percentage to reduce grab range for the Short Range challenge.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 99), Array.Empty())); EnableNetworkSync = ((BaseUnityPlugin)this).Config.Bind("1 - Challenges", "EnableNetworkSync", false, "Sync via Photon (not yet implemented)."); AutoAssignOnRoundStart = ((BaseUnityPlugin)this).Config.Bind("1 - Challenges", "AutoAssignOnRoundStart", false, "Auto-assign random challenge each level."); HudEnabled = ((BaseUnityPlugin)this).Config.Bind("2 - HUD", "Enabled", true, "Show challenge HUD."); HudPositionX = ((BaseUnityPlugin)this).Config.Bind("2 - HUD", "PositionX", 12, "Horizontal offset."); HudPositionY = ((BaseUnityPlugin)this).Config.Bind("2 - HUD", "PositionY", 12, "Vertical offset."); HudFontSize = ((BaseUnityPlugin)this).Config.Bind("2 - HUD", "FontSize", 18, new ConfigDescription("HUD font size.", (AcceptableValueBase)(object)new AcceptableValueRange(10, 40), Array.Empty())); HudShowDescription = ((BaseUnityPlugin)this).Config.Bind("2 - HUD", "ShowDescription", true, "Show challenge description."); HudShowOtherPlayers = ((BaseUnityPlugin)this).Config.Bind("2 - HUD", "ShowOtherPlayers", true, "Show other players challenges."); SbEnabled = ((BaseUnityPlugin)this).Config.Bind("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(); } 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 _queue = new Queue(); 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(); } } 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(); } } 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 _challenges = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly Random _rng = new Random(); public static int Count => _challenges.Count; public static IEnumerable 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 list = _challenges.Values.ToList(); return list[_rng.Next(list.Count)]; } public static BaseChallenge GetByIndex(int index) { List list = _challenges.Values.ToList(); if (list.Count == 0) { return null; } return list[index % list.Count]; } public static IEnumerable AllIds() { return _challenges.Keys; } } }