using System; using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Photon.Pun; using UnityEngine; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: AssemblyVersion("0.0.0.0")] namespace RechargeableDefibroFix; [BepInPlugin("rechargeabledefibro.fix.runtime", "RechargeableDefibro Fix", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { internal static ManualLogSource Log; internal static ConfigEntry DebugLogging; internal static ConfigEntry ReplaceBatteryUpdate; internal static ConfigEntry SuppressBatteryErrors; internal static ConfigEntry KeepDefibroAfterUse; internal static ConfigEntry AllowRecharge; internal static ConfigEntry DisableAutoDrain; internal static ConfigEntry SuppressBatteryUi; internal static ConfigEntry ShowHeldBatteryUi; internal static ConfigEntry UseBatteryVisuals; internal static ConfigEntry BatteryBars; internal static ConfigEntry BatteryLifeOnSpawn; internal static ConfigEntry BatteryLifeAfterUse; internal static ConfigEntry ChargeMultiplier; private void Awake() { //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Expected O, but got Unknown //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Expected O, but got Unknown //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Expected O, but got Unknown //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Expected O, but got Unknown //IL_0208: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; DebugLogging = ((BaseUnityPlugin)this).Config.Bind("General", "DebugLogging", false, "Enable extra logs for RechargeableDefibro Fix."); ReplaceBatteryUpdate = ((BaseUnityPlugin)this).Config.Bind("Fixes", "ReplaceDefibroBatteryUpdate", true, "Use a safe battery update loop for Defibro instead of the vanilla ItemBattery.Update."); SuppressBatteryErrors = ((BaseUnityPlugin)this).Config.Bind("Fixes", "SuppressDefibroBatteryErrors", true, "Suppress Defibro ItemBattery exceptions after repairing the battery state."); KeepDefibroAfterUse = ((BaseUnityPlugin)this).Config.Bind("Defibro", "KeepDefibroAfterUse", true, "Keep Defibro as a rechargeable item after revive instead of letting it behave like a destroyed one."); AllowRecharge = ((BaseUnityPlugin)this).Config.Bind("Defibro", "AllowRecharge", true, "Allow charging stations to recharge Defibro."); DisableAutoDrain = ((BaseUnityPlugin)this).Config.Bind("Defibro", "DisableAutoDrain", true, "Prevent passive battery drain on Defibro."); SuppressBatteryUi = ((BaseUnityPlugin)this).Config.Bind("Defibro", "SuppressBatteryUi", false, "Legacy option for hiding Defibro battery UI when the safe update loop is disabled."); ShowHeldBatteryUi = ((BaseUnityPlugin)this).Config.Bind("Defibro", "ShowHeldBatteryUi", true, "Show the vanilla held-item battery UI for Defibro while using the safe update loop."); UseBatteryVisuals = ((BaseUnityPlugin)this).Config.Bind("Defibro", "UseBatteryVisuals", false, "Use vanilla battery bar visuals when the Defibro prefab has a BatteryVisualLogic component."); BatteryBars = ((BaseUnityPlugin)this).Config.Bind("Defibro", "BatteryBars", 1, new ConfigDescription("Number of battery bars Defibro uses.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 10), new object[0])); BatteryLifeOnSpawn = ((BaseUnityPlugin)this).Config.Bind("Defibro", "BatteryLifeOnSpawn", 100, new ConfigDescription("Battery life when Defibro is created.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), new object[0])); BatteryLifeAfterUse = ((BaseUnityPlugin)this).Config.Bind("Defibro", "BatteryLifeAfterUse", 0, new ConfigDescription("Battery life after a revive is fired.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), new object[0])); ChargeMultiplier = ((BaseUnityPlugin)this).Config.Bind("Defibro", "ChargeMultiplier", 1f, new ConfigDescription("Multiplier for charging speed applied only to Defibro.", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 10f), new object[0])); new Harmony("rechargeabledefibro.fix.runtime").PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Patched RechargeableDefibro battery handling."); } } internal static class ModLog { private static bool loggedMissingState; private static bool loggedSuppressedUpdate; private static bool loggedReactivated; public static void Debug(string message) { if (Plugin.DebugLogging != null && Plugin.DebugLogging.Value && Plugin.Log != null) { Plugin.Log.LogInfo((object)("[Debug] " + message)); } } public static void Warning(string message) { if (Plugin.Log != null) { Plugin.Log.LogWarning((object)message); } } public static void MissingState() { if (!loggedMissingState) { Warning("RechargeableDefibro state component was not found."); loggedMissingState = true; } } public static void SuppressedUpdate(Exception ex) { if (loggedSuppressedUpdate) { Debug("Suppressed another Defibro ItemBattery exception: " + ex.GetType().Name); return; } Warning("Suppressed a Defibro ItemBattery exception after repairing the battery state: " + ex.GetType().Name); loggedSuppressedUpdate = true; } public static void Reactivated() { if (loggedReactivated) { Debug("Defibro reactivated after recharge."); return; } Debug("Defibro reactivated after recharge."); loggedReactivated = true; } } internal static class DefibroBattery { private static readonly Type StateType = AccessTools.TypeByName("RechargeableDefibro.DefibroState"); private static readonly FieldInfo StateIsDepleted = ((StateType == null) ? null : AccessTools.Field(StateType, "isDepleted")); private static readonly FieldInfo StateReviveFired = ((StateType == null) ? null : AccessTools.Field(StateType, "reviveFired")); private static readonly MethodInfo HardResetVisuals = AccessTools.Method(typeof(ItemReviveItem), "HardResetVisuals", (Type[])null, (Type[])null); private static readonly MethodInfo BatteryUpdateBarsMethod = AccessTools.Method(typeof(ItemBattery), "BatteryUpdateBars", (Type[])null, (Type[])null); private static readonly MethodInfo BatteryFullPercentChangeMethod = AccessTools.Method(typeof(ItemBattery), "BatteryFullPercentChange", (Type[])null, (Type[])null); private static readonly MethodInfo BatteryFullPercentChangeLogicMethod = AccessTools.Method(typeof(ItemBattery), "BatteryFullPercentChangeLogic", (Type[])null, (Type[])null); private static readonly FieldInfo SuppressBatteryUiField = AccessTools.Field(typeof(ItemBattery), "suppressBatteryUI"); private static readonly FieldInfo DrainRateField = AccessTools.Field(typeof(ItemBattery), "drainRate"); private static readonly FieldInfo DrainTimerField = AccessTools.Field(typeof(ItemBattery), "drainTimer"); private static readonly FieldInfo ChargerListField = AccessTools.Field(typeof(ItemBattery), "chargerList"); private static readonly FieldInfo ItemAttributesField = AccessTools.Field(typeof(ItemBattery), "itemAttributes"); private static readonly FieldInfo PhotonViewField = AccessTools.Field(typeof(ItemBattery), "photonView"); private static readonly FieldInfo ItemEquippableField = AccessTools.Field(typeof(ItemBattery), "itemEquippable"); private static readonly FieldInfo PhysGrabObjectField = AccessTools.Field(typeof(ItemBattery), "physGrabObject"); private static readonly FieldInfo MainCameraField = AccessTools.Field(typeof(ItemBattery), "mainCamera"); private static readonly FieldInfo BatteryVisualLogicField = AccessTools.Field(typeof(ItemBattery), "batteryVisualLogic"); private static readonly FieldInfo ChargeTimerField = AccessTools.Field(typeof(ItemBattery), "chargeTimer"); private static readonly FieldInfo ChargeRateField = AccessTools.Field(typeof(ItemBattery), "chargeRate"); private static readonly FieldInfo IsChargingField = AccessTools.Field(typeof(ItemBattery), "isCharging"); private static readonly FieldInfo BatteryLifePrevField = AccessTools.Field(typeof(ItemBattery), "batteryLifePrev"); private static readonly FieldInfo BatteryLifeIntField = AccessTools.Field(typeof(ItemBattery), "batteryLifeInt"); private static readonly FieldInfo BatteryColorField = AccessTools.Field(typeof(ItemBattery), "batteryColor"); private static readonly FieldInfo BatteryColorMediumField = AccessTools.Field(typeof(ItemBattery), "batteryColorMedium"); private static readonly FieldInfo CurrentBarsField = AccessTools.Field(typeof(ItemBattery), "currentBars"); private static readonly FieldInfo BatteryLifeCountBarsField = AccessTools.Field(typeof(ItemBattery), "batteryLifeCountBars"); private static readonly FieldInfo BatteryLifeCountBarsPrevField = AccessTools.Field(typeof(ItemBattery), "batteryLifeCountBarsPrev"); private static readonly FieldInfo MapToolActiveField = AccessTools.Field(typeof(MapToolController), "Active"); private static readonly FieldInfo GrabbedPhysGrabObjectField = AccessTools.Field(typeof(PhysGrabber), "grabbedPhysGrabObject"); private static readonly FieldInfo BatteryVisualCurrentBarsField = AccessTools.Field(typeof(BatteryVisualLogic), "currentBars"); private static readonly FieldInfo InventorySpotBatteryVisualLogicField = AccessTools.Field(typeof(InventorySpot), "batteryVisualLogic"); private static readonly FieldInfo ItemAttributesColorPresetField = AccessTools.Field(typeof(ItemAttributes), "colorPreset"); private static readonly Type ColorPresetsType = AccessTools.TypeByName("ColorPresets"); private static readonly MethodInfo ColorPresetGetColorLightMethod = ((ColorPresetsType == null) ? null : AccessTools.Method(ColorPresetsType, "GetColorLight", (Type[])null, (Type[])null)); private static readonly MethodInfo ColorPresetGetColorMainMethod = ((ColorPresetsType == null) ? null : AccessTools.Method(ColorPresetsType, "GetColorMain", (Type[])null, (Type[])null)); private static readonly Color DefaultBatteryColor = new Color(1f, 1f, 0f, 1f); private static readonly Color DefaultBatteryMediumColor = new Color(1f, 0.75f, 0f, 1f); public static bool IsDefibroBattery(ItemBattery battery) { if ((Object)(object)battery != (Object)null) { return (Object)(object)((Component)battery).GetComponent() != (Object)null; } return false; } public static void Repair(ItemBattery battery, bool initial) { if (IsDefibroBattery(battery)) { int batteryBars = Mathf.Max(1, Plugin.BatteryBars.Value); battery.batteryBars = batteryBars; battery.isUnchargable = !Plugin.AllowRecharge.Value; BatteryVisualLogic batteryVisualLogic = GetBatteryVisualLogic(battery); battery.hasBatteryVisuals = Plugin.UseBatteryVisuals.Value && (Object)(object)batteryVisualLogic != (Object)null; SetField(SuppressBatteryUiField, battery, !ShouldShowHeldBatteryUi() || Plugin.SuppressBatteryUi.Value); if (Plugin.DisableAutoDrain.Value) { battery.autoDrain = false; battery.batteryDrainRate = 0f; SetField(DrainRateField, battery, 0f); SetField(DrainTimerField, battery, 0f); } if (GetChargerList(battery) == null) { SetField(ChargerListField, battery, new List()); } if ((Object)(object)GetField(ItemAttributesField, battery) == (Object)null) { SetField(ItemAttributesField, battery, ((Component)battery).GetComponent()); } if ((Object)(object)GetField(PhotonViewField, battery) == (Object)null) { SetField(PhotonViewField, battery, ((Component)battery).GetComponent()); } if ((Object)(object)GetField(ItemEquippableField, battery) == (Object)null) { SetField(ItemEquippableField, battery, GetItemEquippable(battery)); } if ((Object)(object)GetPhysGrabObject(battery) == (Object)null) { SetField(PhysGrabObjectField, battery, ((Component)battery).GetComponentInChildren(true)); } if ((Object)(object)GetField(MainCameraField, battery) == (Object)null) { SetField(MainCameraField, battery, Camera.main); } if ((Object)(object)batteryVisualLogic == (Object)null) { SetField(BatteryVisualLogicField, battery, ((Component)battery).GetComponentInChildren(true)); } if ((Object)(object)GetBatteryVisualLogic(battery) == (Object)null) { battery.hasBatteryVisuals = false; } if (initial && battery.batteryLife <= 1f) { battery.batteryLife = Plugin.BatteryLifeOnSpawn.Value; } battery.batteryLife = Mathf.Clamp(battery.batteryLife, 0f, 100f); ApplyVanillaBatteryColors(battery); ApplyCounts(battery, notifyChange: false); } } public static void Update(ItemBattery battery) { Repair(battery, initial: false); if (Plugin.AllowRecharge.Value && SemiFunc.IsMasterClientOrSingleplayer()) { float field = GetField(ChargeTimerField, battery, 0f); float field2 = GetField(ChargeRateField, battery, 0f); bool field3 = GetField(IsChargingField, battery, fallback: false); if (field > 0f && battery.batteryLife < 100f) { SetField(IsChargingField, battery, true); battery.batteryLife = Mathf.Clamp(battery.batteryLife + field2 * Plugin.ChargeMultiplier.Value * Time.deltaTime, 0f, 100f); SetField(ChargeTimerField, battery, Mathf.Max(0f, field - Time.deltaTime)); } else if (field2 != 0f || field3) { SetField(ChargeRateField, battery, 0f); SetField(ChargeTimerField, battery, 0f); SetField(IsChargingField, battery, false); GetChargerList(battery)?.Clear(); } } ApplyCounts(battery, notifyChange: true); ReactivateIfReady(battery); ShowHeldBatteryUi(battery); if (battery.hasBatteryVisuals && (Object)(object)GetBatteryVisualLogic(battery) != (Object)null && BatteryUpdateBarsMethod != null) { BatteryUpdateBarsMethod.Invoke(battery, new object[1] { GetBatteryLifeInt(battery) }); } } public static void SetAfterUse(ItemBattery battery) { if (IsDefibroBattery(battery) && Plugin.KeepDefibroAfterUse.Value) { Repair(battery, initial: false); battery.batteryLife = Mathf.Clamp(Plugin.BatteryLifeAfterUse.Value, 0, 100); SetField(BatteryLifePrevField, battery, -1f); battery.batteryActive = true; SetField(IsChargingField, battery, false); SetField(ChargeRateField, battery, 0f); SetField(ChargeTimerField, battery, 0f); ApplyCounts(battery, notifyChange: true); PhysGrabObject physGrabObject = GetPhysGrabObject(battery); if ((Object)(object)physGrabObject != (Object)null) { physGrabObject.dead = false; } } } public static bool SetBatteryLife(ItemBattery battery, int life) { if (!IsDefibroBattery(battery)) { return true; } Repair(battery, initial: false); battery.batteryLife = Mathf.Clamp(life, 0, 100); SetField(BatteryLifePrevField, battery, -1f); ApplyCounts(battery, notifyChange: true); ReactivateIfReady(battery); return false; } public static bool CanRunBatteryVisualMethod(ItemBattery battery) { if (IsDefibroBattery(battery)) { if (battery.hasBatteryVisuals && (Object)(object)GetBatteryVisualLogic(battery) != (Object)null) { return !Plugin.SuppressBatteryUi.Value; } return false; } return true; } public static bool CanCharge(ItemBattery battery) { if (!IsDefibroBattery(battery)) { return true; } Repair(battery, initial: false); return Plugin.AllowRecharge.Value; } private static void ApplyCounts(ItemBattery battery, bool notifyChange) { int num = Mathf.Max(1, battery.batteryBars); int num2 = Mathf.Clamp(Mathf.RoundToInt(battery.batteryLife / (100f / (float)num)), 0, num); int field = GetField(BatteryLifeCountBarsPrevField, battery, GetBatteryLifeInt(battery)); SetField(BatteryLifeCountBarsField, battery, num2); SetField(BatteryLifeIntField, battery, num2); SetField(CurrentBarsField, battery, num2); if (notifyChange && num2 != field) { NotifyBatteryChanged(battery, num2, field < num2); SetField(BatteryLifeCountBarsPrevField, battery, num2); } else { SetField(BatteryLifeCountBarsPrevField, battery, num2); } } private static void ReactivateIfReady(ItemBattery battery) { if (IsDepleted(battery) && !(battery.batteryLife < 99f)) { SetDepleted(battery, value: false); SetReviveFired(battery, value: false); PhysGrabObject physGrabObject = GetPhysGrabObject(battery); if ((Object)(object)physGrabObject != (Object)null) { physGrabObject.dead = false; } ItemReviveItem component = ((Component)battery).GetComponent(); if ((Object)(object)component != (Object)null && HardResetVisuals != null) { HardResetVisuals.Invoke(component, null); } ModLog.Reactivated(); } } public static int GetBatteryLifeIntForUi(ItemBattery battery) { return Mathf.Clamp(GetBatteryLifeInt(battery), 0, Mathf.Max(1, ((Object)(object)battery == (Object)null) ? 1 : battery.batteryBars)); } public static void BindInventorySpotVisual(InventorySpot spot) { if (!((Object)(object)spot == (Object)null) && spot.IsOccupied()) { ItemBattery val = FindDefibroBattery((Component)(object)spot.CurrentItem); if (!((Object)(object)val == (Object)null)) { Repair(val, initial: false); BatteryVisualLogic visualLogic = (BatteryVisualLogic)((InventorySpotBatteryVisualLogicField == null) ? null : /*isinst with value type is only supported in some contexts*/); ApplyBatteryVisual(visualLogic, val, rebuild: true); } } } public static ItemBattery FindDefibroBattery(Component component) { if ((Object)(object)component == (Object)null) { return null; } ItemBattery component2 = component.GetComponent(); if (IsDefibroBattery(component2)) { return component2; } ItemReviveItem val = component.GetComponent(); if ((Object)(object)val == (Object)null) { val = component.GetComponentInParent(true); } if ((Object)(object)val == (Object)null) { val = component.GetComponentInChildren(true); } if ((Object)(object)val != (Object)null) { ItemBattery component3 = ((Component)val).GetComponent(); if (IsDefibroBattery(component3)) { return component3; } } ItemBattery componentInParent = component.GetComponentInParent(true); if (IsDefibroBattery(componentInParent)) { return componentInParent; } ItemBattery componentInChildren = component.GetComponentInChildren(true); if (!IsDefibroBattery(componentInChildren)) { return null; } return componentInChildren; } private static void ApplyVanillaBatteryColors(ItemBattery battery) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: 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_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: 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) ItemAttributes val = GetField(ItemAttributesField, battery); if ((Object)(object)val == (Object)null) { val = ((Component)battery).GetComponent(); if ((Object)(object)val != (Object)null) { SetField(ItemAttributesField, battery, val); } } Color val2 = DefaultBatteryColor; Color val3 = DefaultBatteryMediumColor; object obj = ((ItemAttributesColorPresetField == null || (Object)(object)val == (Object)null) ? null : ItemAttributesColorPresetField.GetValue(val)); if (obj != null && ColorPresetGetColorLightMethod != null && ColorPresetGetColorMainMethod != null) { try { Color val4 = (Color)ColorPresetGetColorLightMethod.Invoke(obj, null); Color val5 = (Color)ColorPresetGetColorMainMethod.Invoke(obj, null); if (IsVisibleColor(val4)) { val2 = val4; } if (IsVisibleColor(val5)) { val3 = val5; } } catch (Exception ex) { ModLog.Debug("Could not fetch Defibro battery colors from ColorPreset: " + ex.GetType().Name); } } SetField(BatteryColorField, battery, val2); SetField(BatteryColorMediumField, battery, val3); } private static bool IsVisibleColor(Color color) { if (color.a > 0.01f) { return color.r + color.g + color.b > 0.05f; } return false; } private static void ApplyBatteryVisual(BatteryVisualLogic visualLogic, ItemBattery battery, bool rebuild) { if ((Object)(object)visualLogic == (Object)null || (Object)(object)battery == (Object)null) { return; } try { if (!((Component)visualLogic).gameObject.activeSelf) { ((Component)visualLogic).gameObject.SetActive(true); } if ((Object)(object)visualLogic.itemBattery != (Object)(object)battery) { visualLogic.itemBattery = battery; rebuild = true; } if (visualLogic.batteryBars != battery.batteryBars) { rebuild = true; } if (rebuild) { visualLogic.BatteryBarsSet(); } visualLogic.BatteryBarsUpdate(GetBatteryLifeIntForUi(battery), true); } catch (Exception ex) { ModLog.Debug("Could not apply Defibro battery visual: " + ex.GetType().Name); } } private static int GetBatteryLifeInt(ItemBattery battery) { return GetField(BatteryLifeIntField, battery, 0); } private static bool ShouldShowHeldBatteryUi() { if (Plugin.ShowHeldBatteryUi != null) { return Plugin.ShowHeldBatteryUi.Value; } return false; } private static void ShowHeldBatteryUi(ItemBattery battery) { if (!ShouldShowHeldBatteryUi()) { return; } try { if (SemiFunc.RunIsShop() || SemiFunc.RunIsArena() || ((Object)(object)MapToolController.instance != (Object)null && GetObjectField(MapToolActiveField, MapToolController.instance, fallback: false))) { return; } PhysGrabObject physGrabObject = GetPhysGrabObject(battery); PhysGrabObject val = (((Object)(object)PhysGrabber.instance == (Object)null) ? null : GetObjectField(GrabbedPhysGrabObjectField, PhysGrabber.instance)); if ((Object)(object)physGrabObject == (Object)null || (Object)(object)PhysGrabber.instance == (Object)null || !PhysGrabber.instance.grabbed || (Object)(object)val != (Object)(object)physGrabObject) { return; } BatteryUI instance = BatteryUI.instance; if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.batteryVisualLogic == (Object)null)) { BatteryVisualLogic batteryVisualLogic = instance.batteryVisualLogic; bool flag = (Object)(object)batteryVisualLogic.itemBattery != (Object)(object)battery; if (flag) { batteryVisualLogic.itemBattery = battery; } int objectField = GetObjectField(BatteryVisualCurrentBarsField, batteryVisualLogic, -1); if (flag || batteryVisualLogic.batteryBars != battery.batteryBars || objectField != GetBatteryLifeIntForUi(battery)) { ApplyBatteryVisual(batteryVisualLogic, battery, rebuild: true); } else { ApplyBatteryVisual(batteryVisualLogic, battery, rebuild: false); } ((SemiUI)instance).Show(); } } catch (Exception ex) { ModLog.Debug("Could not show Defibro battery UI: " + ex.GetType().Name); } } private static void NotifyBatteryChanged(ItemBattery battery, int level, bool charging) { if (BatteryFullPercentChangeMethod == null) { SetField(BatteryLifeIntField, battery, level); SetField(CurrentBarsField, battery, level); return; } try { if ((Object)(object)GetField(PhotonViewField, battery) == (Object)null && BatteryFullPercentChangeLogicMethod != null) { BatteryFullPercentChangeLogicMethod.Invoke(battery, new object[2] { level, charging }); } else { BatteryFullPercentChangeMethod.Invoke(battery, new object[2] { level, charging }); } } catch (Exception ex) { ModLog.Debug("Could not run Defibro battery change callback: " + ex.GetType().Name); SetField(BatteryLifeIntField, battery, level); SetField(CurrentBarsField, battery, level); } } private static List GetChargerList(ItemBattery battery) { return GetField>(ChargerListField, battery); } private static BatteryVisualLogic GetBatteryVisualLogic(ItemBattery battery) { BatteryVisualLogic field = GetField(BatteryVisualLogicField, battery); if (!((Object)(object)field != (Object)null)) { return ((Component)battery).GetComponentInChildren(true); } return field; } private static PhysGrabObject GetPhysGrabObject(ItemBattery battery) { PhysGrabObject field = GetField(PhysGrabObjectField, battery); if ((Object)(object)field != (Object)null) { return field; } field = ((Component)battery).GetComponent(); if ((Object)(object)field != (Object)null) { return field; } field = ((Component)battery).GetComponentInChildren(true); if (!((Object)(object)field != (Object)null)) { return ((Component)battery).GetComponentInParent(true); } return field; } private static ItemEquippable GetItemEquippable(ItemBattery battery) { ItemEquippable component = ((Component)battery).GetComponent(); if ((Object)(object)component != (Object)null) { return component; } component = ((Component)battery).GetComponentInChildren(true); if (!((Object)(object)component != (Object)null)) { return ((Component)battery).GetComponentInParent(true); } return component; } private static T GetField(FieldInfo field, ItemBattery battery, T fallback = default(T)) { if (field == null || (Object)(object)battery == (Object)null) { return fallback; } object value = field.GetValue(battery); if (value == null) { return fallback; } if (!(value is T)) { return fallback; } return (T)value; } private static T GetObjectField(FieldInfo field, object instance, T fallback = default(T)) { if (field == null || instance == null) { return fallback; } object value = field.GetValue(instance); if (value == null) { return fallback; } if (!(value is T)) { return fallback; } return (T)value; } private static void SetField(FieldInfo field, ItemBattery battery, object value) { if (field != null && (Object)(object)battery != (Object)null) { field.SetValue(battery, value); } } private static bool IsDepleted(ItemBattery battery) { Component state = GetState(battery); if ((Object)(object)state != (Object)null && StateIsDepleted != null) { return (bool)StateIsDepleted.GetValue(state); } return false; } private static void SetDepleted(ItemBattery battery, bool value) { Component state = GetState(battery); if ((Object)(object)state != (Object)null && StateIsDepleted != null) { StateIsDepleted.SetValue(state, value); } } private static void SetReviveFired(ItemBattery battery, bool value) { Component state = GetState(battery); if ((Object)(object)state != (Object)null && StateReviveFired != null) { StateReviveFired.SetValue(state, value); } } private static Component GetState(ItemBattery battery) { if (StateType == null || (Object)(object)battery == (Object)null) { ModLog.MissingState(); return null; } Component component = ((Component)battery).GetComponent(StateType); if ((Object)(object)component != (Object)null) { return component; } return ((Component)battery).gameObject.AddComponent(StateType); } } [HarmonyPatch(typeof(ItemReviveItem), "Start")] internal static class ItemReviveItemStartPatch { private static void Postfix(ItemReviveItem __instance) { ItemBattery battery = (((Object)(object)__instance == (Object)null) ? null : ((Component)__instance).GetComponent()); DefibroBattery.Repair(battery, initial: true); } } [HarmonyPatch(typeof(ItemReviveItem), "ReviveAndDestroy")] internal static class ItemReviveItemReviveAndDestroyPatch { private static void Postfix(ItemReviveItem __instance) { ItemBattery afterUse = (((Object)(object)__instance == (Object)null) ? null : ((Component)__instance).GetComponent()); DefibroBattery.SetAfterUse(afterUse); } } [HarmonyPatch(typeof(ItemBattery), "Update")] internal static class ItemBatteryUpdatePatch { private static bool Prefix(ItemBattery __instance) { if (!DefibroBattery.IsDefibroBattery(__instance) || !Plugin.ReplaceBatteryUpdate.Value) { return true; } DefibroBattery.Update(__instance); return false; } private static Exception Finalizer(Exception __exception, ItemBattery __instance) { if (__exception == null || !DefibroBattery.IsDefibroBattery(__instance) || !Plugin.SuppressBatteryErrors.Value) { return __exception; } DefibroBattery.Repair(__instance, initial: false); ModLog.SuppressedUpdate(__exception); return null; } } [HarmonyPatch(typeof(InventorySpot), "StateOccupied")] internal static class InventorySpotStateOccupiedPatch { private static void Postfix(InventorySpot __instance) { DefibroBattery.BindInventorySpotVisual(__instance); } } [HarmonyPatch(typeof(Inventory), "GetBatteryStateFromInventorySpot")] internal static class InventoryGetBatteryStateFromInventorySpotPatch { private static void Postfix(Inventory __instance, int index, ref int __result) { if ((Object)(object)__instance == (Object)null) { return; } InventorySpot spotByIndex = __instance.GetSpotByIndex(index); if (!((Object)(object)spotByIndex == (Object)null) && spotByIndex.IsOccupied()) { ItemEquippable currentItem = spotByIndex.CurrentItem; ItemBattery val = DefibroBattery.FindDefibroBattery((Component)(object)currentItem); if (!((Object)(object)val == (Object)null)) { DefibroBattery.Repair(val, initial: false); __result = DefibroBattery.GetBatteryLifeIntForUi(val); } } } } [HarmonyPatch(typeof(ItemBattery), "SetBatteryLife")] internal static class ItemBatterySetBatteryLifePatch { private static bool Prefix(ItemBattery __instance, int _batteryLife) { return DefibroBattery.SetBatteryLife(__instance, _batteryLife); } } [HarmonyPatch(typeof(ItemBattery), "ChargeBattery")] internal static class ItemBatteryChargeBatteryPatch { private static bool Prefix(ItemBattery __instance) { return DefibroBattery.CanCharge(__instance); } private static void Postfix(ItemBattery __instance) { if (DefibroBattery.IsDefibroBattery(__instance)) { DefibroBattery.Repair(__instance, initial: false); } } } [HarmonyPatch(typeof(ItemBattery), "BatteryLookAt")] internal static class ItemBatteryLookAtPatch { private static bool Prefix(ItemBattery __instance) { return DefibroBattery.CanRunBatteryVisualMethod(__instance); } } [HarmonyPatch(typeof(ItemBattery), "BatteryChargingVisuals")] internal static class ItemBatteryChargingVisualsPatch { private static bool Prefix(ItemBattery __instance) { return DefibroBattery.CanRunBatteryVisualMethod(__instance); } } [HarmonyPatch(typeof(ItemBattery), "BatteryUpdateBars")] internal static class ItemBatteryUpdateBarsPatch { private static bool Prefix(ItemBattery __instance) { return DefibroBattery.CanRunBatteryVisualMethod(__instance); } }