Skip to content

Commit

Permalink
feat: PR133 Squashed Scp939EventChange (ExMod-Team#401)
Browse files Browse the repository at this point in the history
PR133 Squashed Scp939EventChange
  • Loading branch information
louis1706 authored Jan 20, 2025
1 parent 3333a5e commit 806bab5
Show file tree
Hide file tree
Showing 7 changed files with 350 additions and 26 deletions.
47 changes: 47 additions & 0 deletions EXILED/Exiled.API/Enums/Scp939VisibilityStates.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// -----------------------------------------------------------------------
// <copyright file="Scp939VisibilityStates.cs" company="ExMod Team">
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------

namespace Exiled.API.Enums
{
using Features.Roles;

/// <summary>
/// Unique identifier for a <see cref="Scp939Role"/>.
/// </summary>
public enum Scp939VisibilityState
{
/// <summary>
/// SCP-939 doesnt see an other player, by default FPC role logic.
/// </summary>
None,

/// <summary>
/// SCP-939 doesnt see an player, by basic SCP-939 logic.
/// </summary>
NotSeen,

/// <summary>
/// SCP-939 sees an other player, who is teammate SCP.
/// </summary>
SeenAsScp,

/// <summary>
/// SCP-939 sees an other player due the Alpha Warhead detonation.
/// </summary>
SeenByDetonation,

/// <summary>
/// SCP-939 sees an other player, due the base-game vision range logic.
/// </summary>
SeenByRange,

/// <summary>
/// SCP-939 sees an other player for a while, after it's out of range.
/// </summary>
SeenByLastTime,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// -----------------------------------------------------------------------
// <copyright file="CreatedAmnesticCloudEventArgs.cs" company="ExMod Team">
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------

namespace Exiled.Events.EventArgs.Scp939
{
using API.Features;

using Exiled.API.Features.Hazards;
using Exiled.API.Features.Roles;
using Interfaces;

using PlayerRoles.PlayableScps.Scp939;

using Scp939Role = API.Features.Roles.Scp939Role;

/// <summary>
/// Contains all information after SCP-939 fully created target <see cref="PlacedAmnesticCloudEventArgs"/>.
/// </summary>
public class CreatedAmnesticCloudEventArgs : IScp939Event, IHazardEvent
{
/// <summary>
/// Initializes a new instance of the <see cref="CreatedAmnesticCloudEventArgs" /> class.
/// </summary>
/// <param name="hub">
/// <inheritdoc cref="ReferenceHub" />
/// </param>
/// <param name="cloud">
/// <inheritdoc cref="PlayerRoles.PlayableScps.Scp939.Scp939AmnesticCloudInstance" />
/// </param>
public CreatedAmnesticCloudEventArgs(ReferenceHub hub, Scp939AmnesticCloudInstance cloud)
{
Player = Player.Get(hub);
AmnesticCloud = Hazard.Get<AmnesticCloudHazard>(cloud);
Scp939 = Player.Role.As<Scp939Role>();
}

/// <inheritdoc/>
public Player Player { get; }

/// <summary>
/// Gets the <see cref="AmnesticCloudHazard"/> instance.
/// </summary>
public AmnesticCloudHazard AmnesticCloud { get; }

/// <inheritdoc/>
public Scp939Role Scp939 { get; }

/// <inheritdoc/>
public Hazard Hazard => AmnesticCloud;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace Exiled.Events.EventArgs.Scp939
/// <summary>
/// Contains all information after SCP-939 used its amnestic cloud ability.
/// </summary>
public class PlacedAmnesticCloudEventArgs : IScp939Event
public class PlacedAmnesticCloudEventArgs : IScp939Event, IHazardEvent
{
/// <summary>
/// Initializes a new instance of the <see cref="PlacedAmnesticCloudEventArgs" /> class.
Expand All @@ -26,12 +26,12 @@ public class PlacedAmnesticCloudEventArgs : IScp939Event
/// <inheritdoc cref="ReferenceHub" />
/// </param>
/// <param name="cloud">
/// <inheritdoc cref="PlayerRoles.PlayableScps.Scp939.Scp939AmnesticCloudInstance" />
/// <inheritdoc cref="Scp939AmnesticCloudInstance" />
/// </param>
public PlacedAmnesticCloudEventArgs(ReferenceHub hub, Scp939AmnesticCloudInstance cloud)
{
Player = Player.Get(hub);
AmnesticCloud = new AmnesticCloudHazard(cloud);
AmnesticCloud = Hazard.Get<AmnesticCloudHazard>(cloud);
Scp939 = Player.Role.As<Scp939Role>();
}

Expand All @@ -47,5 +47,8 @@ public PlacedAmnesticCloudEventArgs(ReferenceHub hub, Scp939AmnesticCloudInstanc

/// <inheritdoc/>
public Scp939Role Scp939 { get; }

/// <inheritdoc/>
public Hazard Hazard => AmnesticCloud;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
// <copyright file="ValidatingVisibilityEventArgs.cs" company="ExMod Team">
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
Expand All @@ -8,50 +8,65 @@
namespace Exiled.Events.EventArgs.Scp939
{
using API.Features;

using Exiled.API.Enums;
using Exiled.API.Features.Roles;
using Interfaces;

/// <summary>
/// Contains all information before SCP-939 sees the player.
/// Contains all information before SCP-939 sees the player.
/// </summary>
public class ValidatingVisibilityEventArgs : IScp939Event, IDeniableEvent
{
/// <summary>
/// Initializes a new instance of the <see cref="ValidatingVisibilityEventArgs" /> class.
/// Initializes a new instance of the <see cref="ValidatingVisibilityEventArgs" /> class.
/// </summary>
/// <param name="state">
/// <inheritdoc cref="TargetVisibilityState"/>
/// </param>
/// <param name="player">
/// <inheritdoc cref="Player" />
/// <inheritdoc cref="Player" />
/// </param>
/// <param name="target">
/// The target being shown to SCP-939.
/// The target being shown to SCP-939.
/// </param>
/// <param name="isAllowed">
/// Whether SCP-939 is allowed to view the player.
/// </param>
public ValidatingVisibilityEventArgs(ReferenceHub player, ReferenceHub target, bool isAllowed)
public ValidatingVisibilityEventArgs(Scp939VisibilityState state, ReferenceHub player, ReferenceHub target)
{
Player = Player.Get(player);
Scp939 = Player.Role.As<Scp939Role>();
Target = Player.Get(target);
IsAllowed = isAllowed;
TargetVisibilityState = state;
IsAllowed = TargetVisibilityState is not(Scp939VisibilityState.NotSeen or Scp939VisibilityState.None);
IsLateSeen = TargetVisibilityState is Scp939VisibilityState.SeenByRange;
}

/// <summary>
/// Gets the player who's being shown to SCP-939.
/// Gets the player who's being shown to SCP-939.
/// </summary>
public Player Target { get; }

/// <summary>
/// Gets the player who's controlling SCP-939.
/// Gets the player who's controlling SCP-939.
/// </summary>
public Player Player { get; }

/// <inheritdoc/>
public Scp939Role Scp939 { get; }

/// <summary>
/// Gets or sets a value indicating whether visibility can be validated.
/// Gets the info about base-game vision information.
/// </summary>
public bool IsAllowed { get; set; }
public Scp939VisibilityState TargetVisibilityState { get; }

/// <summary>
/// Gets or sets a value indicating whether or not the SCP-939 will detect that vision as <see cref="Scp939VisibilityState.SeenByRange"/>.
/// </summary>
/// <remarks>
/// Works only when <see cref="IsAllowed"/> = <see langword="true"/>, and makes player visible to SCP-939 for a while, after it's out of range.
/// </remarks>
public bool IsLateSeen { get; set; }

/// <inheritdoc/>
public bool IsAllowed { get; set; }
}
}
}
12 changes: 12 additions & 0 deletions EXILED/Exiled.Events/Handlers/Scp939.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
namespace Exiled.Events.Handlers
{
#pragma warning disable SA1623 // Property summary documentation should match accessors
using Exiled.API.Features.Hazards;

using Exiled.Events.EventArgs.Scp939;
using Exiled.Events.Features;
Expand Down Expand Up @@ -37,6 +38,11 @@ public static class Scp939
/// </summary>
public static Event<PlacedAmnesticCloudEventArgs> PlacedAmnesticCloud { get; set; } = new();

/// <summary>
/// Invoked after SCP-939 fully spawned <see cref="AmnesticCloudHazard"/>.
/// </summary>
public static Event<CreatedAmnesticCloudEventArgs> CreatedAmnesticCloud { get; set; } = new();

/// <summary>
/// Invoked before SCP-939 plays a stolen voice.
/// </summary>
Expand Down Expand Up @@ -92,6 +98,12 @@ public static class Scp939
/// <param name="ev">The <see cref="PlacedAmnesticCloudEventArgs" /> instance.</param>
public static void OnPlacedAmnesticCloud(PlacedAmnesticCloudEventArgs ev) => PlacedAmnesticCloud.InvokeSafely(ev);

/// <summary>
/// Called after SCP-939 fully spawned <see cref="AmnesticCloudHazard"/>.
/// </summary>
/// <param name="ev">The <see cref="CreatedAmnesticCloudEventArgs" /> instance.</param>
public static void OnCreatedAmnesticCloud(CreatedAmnesticCloudEventArgs ev) => CreatedAmnesticCloud.InvokeSafely(ev);

/// <summary>
/// Called before SCP-939 plays a stolen voice.
/// </summary>
Expand Down
71 changes: 71 additions & 0 deletions EXILED/Exiled.Events/Patches/Events/Scp939/CreatedAmnesticCloud.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// -----------------------------------------------------------------------
// <copyright file="CreatedAmnesticCloud.cs" company="ExMod Team">
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------

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

using Exiled.API.Features.Pools;
using Exiled.Events.Attributes;
using Exiled.Events.EventArgs.Scp939;
using Exiled.Events.Handlers;

using HarmonyLib;

using PlayerRoles.PlayableScps.Scp939;

using static HarmonyLib.AccessTools;

/// <summary>
/// Patches <see cref="Scp939AmnesticCloudInstance.State" /> setter.
/// to add the <see cref="Scp939.CreatedAmnesticCloud" /> event.
/// </summary>
[EventPatch(typeof(Scp939), nameof(Scp939.CreatedAmnesticCloud))]
[HarmonyPatch(typeof(Scp939AmnesticCloudInstance), nameof(Scp939AmnesticCloudInstance.State), MethodType.Setter)]
internal static class CreatedAmnesticCloud
{
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
List<CodeInstruction> newInstructions = ListPool<CodeInstruction>.Pool.Get(instructions);

LocalBuilder hub = generator.DeclareLocal(typeof(ReferenceHub));

Label ret = generator.DefineLabel();

newInstructions.InsertRange(
newInstructions.Count - 1,
new[]
{
// if (!ReferenceHub.TryGetHubNetID(_syncOwner, out ReferenceHub owner))
// return;
new CodeInstruction(OpCodes.Ldarg_0),
new(OpCodes.Ldfld, Field(typeof(Scp939AmnesticCloudInstance), nameof(Scp939AmnesticCloudInstance._syncOwner))),
new(OpCodes.Ldloca_S, hub.LocalIndex),
new(OpCodes.Call, Method(typeof(ReferenceHub), nameof(ReferenceHub.TryGetHubNetID))),
new(OpCodes.Brfalse_S, ret),

// owner
new(OpCodes.Ldloc_S, hub.LocalIndex),

// this
new(OpCodes.Ldarg_0),

// Scp939.OnCreatedAmnesticCloud(new CreatedAmnesticCloudEventArgs(owner, this));
new(OpCodes.Newobj, GetDeclaredConstructors(typeof(CreatedAmnesticCloudEventArgs))[0]),
new(OpCodes.Call, Method(typeof(Scp939), nameof(Scp939.OnCreatedAmnesticCloud))),
});

newInstructions[newInstructions.Count - 1].labels.Add(ret);

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

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

0 comments on commit 806bab5

Please sign in to comment.