Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of GynxzRepoChallenges v1.2.3
plugins\GynxzRepoChallenges\GynxzRepoChallenges.dll
Decompiled 2 days agousing 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; } } }