diff --git a/EXILED/Exiled.Events/EventArgs/Player/MicroHIDOpeningDoorEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/MicroHIDOpeningDoorEventArgs.cs new file mode 100644 index 0000000000..a8bf27b722 --- /dev/null +++ b/EXILED/Exiled.Events/EventArgs/Player/MicroHIDOpeningDoorEventArgs.cs @@ -0,0 +1,61 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) ExMod Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.Events.EventArgs.Player +{ + using Exiled.API.Features.Doors; + using Exiled.API.Features.Items; + using Exiled.Events.EventArgs.Interfaces; + + using Interactables.Interobjects.DoorUtils; + using InventorySystem.Items.MicroHID; + + /// + /// Contains all information before the micro opens a doors. + /// + public class MicroHIDOpeningDoorEventArgs : IDeniableEvent, IDoorEvent, IItemEvent + { + /// + /// Initializes a new instance of the class. + /// + /// + /// Whether the Micro HID can open the door or not. + /// + public MicroHIDOpeningDoorEventArgs(MicroHIDItem item, DoorVariant door, bool isAllowed = true) + { + MicroHID = Item.Get(item); + Player = MicroHID.Owner; + IsAllowed = isAllowed; + Door = Door.Get(door); + } + + /// + /// Gets the item. + /// + public Item Item => MicroHID; + + /// + /// Gets the player in owner of the item. + /// + public Exiled.API.Features.Player Player { get; } + + /// + /// Gets MicroHid item. + /// + public MicroHid MicroHID { get; } + + /// + /// Gets the instance. + /// + public Door Door { get; } + + /// + /// Gets or sets a value indicating whether the player can explode the micro HID. + /// + public bool IsAllowed { get; set; } + } +} \ No newline at end of file diff --git a/EXILED/Exiled.Events/Handlers/Player.cs b/EXILED/Exiled.Events/Handlers/Player.cs index ac58bb3085..940778ef29 100644 --- a/EXILED/Exiled.Events/Handlers/Player.cs +++ b/EXILED/Exiled.Events/Handlers/Player.cs @@ -583,6 +583,11 @@ public class Player /// public static Event ChangingDisruptorMode { get; set; } = new(); + /// + /// Invoked before the micro HID opens a door. + /// + public static Event MicroHIDOpeningDoor { get; set; } = new(); + /// /// Invoked before player interacts with coffee cup. /// @@ -1260,6 +1265,12 @@ public static void OnItemRemoved(ReferenceHub referenceHub, InventorySystem.Item /// The instance. public static void OnChangingDisruptorMode(ChangingDisruptorModeEventArgs ev) => ChangingDisruptorMode.InvokeSafely(ev); + /// + /// Called before the micro HID opens a door. + /// + /// The instance. + public static void OnMicroHIDOpeningDoor(MicroHIDOpeningDoorEventArgs ev) => MicroHIDOpeningDoor.InvokeSafely(ev); + /// /// Called before player interacts with coffee cup. /// diff --git a/EXILED/Exiled.Events/Patches/Events/Player/MicroHIDOpeningDoor.cs b/EXILED/Exiled.Events/Patches/Events/Player/MicroHIDOpeningDoor.cs new file mode 100644 index 0000000000..262114b6ad --- /dev/null +++ b/EXILED/Exiled.Events/Patches/Events/Player/MicroHIDOpeningDoor.cs @@ -0,0 +1,73 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) ExMod Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.Events.Patches.Events.Player +{ + using System.Collections.Generic; + using System.Reflection.Emit; + + using Attributes; + using Exiled.API.Features.Pools; + using Exiled.Events.EventArgs.Player; + + using HarmonyLib; + using InventorySystem.Items.MicroHID.Modules; + + using static HarmonyLib.AccessTools; + + /// + /// Patches . + /// Adds the event. + /// + [EventPatch(typeof(Handlers.Player), nameof(Handlers.Player.MicroHIDOpeningDoor))] + [HarmonyPatch(typeof(ChargeFireModeModule), nameof(ChargeFireModeModule.HandlePotentialDoor))] + internal static class MicroHIDOpeningDoor + { + private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator) + { + List newInstructions = ListPool.Pool.Get(instructions); + + int offset = 0; + int index = newInstructions.FindLastIndex(x => x.opcode == OpCodes.Brtrue_S) + offset; + + LocalBuilder result = generator.DeclareLocal(typeof(bool)); + + newInstructions.InsertRange( + index, + new CodeInstruction[] + { + // bool result = onStack + new(OpCodes.Stloc_S, result.LocalIndex), + + // this.MicroHid + new(OpCodes.Ldarg_0), + new(OpCodes.Call, PropertyGetter(typeof(ChargeFireModeModule), nameof(ChargeFireModeModule.MicroHid))), + + // breakableDoor + new(OpCodes.Ldloc_0), + + // result + new(OpCodes.Ldloc_S, result.LocalIndex), + + // MicroHIDOpeningDoorEventArgs ev = new(MicroHIDItem, DoorVariant, ValueOnStack); + new(OpCodes.Newobj, GetDeclaredConstructors(typeof(MicroHIDOpeningDoorEventArgs))[0]), + new(OpCodes.Dup), + + // Handlers.Player.OnMicroHIDOpeningDoor(ev); + new(OpCodes.Call, Method(typeof(Handlers.Player), nameof(Handlers.Player.OnMicroHIDOpeningDoor))), + + // ev.IsAllowed (leave on stack) + new(OpCodes.Callvirt, PropertyGetter(typeof(MicroHIDOpeningDoorEventArgs), nameof(MicroHIDOpeningDoorEventArgs.IsAllowed))), + }); + + for (int z = 0; z < newInstructions.Count; z++) + yield return newInstructions[z]; + + ListPool.Pool.Return(newInstructions); + } + } +}