using System; using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using CSync.Lib; using CSync.Util; using GameNetcodeStuff; using HarmonyLib; using MoreBatteryMod.Patches; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace MoreBatteryMod { [BepInPlugin("MoreBattery", "MoreBattery", "1.2.6")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public static Plugin Instance; internal ManualLogSource Log; private Harmony harmony; public static MoreBatteryConfig ConfigInstance; public static ConfigEntry ShowDebugUI; public static ConfigEntry ForceAntiCheatTest; private static GameObject hudGo; private void Awake() { //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown if ((Object)(object)Instance == (Object)null) { Instance = this; } Log = ((BaseUnityPlugin)this).Logger; ConfigInstance = new MoreBatteryConfig(((BaseUnityPlugin)this).Config); ShowDebugUI = ((BaseUnityPlugin)this).Config.Bind("General", "ShowDebugUI", false, "If true, shows a basic text overlay on the screen when holding or using a battery-operated item."); Log.LogInfo((object)("ShowDebugUI bound. Value = " + ShowDebugUI.Value)); ForceAntiCheatTest = ((BaseUnityPlugin)this).Config.Bind("Debug", "ForceAntiCheatTest", false, "[TESTING ONLY] If true, forces the anti-cheat fallback as if you are in a vanilla lobby (multiplier locked to 1.0x). Leave false for normal gameplay."); Log.LogInfo((object)("ForceAntiCheatTest bound. Value = " + ForceAntiCheatTest.Value)); try { harmony = new Harmony("MoreBattery"); harmony.PatchAll(typeof(MoreBatteryModPatches)); SceneManager.sceneLoaded += OnSceneLoaded; Log.LogInfo((object)"MoreBattery v1.2.6 with CSync networking support loaded successfully!"); } catch (Exception ex) { Log.LogError((object)("Failed to apply patches: " + ex.ToString())); } } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown if ((Object)(object)hudGo == (Object)null) { Log.LogInfo((object)("[MoreBattery] Spawning HUD GameObject on scene loaded: " + ((Scene)(ref scene)).name)); try { hudGo = new GameObject("MoreBatteryHUD"); Object.DontDestroyOnLoad((Object)(object)hudGo); hudGo.AddComponent(); Log.LogInfo((object)"[MoreBattery] Successfully spawned HUD GameObject!"); } catch (Exception ex) { Log.LogError((object)("[MoreBattery] Failed to spawn HUD GameObject: " + ex.ToString())); } } } } public class MoreBatteryHUD : MonoBehaviour { private bool _onGuiLoggedOnce; private bool _hudLoggedOnce; private void OnGUI() { //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Expected O, but got Unknown //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Expected O, but got Unknown //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_04f8: Unknown result type (might be due to invalid IL or missing references) //IL_0529: Unknown result type (might be due to invalid IL or missing references) //IL_0564: Unknown result type (might be due to invalid IL or missing references) //IL_033f: Unknown result type (might be due to invalid IL or missing references) //IL_063f: Unknown result type (might be due to invalid IL or missing references) //IL_0457: Unknown result type (might be due to invalid IL or missing references) if (!_onGuiLoggedOnce) { Plugin.Instance.Log.LogInfo((object)("[MoreBattery HUD] Component OnGUI first call! ShowDebugUI = " + ((Plugin.ShowDebugUI != null) ? Plugin.ShowDebugUI.Value.ToString() : "null"))); _onGuiLoggedOnce = true; } if (Plugin.ShowDebugUI == null || !Plugin.ShowDebugUI.Value) { return; } int num = 340; int num2 = 120; int num3 = 10; int num4 = 10; if (!_hudLoggedOnce) { Plugin.Instance.Log.LogInfo((object)("[MoreBattery HUD] Component OnGUI drawing at (" + num3 + "," + num4 + ") size " + num + "x" + num2)); _hudLoggedOnce = true; } Color backgroundColor = GUI.backgroundColor; GUI.backgroundColor = new Color(0f, 0f, 0f, 0.75f); GUI.Box(new Rect((float)num3, (float)num4, (float)num, (float)num2), ""); GUI.backgroundColor = backgroundColor; GUIStyle val = new GUIStyle(GUI.skin.label); val.fontStyle = (FontStyle)1; val.normal.textColor = Color.yellow; val.fontSize = 14; GUIStyle val2 = new GUIStyle(GUI.skin.label); val2.normal.textColor = Color.white; val2.fontSize = 12; GUI.Label(new Rect((float)(num3 + 15), (float)(num4 + 10), (float)(num - 30), 20f), "MoreBattery Debug Info", val); PlayerControllerB localPlayer = GetLocalPlayer(); if ((Object)(object)localPlayer == (Object)null) { return; } GrabbableObject activeBatteryItem = GetActiveBatteryItem(localPlayer); if ((Object)(object)activeBatteryItem == (Object)null || (Object)(object)activeBatteryItem.itemProperties == (Object)null) { GUI.Label(new Rect((float)(num3 + 15), (float)(num4 + 25), (float)(num - 30), 18f), "Status: Active & Loaded (No Item)", val2); string text = (((Object)(object)localPlayer.currentlyHeldObject != (Object)null) ? ((Object)localPlayer.currentlyHeldObject).name : "null"); string text2 = (((Object)(object)localPlayer.ItemOnlySlot != (Object)null) ? ((Object)localPlayer.ItemOnlySlot).name : "null"); GUI.Label(new Rect((float)(num3 + 15), (float)(num4 + 43), (float)(num - 30), 18f), "Held: " + text + " | Utility: " + text2, val2); string text3 = (((Object)(object)localPlayer.pocketedFlashlight != (Object)null) ? ((Object)localPlayer.pocketedFlashlight).name : "null"); GUI.Label(new Rect((float)(num3 + 15), (float)(num4 + 61), (float)(num - 30), 18f), "Pocketed Flashlight: " + text3, val2); string text4 = "null"; if (localPlayer.ItemSlots != null && localPlayer.currentItemSlot >= 0 && localPlayer.currentItemSlot < localPlayer.ItemSlots.Length) { GrabbableObject val3 = localPlayer.ItemSlots[localPlayer.currentItemSlot]; text4 = (((Object)(object)val3 != (Object)null) ? ((Object)val3).name : "null"); } GUI.Label(new Rect((float)(num3 + 15), (float)(num4 + 79), (float)(num - 30), 18f), "Slot " + localPlayer.currentItemSlot + ": " + text4, val2); string text5 = "None"; if (localPlayer.ItemSlots != null) { for (int i = 0; i < localPlayer.ItemSlots.Length; i++) { if ((Object)(object)localPlayer.ItemSlots[i] != (Object)null && localPlayer.ItemSlots[i] is FlashlightItem) { text5 = "Slot " + i + ": " + ((Object)localPlayer.ItemSlots[i]).name + " (Used: " + localPlayer.ItemSlots[i].isBeingUsed + ")"; break; } } } GUI.Label(new Rect((float)(num3 + 15), (float)(num4 + 97), (float)(num - 30), 18f), "Found in Inventory: " + text5, val2); } else { Item itemProperties = activeBatteryItem.itemProperties; float num5 = itemProperties.batteryUsage; if (MoreBatteryModPatches.OriginalDurations.TryGetValue(itemProperties, out var value)) { num5 = value; } float batteryUsage = itemProperties.batteryUsage; float num6 = ((activeBatteryItem.insertedBattery != null) ? (activeBatteryItem.insertedBattery.charge * 100f) : 0f); float num7 = ((activeBatteryItem.insertedBattery != null) ? (activeBatteryItem.insertedBattery.charge * batteryUsage) : 0f); GUI.Label(new Rect((float)(num3 + 15), (float)(num4 + 30), (float)(num - 30), 20f), "Item Name: " + itemProperties.itemName, val2); GUI.Label(new Rect((float)(num3 + 15), (float)(num4 + 48), (float)(num - 30), 20f), "Vanilla Max Duration: " + num5.ToString("F1") + " seconds", val2); GUI.Label(new Rect((float)(num3 + 15), (float)(num4 + 66), (float)(num - 30), 20f), "Current Max Duration: " + batteryUsage.ToString("F1") + " seconds (" + (batteryUsage / num5).ToString("F2") + "x)", val2); string text6 = "Battery Charge: " + num6.ToString("F1") + "% (approx. " + num7.ToString("F1") + "s left)"; if (activeBatteryItem.insertedBattery != null && activeBatteryItem.insertedBattery.empty) { text6 = "Battery Charge: EMPTY (0.0s)"; } GUI.Label(new Rect((float)(num3 + 15), (float)(num4 + 84), (float)(num - 30), 20f), text6, val2); } } private PlayerControllerB GetLocalPlayer() { if ((Object)(object)GameNetworkManager.Instance != (Object)null && (Object)(object)GameNetworkManager.Instance.localPlayerController != (Object)null) { return GameNetworkManager.Instance.localPlayerController; } if ((Object)(object)StartOfRound.Instance != (Object)null && (Object)(object)StartOfRound.Instance.localPlayerController != (Object)null) { return StartOfRound.Instance.localPlayerController; } return null; } private GrabbableObject GetActiveBatteryItem(PlayerControllerB player) { if ((Object)(object)player.currentlyHeldObject != (Object)null && (Object)(object)player.currentlyHeldObject.itemProperties != (Object)null && player.currentlyHeldObject.itemProperties.requiresBattery) { return player.currentlyHeldObject; } if ((Object)(object)player.ItemOnlySlot != (Object)null && (Object)(object)player.ItemOnlySlot.itemProperties != (Object)null && player.ItemOnlySlot.itemProperties.requiresBattery) { return player.ItemOnlySlot; } if ((Object)(object)player.pocketedFlashlight != (Object)null && (Object)(object)player.pocketedFlashlight.itemProperties != (Object)null && player.pocketedFlashlight.itemProperties.requiresBattery) { return player.pocketedFlashlight; } if (player.ItemSlots != null && player.currentItemSlot >= 0 && player.currentItemSlot < player.ItemSlots.Length) { GrabbableObject val = player.ItemSlots[player.currentItemSlot]; if ((Object)(object)val != (Object)null && (Object)(object)val.itemProperties != (Object)null && val.itemProperties.requiresBattery) { return val; } } if (player.ItemSlots != null) { GrabbableObject result = null; for (int i = 0; i < player.ItemSlots.Length; i++) { GrabbableObject val2 = player.ItemSlots[i]; if ((Object)(object)val2 != (Object)null && (Object)(object)val2.itemProperties != (Object)null && val2.itemProperties.requiresBattery) { if (val2.isBeingUsed) { return val2; } result = val2; } } return result; } return null; } } public class MoreBatteryConfig : SyncedConfig2 { public bool Synced; [SyncedEntryField] public SyncedEntry BatteryMultiplier; [SyncedEntryField] public SyncedEntry ApplyToAllFlashlights; [SyncedEntryField] public SyncedEntry CustomItemNames; [SyncedEntryField] public SyncedEntry ExcludedItemNames; public MoreBatteryConfig(ConfigFile cfg) : base("MoreBattery") { EventHandler eventHandler = delegate { Synced = true; Plugin.Instance.Log.LogInfo((object)"MoreBattery: Configuration successfully synchronized with host!"); }; base.InitialSyncCompleted += eventHandler; BatteryMultiplier = Extensions.BindSyncedEntry(cfg, "General", "BatteryMultiplier", 1.5f, "The multiplier applied to the battery life (duration in seconds) of flashlights and light sources. 1.0 keeps it vanilla."); ApplyToAllFlashlights = Extensions.BindSyncedEntry(cfg, "General", "ApplyToAllFlashlights", true, "If true, automatically applies the battery multiplier to all items inheriting from FlashlightItem."); CustomItemNames = Extensions.BindSyncedEntry(cfg, "General", "CustomItemNames", "Lantern,Elite Flashlight,EliteFlashlight", "A comma-separated list of additional item names (case-insensitive) to apply the battery multiplier to."); ExcludedItemNames = Extensions.BindSyncedEntry(cfg, "General", "ExcludedItemNames", "", "A comma-separated list of item names to exclude from receiving the battery multiplier."); ConfigManager.Register((SyncedConfig2)this); } } public static class PluginInfo { public const string PLUGIN_GUID = "MoreBattery"; public const string PLUGIN_NAME = "MoreBattery"; public const string PLUGIN_VERSION = "1.2.6"; } } namespace MoreBatteryMod.Patches { [HarmonyPatch(typeof(GrabbableObject))] public static class MoreBatteryModPatches { public static readonly Dictionary OriginalDurations = new Dictionary(); private static readonly HashSet modifiedItems = new HashSet(); private static readonly HashSet customNamesList = new HashSet(StringComparer.OrdinalIgnoreCase); private static readonly HashSet excludedNamesList = new HashSet(StringComparer.OrdinalIgnoreCase); private static bool listsInitialized = false; private static void InitializeLists() { customNamesList.Clear(); excludedNamesList.Clear(); string value = Plugin.ConfigInstance.CustomItemNames.Value; if (!string.IsNullOrEmpty(value)) { string[] array = value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text in array) { string text2 = text.Trim(); if (!string.IsNullOrEmpty(text2)) { customNamesList.Add(text2); } } } string value2 = Plugin.ConfigInstance.ExcludedItemNames.Value; if (!string.IsNullOrEmpty(value2)) { string[] array2 = value2.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text3 in array2) { string text4 = text3.Trim(); if (!string.IsNullOrEmpty(text4)) { excludedNamesList.Add(text4); } } } listsInitialized = true; } [HarmonyPostfix] [HarmonyPatch("Start")] public static void MoreBatteryPatch(GrabbableObject __instance) { if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.itemProperties == (Object)null) { return; } Item itemProperties = __instance.itemProperties; if (!itemProperties.requiresBattery) { return; } if (!OriginalDurations.ContainsKey(itemProperties)) { OriginalDurations[itemProperties] = itemProperties.batteryUsage; } if (modifiedItems.Contains(itemProperties)) { return; } if (!listsInitialized) { InitializeLists(); } bool flag = false; if (Plugin.ConfigInstance.ApplyToAllFlashlights.Value && __instance is FlashlightItem) { flag = true; } if (!flag && !string.IsNullOrEmpty(itemProperties.itemName) && customNamesList.Contains(itemProperties.itemName)) { flag = true; } if (flag && !string.IsNullOrEmpty(itemProperties.itemName) && excludedNamesList.Contains(itemProperties.itemName)) { flag = false; } if (flag) { float batteryUsage = itemProperties.batteryUsage; float num = Plugin.ConfigInstance.BatteryMultiplier.Value; bool flag2 = !Plugin.ConfigInstance.Synced; bool flag3 = Plugin.ForceAntiCheatTest != null && Plugin.ForceAntiCheatTest.Value; if (flag2 || flag3) { string text = (flag3 ? "ForceAntiCheatTest is enabled" : "lobby is not synced (vanilla host)"); Plugin.Instance.Log.LogInfo((object)("[AntiCheat] Reverting multiplier to 1.0x — " + text)); num = 1f; } itemProperties.batteryUsage = batteryUsage * num; modifiedItems.Add(itemProperties); Plugin.Instance.Log.LogInfo((object)("Applied battery multiplier of " + num + "x to item: '" + itemProperties.itemName + "' (Original battery life: " + batteryUsage + "s -> New battery life: " + itemProperties.batteryUsage + "s)")); } } } }