using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("WeedKillerRefill")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.8.0")] [assembly: AssemblyInformationalVersion("1.0.8")] [assembly: AssemblyProduct("WeedKillerRefill")] [assembly: AssemblyTitle("WeedKillerRefill")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.8.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace WeedKillerRefill { internal static class InputUtil { private static readonly Dictionary KeyMap = new Dictionary { { (KeyCode)97, (Key)15 }, { (KeyCode)98, (Key)16 }, { (KeyCode)99, (Key)17 }, { (KeyCode)100, (Key)18 }, { (KeyCode)101, (Key)19 }, { (KeyCode)102, (Key)20 }, { (KeyCode)103, (Key)21 }, { (KeyCode)104, (Key)22 }, { (KeyCode)105, (Key)23 }, { (KeyCode)106, (Key)24 }, { (KeyCode)107, (Key)25 }, { (KeyCode)108, (Key)26 }, { (KeyCode)109, (Key)27 }, { (KeyCode)110, (Key)28 }, { (KeyCode)111, (Key)29 }, { (KeyCode)112, (Key)30 }, { (KeyCode)113, (Key)31 }, { (KeyCode)114, (Key)32 }, { (KeyCode)115, (Key)33 }, { (KeyCode)116, (Key)34 }, { (KeyCode)117, (Key)35 }, { (KeyCode)118, (Key)36 }, { (KeyCode)119, (Key)37 }, { (KeyCode)120, (Key)38 }, { (KeyCode)121, (Key)39 }, { (KeyCode)122, (Key)40 }, { (KeyCode)48, (Key)50 }, { (KeyCode)49, (Key)41 }, { (KeyCode)50, (Key)42 }, { (KeyCode)51, (Key)43 }, { (KeyCode)52, (Key)44 }, { (KeyCode)53, (Key)45 }, { (KeyCode)54, (Key)46 }, { (KeyCode)55, (Key)47 }, { (KeyCode)56, (Key)48 }, { (KeyCode)57, (Key)49 }, { (KeyCode)32, (Key)1 }, { (KeyCode)304, (Key)51 }, { (KeyCode)303, (Key)52 }, { (KeyCode)306, (Key)55 }, { (KeyCode)305, (Key)56 }, { (KeyCode)308, (Key)53 }, { (KeyCode)307, (Key)54 }, { (KeyCode)9, (Key)3 }, { (KeyCode)301, (Key)72 }, { (KeyCode)8, (Key)65 }, { (KeyCode)13, (Key)2 }, { (KeyCode)27, (Key)60 }, { (KeyCode)273, (Key)63 }, { (KeyCode)274, (Key)64 }, { (KeyCode)276, (Key)61 }, { (KeyCode)275, (Key)62 }, { (KeyCode)277, (Key)70 }, { (KeyCode)127, (Key)71 }, { (KeyCode)278, (Key)68 }, { (KeyCode)279, (Key)69 }, { (KeyCode)280, (Key)67 }, { (KeyCode)281, (Key)66 }, { (KeyCode)282, (Key)94 }, { (KeyCode)283, (Key)95 }, { (KeyCode)284, (Key)96 }, { (KeyCode)285, (Key)97 }, { (KeyCode)286, (Key)98 }, { (KeyCode)287, (Key)99 }, { (KeyCode)288, (Key)100 }, { (KeyCode)289, (Key)101 }, { (KeyCode)290, (Key)102 }, { (KeyCode)291, (Key)103 }, { (KeyCode)292, (Key)104 }, { (KeyCode)293, (Key)105 } }; private static bool _wasDown; private static int _edgeFrame = -1; private static bool _edgeResult; public static bool WasPressedThisFrame(KeyCode keyCode) { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 //IL_004d: 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) int frameCount = Time.frameCount; if (frameCount == _edgeFrame) { return _edgeResult; } _edgeFrame = frameCount; try { Keyboard current = Keyboard.current; if (current != null && (int)keyCode == 114 && ((ButtonControl)current.rKey).wasPressedThisFrame) { _edgeResult = true; _wasDown = true; return true; } if (current != null && KeyMap.TryGetValue(keyCode, out var value)) { KeyControl val = current[value]; if (val != null && ((ButtonControl)val).wasPressedThisFrame) { _edgeResult = true; _wasDown = true; return true; } } } catch { } try { if (Input.GetKeyDown(keyCode)) { _edgeResult = true; _wasDown = true; return true; } } catch { } bool num = IsDown(keyCode); _edgeResult = num && !_wasDown; _wasDown = num; return _edgeResult; } public static bool IsDown(KeyCode keyCode) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) try { Keyboard current = Keyboard.current; if (current != null) { if ((int)keyCode == 114 && ((ButtonControl)current.rKey).isPressed) { return true; } if (KeyMap.TryGetValue(keyCode, out var value)) { KeyControl val = current[value]; if (val != null && ((ButtonControl)val).isPressed) { return true; } } } } catch { } try { if (Input.GetKey(keyCode)) { return true; } } catch { } return false; } public unsafe static string TipLabel(KeyCode keyCode) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Invalid comparison between Unknown and I4 //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 //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_0030: Expected I4, but got Unknown //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Invalid comparison between Unknown and I4 //IL_0066: 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_006a: Unknown result type (might be due to invalid IL or missing references) KeyCode val = keyCode; if ((int)val != 13) { if ((int)val != 27) { switch (val - 303) { case 0: case 1: return "Shift"; case 2: case 3: return "Ctrl"; case 4: case 5: return "Alt"; default: if ((int)keyCode >= 48 && (int)keyCode <= 57) { return ((char)(48 + (keyCode - 48))).ToString(); } return ((object)(*(KeyCode*)(&keyCode))/*cast due to .constrained prefix*/).ToString(); } } return "Esc"; } return "Enter"; } } [HarmonyPatch(typeof(SprayPaintItem), "ItemInteractLeftRight")] internal static class SprayPaintShakeRefillPatch { [HarmonyPostfix] private static void Postfix(SprayPaintItem __instance, bool right) { if (!(!Plugin.Enabled.Value || right) && __instance.isWeedKillerSprayBottle && WeedKillerUtil.IsHeldByLocalPlayer(__instance) && !__instance.isSpraying) { if (Plugin.OnlyWhenEmpty.Value && !WeedKillerUtil.IsEmpty(__instance)) { __instance.sprayCanShakeMeter = 1f; return; } WeedKillerUtil.Refill(__instance, "Shake.Q"); WeedKillerUtil.PlayShakeFeedback(__instance); } } } [HarmonyPatch(typeof(SprayPaintItem), "LateUpdate")] internal static class SprayPaintLateUpdatePatch { [HarmonyPostfix] private static void Postfix(SprayPaintItem __instance) { if (Plugin.Enabled.Value && Plugin.AllowKeyRefill.Value && __instance.isWeedKillerSprayBottle && WeedKillerUtil.IsHeldByLocalPlayer(__instance)) { RefillController.TickHeld(__instance, "Spray.LateUpdate"); } } } [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] internal static class PlayerLateUpdateRefillPatch { [HarmonyPostfix] private static void Postfix(PlayerControllerB __instance) { if (Plugin.AllowKeyRefill.Value && !((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController)) { RefillController.Tick("Player.LateUpdate"); } } } [HarmonyPatch(typeof(StartOfRound), "Start")] internal static class StartOfRoundEnsurePatch { [HarmonyPostfix] private static void Postfix() { WeedKillerRefillBehaviour.EnsureExists(); Plugin.Log.LogInfo((object)"[StartOfRound.Start] refill behaviour ensured"); } } [HarmonyPatch(typeof(HUDManager), "Start")] internal static class HudManagerEnsurePatch { [HarmonyPostfix] private static void Postfix() { WeedKillerRefillBehaviour.EnsureExists(); } } [HarmonyPatch(typeof(GrabbableObject), "ChargeBatteries")] internal static class ChargeBatteriesTankSyncPatch { [HarmonyPostfix] private static void Postfix(GrabbableObject __instance) { SprayPaintItem val = (SprayPaintItem)(object)((__instance is SprayPaintItem) ? __instance : null); if (val == null || !val.isWeedKillerSprayBottle) { return; } try { Battery insertedBattery = ((GrabbableObject)val).insertedBattery; if (insertedBattery != null && insertedBattery.charge > val.sprayCanTank) { val.sprayCanTank = insertedBattery.charge; val.sprayCanShakeMeter = 1f; val.tryingToUseEmptyCan = insertedBattery.charge <= Plugin.EmptyThreshold.Value; Plugin.V($"[ChargeBatteries] synced tank={val.sprayCanTank:0.###} from battery"); } } catch { } } } [BepInPlugin("com.benhough.lethal.WeedKillerRefill", "WeedKillerRefill", "1.0.8")] public class Plugin : BaseUnityPlugin { public const string ModGuid = "com.benhough.lethal.WeedKillerRefill"; public const string ModName = "WeedKillerRefill"; public const string ModVersion = "1.0.8"; private readonly Harmony _harmony = new Harmony("com.benhough.lethal.WeedKillerRefill"); internal static Plugin Instance { get; private set; } internal static ManualLogSource Log { get; private set; } internal static ConfigEntry Enabled { get; private set; } internal static ConfigEntry RefillKey { get; private set; } internal static ConfigEntry EmptyThreshold { get; private set; } internal static ConfigEntry ShowControlTip { get; private set; } internal static ConfigEntry OnlyWhenEmpty { get; private set; } internal static ConfigEntry Verbose { get; private set; } internal static ConfigEntry AllowKeyRefill { get; private set; } private void Awake() { //IL_0161: Unknown result type (might be due to invalid IL or missing references) Instance = this; Log = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind("General", "Enabled", true, "Allow refilling weed killer with the configured key."); RefillKey = ((BaseUnityPlugin)this).Config.Bind("General", "RefillKey", (KeyCode)114, "Key to refill a held weed killer."); EmptyThreshold = ((BaseUnityPlugin)this).Config.Bind("General", "EmptyThreshold", 0.05f, "Tank/battery charge at or below this counts as empty (0–1)."); OnlyWhenEmpty = ((BaseUnityPlugin)this).Config.Bind("General", "OnlyWhenEmpty", true, "If true, refill only works when empty. If false, always tops off on key press."); ShowControlTip = ((BaseUnityPlugin)this).Config.Bind("General", "ShowControlTip", true, "Show a fixed bottom-screen tip (Refill : [R]) when holding an empty weed killer."); Verbose = ((BaseUnityPlugin)this).Config.Bind("General", "VerboseLogging", true, "Log holding/key/refill traces."); AllowKeyRefill = ((BaseUnityPlugin)this).Config.Bind("General", "AllowKeyRefill", true, "Allow refill with RefillKey (default R)."); try { _harmony.PatchAll(typeof(Plugin).Assembly); Log.LogInfo((object)"Harmony patches applied (R key refill + ChargeBatteries sync)."); } catch (Exception ex) { Log.LogWarning((object)("Harmony patch failed: " + ex.Message)); } WeedKillerRefillBehaviour.EnsureExists(); RefillTipHud.EnsureExists(); Log.LogInfo((object)string.Format("{0} v{1} loaded. Press {2} to refill.", "WeedKillerRefill", "1.0.8", RefillKey.Value)); } internal static void V(string msg) { if (Verbose != null && Verbose.Value) { Log.LogInfo((object)msg); } } } internal static class PluginInfo { public const string PLUGIN_GUID = "com.benhough.lethal.WeedKillerRefill"; public const string PLUGIN_NAME = "WeedKillerRefill"; public const string PLUGIN_VERSION = "1.0.8"; } internal static class RefillController { private static bool _loggedHoldingEmpty; private static float _nextHeartbeat; private static int _lastRefillFrame = -1; internal static void Tick(string source) { if (Plugin.Enabled != null && Plugin.Enabled.Value && Plugin.AllowKeyRefill.Value) { if (!WeedKillerUtil.TryGetHeldWeedKiller(out SprayPaintItem spray)) { _loggedHoldingEmpty = false; } else { TickHeld(spray, source); } } } internal static void TickHeld(SprayPaintItem spray, string source) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: 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) if (Plugin.Enabled == null || !Plugin.Enabled.Value || (Object)(object)spray == (Object)null || !Plugin.AllowKeyRefill.Value) { return; } bool flag = WeedKillerUtil.IsEmpty(spray); if (flag && !_loggedHoldingEmpty) { _loggedHoldingEmpty = true; Plugin.Log.LogInfo((object)$"[{source}] Holding empty weed killer (tank={spray.sprayCanTank:0.###}). Press {Plugin.RefillKey.Value} to refill."); } else if (!flag) { _loggedHoldingEmpty = false; } if (Time.unscaledTime >= _nextHeartbeat) { _nextHeartbeat = Time.unscaledTime + 8f; Plugin.V($"[{source}] holding weedkiller empty={flag} tank={spray.sprayCanTank:0.###} keyDown={InputUtil.IsDown(Plugin.RefillKey.Value)}"); } if (!InputUtil.WasPressedThisFrame(Plugin.RefillKey.Value)) { return; } int frameCount = Time.frameCount; if (frameCount == _lastRefillFrame) { return; } _lastRefillFrame = frameCount; Plugin.Log.LogInfo((object)$"[{source}] Refill key {Plugin.RefillKey.Value} pressed (empty={flag}, tank={spray.sprayCanTank:0.###})."); if (Plugin.OnlyWhenEmpty.Value && !flag) { return; } try { WeedKillerUtil.Refill(spray, source); WeedKillerUtil.PlayShakeFeedback(spray); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[" + source + "] Failed to refill: " + ex.Message)); } } } internal sealed class RefillTipHud : MonoBehaviour { private static RefillTipHud? _instance; private Canvas? _canvas; private TextMeshProUGUI? _label; private string _lastText = ""; internal 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("WeedKillerRefillTipHud"); Object.DontDestroyOnLoad((Object)val); _instance = val.AddComponent(); } } private void Awake() { _instance = this; BuildUi(); } private void OnDestroy() { if ((Object)(object)_instance == (Object)(object)this) { _instance = null; } } private void BuildUi() { //IL_0049: 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_007d: Expected O, but got Unknown //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: 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_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) _canvas = ((Component)this).gameObject.AddComponent(); _canvas.renderMode = (RenderMode)0; _canvas.sortingOrder = 4800; CanvasScaler obj = ((Component)this).gameObject.AddComponent(); obj.uiScaleMode = (ScaleMode)1; obj.referenceResolution = new Vector2(1920f, 1080f); ((Component)this).gameObject.AddComponent(); GameObject val = new GameObject("RefillTipLabel", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(((Component)this).transform, false); RectTransform component = val.GetComponent(); component.anchorMin = new Vector2(0.5f, 0.08f); component.anchorMax = new Vector2(0.5f, 0.08f); component.pivot = new Vector2(0.5f, 0.5f); component.sizeDelta = new Vector2(480f, 40f); component.anchoredPosition = Vector2.zero; _label = val.AddComponent(); ((TMP_Text)_label).alignment = (TextAlignmentOptions)514; ((TMP_Text)_label).fontStyle = (FontStyles)1; ((TMP_Text)_label).fontSize = 22f; ((Graphic)_label).color = new Color(0.75f, 0.85f, 1f, 1f); ((TMP_Text)_label).enableWordWrapping = false; ((Graphic)_label).raycastTarget = false; ((TMP_Text)_label).overflowMode = (TextOverflowModes)0; ((TMP_Text)_label).text = ""; TryAssignFont(); ((Behaviour)_canvas).enabled = false; } private void TryAssignFont() { if ((Object)(object)_label == (Object)null) { return; } try { HUDManager instance = HUDManager.Instance; TMP_FontAsset val = null; if (instance?.controlTipLines != null) { TextMeshProUGUI[] controlTipLines = instance.controlTipLines; foreach (TextMeshProUGUI val2 in controlTipLines) { if ((Object)(object)val2 != (Object)null && (Object)(object)((TMP_Text)val2).font != (Object)null) { val = ((TMP_Text)val2).font; break; } } } if ((Object)(object)val == (Object)null && (Object)(object)instance?.weightCounter != (Object)null) { val = ((TMP_Text)instance.weightCounter).font; } if ((Object)(object)val == (Object)null && (Object)(object)TMP_Settings.defaultFontAsset != (Object)null) { val = TMP_Settings.defaultFontAsset; } if ((Object)(object)val != (Object)null) { ((TMP_Text)_label).font = val; } } catch { } } private void LateUpdate() { if ((Object)(object)_canvas == (Object)null || (Object)(object)_label == (Object)null) { BuildUi(); } EnsureExists(); Refresh(); } private void Refresh() { //IL_0096: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_canvas == (Object)null || (Object)(object)_label == (Object)null) { return; } if (Plugin.ShowControlTip == null || !Plugin.ShowControlTip.Value || Plugin.Enabled == null || !Plugin.Enabled.Value || Plugin.AllowKeyRefill == null || !Plugin.AllowKeyRefill.Value) { SetVisible(visible: false); return; } if (!WeedKillerUtil.TryGetHeldWeedKiller(out SprayPaintItem spray)) { SetVisible(visible: false); return; } if (Plugin.OnlyWhenEmpty.Value && !WeedKillerUtil.IsEmpty(spray)) { SetVisible(visible: false); return; } TryAssignFont(); string text = InputUtil.TipLabel(Plugin.RefillKey.Value); string text2 = "Refill : [" + text + "]"; if (text2 != _lastText) { ((TMP_Text)_label).text = text2; _lastText = text2; } SetVisible(visible: true); } private void SetVisible(bool visible) { if ((Object)(object)_canvas != (Object)null && ((Behaviour)_canvas).enabled != visible) { ((Behaviour)_canvas).enabled = visible; } if ((Object)(object)_label != (Object)null && ((Component)_label).gameObject.activeSelf != visible) { ((Component)_label).gameObject.SetActive(visible); } } } internal sealed class WeedKillerRefillBehaviour : MonoBehaviour { private static WeedKillerRefillBehaviour? _instance; private float _nextAliveLog; internal 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("WeedKillerRefill"); Object.DontDestroyOnLoad((Object)val); _instance = val.AddComponent(); RefillTipHud.EnsureExists(); Plugin.Log.LogInfo((object)"[Behaviour] created"); } } private void Awake() { _instance = this; } private void OnDestroy() { if ((Object)(object)_instance == (Object)(object)this) { _instance = null; } } private void LateUpdate() { if (Time.unscaledTime >= _nextAliveLog) { _nextAliveLog = Time.unscaledTime + 30f; Plugin.V("[Behaviour] LateUpdate alive"); } RefillController.Tick("Behaviour.LateUpdate"); } } internal static class WeedKillerUtil { public static bool TryGetHeldWeedKiller(out SprayPaintItem spray) { spray = null; try { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val == (Object)null || val.isPlayerDead) { return false; } GrabbableObject val2 = val.currentlyHeldObject; if ((Object)(object)val2 == (Object)null) { val2 = val.currentlyHeldObjectServer; } SprayPaintItem val3 = (SprayPaintItem)(object)((val2 is SprayPaintItem) ? val2 : null); if (val3 == null) { return false; } if (!val3.isWeedKillerSprayBottle) { return false; } spray = val3; return true; } catch { return false; } } public static bool IsHeldByLocalPlayer(SprayPaintItem spray) { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val == (Object)null || (Object)(object)spray == (Object)null) { return false; } if (!((Object)(object)(val.currentlyHeldObject ?? val.currentlyHeldObjectServer) == (Object)(object)spray)) { return (Object)(object)((GrabbableObject)spray).playerHeldBy == (Object)(object)val; } return true; } public static bool IsEmpty(SprayPaintItem spray) { float value = Plugin.EmptyThreshold.Value; if (spray.sprayCanTank <= value) { return true; } if (spray.tryingToUseEmptyCan) { return true; } try { Battery insertedBattery = ((GrabbableObject)spray).insertedBattery; if (insertedBattery != null && (insertedBattery.empty || insertedBattery.charge <= value)) { return true; } } catch { } return false; } public static void Refill(SprayPaintItem spray, string source) { spray.sprayCanTank = 1f; spray.sprayCanShakeMeter = 1f; spray.tryingToUseEmptyCan = false; try { if ((Object)(object)spray.sprayCanNeedsShakingParticle != (Object)null && spray.sprayCanNeedsShakingParticle.isPlaying) { spray.sprayCanNeedsShakingParticle.Stop(true, (ParticleSystemStopBehavior)0); } } catch { } try { Battery insertedBattery = ((GrabbableObject)spray).insertedBattery; if (insertedBattery != null) { insertedBattery.charge = 1f; insertedBattery.empty = false; ((GrabbableObject)spray).insertedBattery = insertedBattery; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Battery refill partial: " + ex.Message)); } try { if ((Object)(object)((GrabbableObject)spray).itemProperties != (Object)null && ((GrabbableObject)spray).itemProperties.requiresBattery) { ((GrabbableObject)spray).SyncBatteryServerRpc(100); } } catch (Exception ex2) { Plugin.Log.LogWarning((object)("SyncBatteryServerRpc failed: " + ex2.Message)); } try { ((GrabbableObject)spray).ChargeBatteries(); } catch { } try { ((GrabbableObject)spray).SetControlTipsForItem(); } catch { } Plugin.Log.LogInfo((object)$"[{source}] Refilled: tank={spray.sprayCanTank:0.###} shake={spray.sprayCanShakeMeter:0.###} tryingEmpty={spray.tryingToUseEmptyCan}"); } public static void PlayShakeFeedback(SprayPaintItem spray) { try { if ((Object)(object)((GrabbableObject)spray).playerHeldBy != (Object)null) { ((GrabbableObject)spray).playerHeldBy.playerBodyAnimator.SetTrigger("shakeItem"); } } catch { } try { if (spray.sprayCanShakeSFX != null && spray.sprayCanShakeSFX.Length != 0 && (Object)(object)spray.sprayAudio != (Object)null) { RoundManager.PlayRandomClip(spray.sprayAudio, spray.sprayCanShakeSFX, true, 1f, 0, 1000); if ((Object)(object)spray.sprayCanShakeEmptySFX != (Object)null) { WalkieTalkie.TransmitOneShotAudio(spray.sprayAudio, spray.sprayCanShakeEmptySFX, 1f); } } } catch { } } } }