Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EXILED::Events] BeingObserved event #72

Closed
wants to merge 14 commits into from
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// -----------------------------------------------------------------------
// <copyright file="Scp173BeingObservedEventArgs.cs" company="Exiled Team">
// Copyright (c) Exiled Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------

namespace Exiled.Events.EventArgs.Scp173
{
using Exiled.API.Features.Roles;
using Exiled.Events.EventArgs.Interfaces;

/// <summary>
/// Contains all the information before being observed.
/// </summary>
public class Scp173BeingObservedEventArgs : IScp173Event, IDeniableEvent
{
/// <summary>
/// Initializes a new instance of the <see cref="Scp173BeingObservedEventArgs" /> class.
/// </summary>
/// <param name="target">
/// <inheritdoc cref="Target" />
/// </param>
/// <param name="scp173">
/// <inheritdoc cref="Player"/>
/// </param>
/// <param name="isAllowed">
/// <inheritdoc cref="IsAllowed"/>
/// </param>
public Scp173BeingObservedEventArgs(API.Features.Player target, API.Features.Player scp173, bool isAllowed = true)
{
Target = target;
Player = scp173;
Scp173 = scp173.Role.As<Scp173Role>();
IsAllowed = isAllowed;
}

/// <summary>
/// Gets the player who's observing the Scp 173.
/// </summary>
public API.Features.Player Target { get; }

/// <summary>
/// Gets the player who's being observed.
/// </summary>
public API.Features.Player Player { get; }

/// <inheritdoc/>
public Scp173Role Scp173 { get; }

/// <summary>
/// Gets or sets a value indicating whether or not the player can be counted as observing.
/// </summary>
public bool IsAllowed { get; set; }
}
}
11 changes: 11 additions & 0 deletions EXILED/Exiled.Events/Handlers/Scp173.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ public static class Scp173
/// </summary>
public static Event<UsingBreakneckSpeedsEventArgs> UsingBreakneckSpeeds { get; set; } = new();

/// <summary>
/// Invoked before Scp 173 is observed.
6hundred9 marked this conversation as resolved.
Show resolved Hide resolved
/// </summary>
public static Event<Scp173BeingObservedEventArgs> Scp173BeingObserved { get; set; } = new();

/// <summary>
/// Called before players near SCP-173 blink.
/// </summary>
Expand All @@ -60,5 +65,11 @@ public static class Scp173
/// </summary>
/// <param name="ev">The <see cref="UsingBreakneckSpeedsEventArgs" /> instance.</param>
public static void OnUsingBreakneckSpeeds(UsingBreakneckSpeedsEventArgs ev) => UsingBreakneckSpeeds.InvokeSafely(ev);

/// <summary>
/// Called before Scp 173 is observed.
6hundred9 marked this conversation as resolved.
Show resolved Hide resolved
/// </summary>
/// <param name="ev">The <see cref="Scp173BeingObservedEventArgs" /> instance.</param>
public static void OnScp173BeingObserved(Scp173BeingObservedEventArgs ev) => Scp173BeingObserved.InvokeSafely(ev);
}
}
82 changes: 82 additions & 0 deletions EXILED/Exiled.Events/Patches/Events/Scp173/Scp173BeingObserved.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// -----------------------------------------------------------------------
// <copyright file="Scp173BeingObserved.cs" company="Exiled Team">
// Copyright (c) Exiled Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------

namespace Exiled.Events.Patches.Events.Scp173
{
using System.Collections.Generic;
using System.Reflection.Emit;

using Exiled.API.Features.Pools;
using Exiled.Events.Attributes;
using Exiled.Events.EventArgs.Scp173;
using HarmonyLib;
using PlayerRoles.PlayableScps.Scp173;
using PlayerRoles.Subroutines;
using PluginAPI.Events;

using static HarmonyLib.AccessTools;

/// <summary>
/// Patches <see cref="Scp173ObserversTracker.IsObservedBy" />.
/// Adds the <see cref="Handlers.Scp173.Scp173BeingObserved" /> event.
/// </summary>
[EventPatch(typeof(Handlers.Scp173), nameof(Handlers.Scp173.Scp173BeingObserved))]
[HarmonyPatch(typeof(Scp173ObserversTracker), nameof(Scp173ObserversTracker.IsObservedBy))]
internal static class Scp173BeingObserved
{
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
List<CodeInstruction> newInstructions = ListPool<CodeInstruction>.Pool.Get(instructions);

Label continueLabel = generator.DefineLabel();

const int offset = -4;
int index = newInstructions.FindIndex(i => i.Is(OpCodes.Call, Field(typeof(EventManager), nameof(EventManager.ExecuteEvent)))) + offset;
6hundred9 marked this conversation as resolved.
Show resolved Hide resolved

newInstructions.InsertRange(
index,
new CodeInstruction[]
{
// Player.Get(target)
new(OpCodes.Ldarg_1),
new(OpCodes.Call, Method(typeof(API.Features.Player), nameof(API.Features.Player.Get))),
6hundred9 marked this conversation as resolved.
Show resolved Hide resolved

// Player.Get(base.Owner)
new(OpCodes.Ldarg_0),
new(OpCodes.Call, PropertyGetter(typeof(StandardSubroutine<Scp173Role>), nameof(StandardSubroutine<Scp173Role>.Owner))),
new(OpCodes.Call, Method(typeof(API.Features.Player), nameof(API.Features.Player.Get))),
6hundred9 marked this conversation as resolved.
Show resolved Hide resolved

// true
new(OpCodes.Ldc_I4_1),

// Scp173BeingObservedEventArgs ev = new(Player, Player, bool)
new(OpCodes.Newobj, GetDeclaredConstructors(typeof(Scp173BeingObservedEventArgs))[0]),
new(OpCodes.Dup),

// Handlers.Scp173.OnScp173BeingObserved(ev)
new(OpCodes.Call, Method(typeof(Handlers.Scp173), nameof(Handlers.Scp173.OnScp173BeingObserved))),

// if (ev.IsAllowed)
// goto continueLabel
new(OpCodes.Callvirt, PropertyGetter(typeof(Scp173BeingObservedEventArgs), nameof(Scp173BeingObservedEventArgs.IsAllowed))),
new(OpCodes.Brtrue, continueLabel),

// return false
new(OpCodes.Ldc_I4_0),
new(OpCodes.Ret),

// continueLabel:
new CodeInstruction(OpCodes.Nop).WithLabels(continueLabel),
});

for (int z = 0; z < newInstructions.Count; z++)
yield return newInstructions[z];

ListPool<CodeInstruction>.Pool.Return(newInstructions);
}
}
}
Loading