Skip to content

Commit

Permalink
[Resonance] Alpha 18 Fixes (#2747)
Browse files Browse the repository at this point in the history
* alpha 18 fixes

* change summaries to match with other ones

* see cref

* healing fix & change this
  • Loading branch information
xNexusACS authored Jul 21, 2024
1 parent 77ab331 commit c4e6422
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 162 deletions.
2 changes: 1 addition & 1 deletion Exiled.Events/EventArgs/Player/SpawningRagdollEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public string Nickname
/// </summary>
public DamageHandler DamageHandlerBase
{
get => damageHandler ??= new(Player, Info.Handler);
get => damageHandler ??= new DamageHandler(Player, Info.Handler);
set
{
Info = new RagdollData(Player.ReferenceHub, value, Role, Position, Rotation, Nickname, CreationTime);
Expand Down
60 changes: 16 additions & 44 deletions Exiled.Events/EventArgs/Scp3114/StranglingEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,68 +8,40 @@
namespace Exiled.Events.EventArgs.Scp3114
{
using Exiled.API.Features;
using Exiled.API.Features.Roles;
using Exiled.Events.EventArgs.Interfaces;

using PlayerRoles.PlayableScps.Scp3114;

using HumanRole = PlayerRoles.HumanRole;
using Scp3114Role = API.Features.Roles.Scp3114Role;

/// <summary>
/// Contains all information before strangling a player.
/// </summary>
public class StranglingEventArgs : IScp3114Event, IDeniableEvent
{
private readonly Scp3114Strangle strangle;
private Player target = null;

/// <summary>
/// Initializes a new instance of the <see cref="StranglingEventArgs"/> class.
/// Initializes a new instance of the <see cref="StranglingEventArgs" /> class.
/// </summary>
/// <param name="strangle">The <see cref="Scp3114Strangle"/> instance.</param>
/// <param name="player">The <see cref="API.Features.Player"/> triggering the event.</param>
/// <param name="target">The <see cref="API.Features.Player"/> being targeted.</param>
public StranglingEventArgs(Scp3114Strangle strangle, Player player, Scp3114Strangle.StrangleTarget target)
/// <param name="player"><see cref="Player"/>.</param>
/// <param name="target"><see cref="Target"/>.</param>
/// <param name="isAllowed"><see cref="IsAllowed"/>.</param>
public StranglingEventArgs(Player player, Player target, bool isAllowed = true)
{
this.strangle = strangle;
Scp3114 = player.Role.As<Scp3114Role>();
Player = player;
Target = Player.Get(target.Target);
StrangleTarget = target;
Scp3114 = Player.Role.As<Scp3114Role>();
Target = target;
IsAllowed = isAllowed;
}

/// <inheritdoc />
public Scp3114Role Scp3114 { get; }

/// <inheritdoc />
public Player Player
{
get => target;
set
{
target = value;

if (!target)
{
StrangleTarget = default(Scp3114Strangle.StrangleTarget);
return;
}
/// <inheritdoc/>
public Player Player { get; }

StrangleTarget = new(target.ReferenceHub, strangle.GetStranglePosition(target.ReferenceHub.roleManager.CurrentRole as HumanRole), Player.Position);
}
}
/// <inheritdoc/>
public Scp3114Role Scp3114 { get; }

/// <summary>
/// Gets the target player.
/// Gets the <see cref="Player"/> being strangled.
/// </summary>
public Player Target { get; }

/// <summary>
/// Gets the <see cref="Scp3114Strangle.StrangleTarget"/>. This value is updated when <see cref="Target"/> is changed.
/// </summary>
public Scp3114Strangle.StrangleTarget? StrangleTarget { get; private set; }

/// <inheritdoc />
public bool IsAllowed { get; set; } = true;
/// <inheritdoc/>
public bool IsAllowed { get; set; }
}
}
32 changes: 22 additions & 10 deletions Exiled.Events/Patches/Events/Player/Healing.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstructi
List<CodeInstruction> newInstructions = ListPool<CodeInstruction>.Pool.Get(instructions);

Label continueLabel = generator.DefineLabel();
Label skip1 = generator.DefineLabel();
Label skip2 = generator.DefineLabel();

LocalBuilder ev = generator.DeclareLocal(typeof(HealingEventArgs));
LocalBuilder player = generator.DeclareLocal(typeof(Player));
Expand All @@ -48,49 +50,59 @@ private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstructi
new(OpCodes.Stloc_S, lastHealth.LocalIndex),

// player = Player.Get(this.Hub);
// if (player is null) skip
new(OpCodes.Ldarg_0),
new(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(HealthStat), nameof(HealthStat.Hub))),
new(OpCodes.Call, AccessTools.Method(typeof(Player), nameof(Player.Get), new Type[] { typeof(ReferenceHub) })),
new(OpCodes.Call, AccessTools.Method(typeof(Player), nameof(Player.Get), new[] { typeof(ReferenceHub) })),
new(OpCodes.Dup),
new(OpCodes.Stloc_S, player.LocalIndex),
new(OpCodes.Brfalse_S, skip1),

// HealingEventArgs ev = new(Player, amount)
// HealingEventArgs args = new(player, amount)
new(OpCodes.Ldloc_S, player.LocalIndex),
new(OpCodes.Ldarg_1),
new(OpCodes.Newobj, AccessTools.GetDeclaredConstructors(typeof(HealingEventArgs))[0]),
new(OpCodes.Dup),
new(OpCodes.Dup),
new(OpCodes.Stloc_S, ev.LocalIndex),

// OnHealing(ev)
// Player::OnHealing(args)
new(OpCodes.Call, AccessTools.Method(typeof(Handlers.Player), nameof(Handlers.Player.OnHealing))),

// if (!ev.IsAllowed)
// return
// if (!args.IsAllowed) return
new(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(HealingEventArgs), nameof(HealingEventArgs.IsAllowed))),
new(OpCodes.Brtrue_S, continueLabel),
new(OpCodes.Pop),
new(OpCodes.Pop),
new(OpCodes.Ret),

// healAmount = ev.Amount
// healAmount = args.Amount
new CodeInstruction(OpCodes.Ldloc_S, ev.LocalIndex).WithLabels(continueLabel),
new(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(HealingEventArgs), nameof(HealingEventArgs.Amount))),
new(OpCodes.Starg_S, 1),

new CodeInstruction(OpCodes.Nop).WithLabels(skip1),
});

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

newInstructions.InsertRange(newInstructions.Count - 1, new[]
{
// HealedEventArgs ev = new(Player, lastAmount)
// if (player is null) skip
new(OpCodes.Ldloc_S, player.LocalIndex),
new(OpCodes.Brfalse_S, skip2),

// HealedEventArgs args = new(player, lastAmount)
new(OpCodes.Ldloc_S, player.LocalIndex),
new(OpCodes.Ldloc_S, lastHealth.LocalIndex),
new(OpCodes.Newobj, AccessTools.GetDeclaredConstructors(typeof(HealedEventArgs))[0]),

// OnHealed(ev)
// Player::OnHealed(args)
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Handlers.Player), nameof(Handlers.Player.OnHealed))),
});

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

ListPool<CodeInstruction>.Pool.Return(newInstructions);
}
Expand Down
121 changes: 32 additions & 89 deletions Exiled.Events/Patches/Events/Player/SpawningRagdoll.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,9 @@ namespace Exiled.Events.Patches.Events.Player
using Exiled.API.Features;
using Exiled.Events.Attributes;
using Exiled.Events.EventArgs.Player;

using HarmonyLib;
using PlayerRoles.Ragdolls;

using PlayerStatsSystem;

using UnityEngine;

using static HarmonyLib.AccessTools;
Expand All @@ -39,118 +36,66 @@ private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstructi
{
List<CodeInstruction> newInstructions = ListPool<CodeInstruction>.Pool.Get(instructions);

Label ret = generator.DefineLabel();
Label continueLabel = generator.DefineLabel();

LocalBuilder ev = generator.DeclareLocal(typeof(SpawningRagdollEventArgs));
LocalBuilder newRagdoll = generator.DeclareLocal(typeof(Ragdoll));
LocalBuilder localScale = generator.DeclareLocal(typeof(Vector3));
LocalBuilder evScale = generator.DeclareLocal(typeof(Vector3));
LocalBuilder targetScale = generator.DeclareLocal(typeof(Vector3));

int offset = 0;
int index = newInstructions.FindIndex(instruction => instruction.opcode == OpCodes.Ldloc_1) + offset;

// remove
// "basicRagdoll.NetworkInfo = new RagdollData(owner, handler, transform.localPosition, transform.localRotation);"
newInstructions.RemoveRange(index, 9);
int index = newInstructions.FindIndex(instruction => instruction.Calls(PropertySetter(typeof(BasicRagdoll), nameof(BasicRagdoll.NetworkInfo))));

// replace with
newInstructions.InsertRange(index, new[]
{
// hub
new CodeInstruction(OpCodes.Ldarg_0),

// handler
new(OpCodes.Ldarg_1),

// ragdollRole.transform.localPosition
new(OpCodes.Ldloc_2),
new(OpCodes.Callvirt, PropertyGetter(typeof(Transform), nameof(Transform.localPosition))),

// ragdollRole.transform.localRotation
new(OpCodes.Ldloc_2),
new(OpCodes.Callvirt, PropertyGetter(typeof(Transform), nameof(Transform.localRotation))),

// new RagdollInfo(ReferenceHub, DamageHandlerBase, Vector3, Quaternion)
new(OpCodes.Newobj, GetDeclaredConstructors(typeof(RagdollData))[0]),

// true
new(OpCodes.Ldc_I4_1),

// SpawningRagdollEventArgs ev = new(RagdollInfo, DamageHandlerBase, bool)
// SpawningRagdollEventArgs args = new(RagdollInfo, bool)
new(OpCodes.Newobj, GetDeclaredConstructors(typeof(SpawningRagdollEventArgs))[0]),
new(OpCodes.Dup),
new(OpCodes.Dup),
new(OpCodes.Stloc_S, ev.LocalIndex),

// Player.OnSpawningRagdoll(ev)
// Player::OnSpawningRagdoll(args)
new(OpCodes.Call, Method(typeof(Player), nameof(Player.OnSpawningRagdoll))),

// if (!ev.IsAllowed)
// return;
// if (!args.IsAllowed)
// {
// Object.Destroy(gameObject);
// return null;
// }
new(OpCodes.Callvirt, PropertyGetter(typeof(SpawningRagdollEventArgs), nameof(SpawningRagdollEventArgs.IsAllowed))),
new(OpCodes.Brfalse_S, ret),

// basicRagdoll.NetworkInfo = ev.Info
new(OpCodes.Ldloc_1),
new(OpCodes.Ldloc_S, ev.LocalIndex),
new(OpCodes.Callvirt, PropertyGetter(typeof(SpawningRagdollEventArgs), nameof(SpawningRagdollEventArgs.Info))),
new(OpCodes.Call, PropertySetter(typeof(BasicRagdoll), nameof(BasicRagdoll.NetworkInfo))),
new(OpCodes.Brtrue_S, continueLabel),

// new Vector3()
new(OpCodes.Ldloca_S, targetScale.LocalIndex),
new(OpCodes.Initobj, typeof(Vector3)),
new(OpCodes.Pop),
new(OpCodes.Call, Method(typeof(Object), nameof(Object.Destroy), new[] { typeof(Object) })),
new(OpCodes.Ldnull),
new(OpCodes.Ret),

// localScale = ragdoll.gameObject.transform.localScale
new(OpCodes.Ldloc_1),
// ragdoll transform
new CodeInstruction(OpCodes.Ldloc_1).WithLabels(continueLabel),
new(OpCodes.Callvirt, PropertyGetter(typeof(BasicRagdoll), nameof(BasicRagdoll.gameObject))),
new(OpCodes.Callvirt, PropertyGetter(typeof(GameObject), nameof(GameObject.transform))),

// ragdoll localScale
new(OpCodes.Dup),
new(OpCodes.Callvirt, PropertyGetter(typeof(Transform), nameof(Transform.localScale))),
new(OpCodes.Stloc_S, localScale.LocalIndex),

// evScale = ev.Scale
// SpawningRagdollEventArgs::Scale
new(OpCodes.Ldloc_S, ev.LocalIndex),
new(OpCodes.Callvirt, PropertyGetter(typeof(SpawningRagdollEventArgs), nameof(SpawningRagdollEventArgs.Scale))),
new(OpCodes.Stloc_S, evScale.LocalIndex),

// targetScale.x = evScale.x * localScale.x
new(OpCodes.Ldloca_S, targetScale.LocalIndex),
new(OpCodes.Ldloc_S, evScale.LocalIndex),
new(OpCodes.Ldfld, Field(typeof(Vector3), nameof(Vector3.x))),
new(OpCodes.Ldloc_S, localScale.LocalIndex),
new(OpCodes.Ldfld, Field(typeof(Vector3), nameof(Vector3.x))),
new(OpCodes.Mul),
new(OpCodes.Stfld, Field(typeof(Vector3), nameof(Vector3.x))),

// targetScale.y = evScale.y * localScale.y
new(OpCodes.Ldloca_S, targetScale.LocalIndex),
new(OpCodes.Ldloc_S, evScale.LocalIndex),
new(OpCodes.Ldfld, Field(typeof(Vector3), nameof(Vector3.y))),
new(OpCodes.Ldloc_S, localScale.LocalIndex),
new(OpCodes.Ldfld, Field(typeof(Vector3), nameof(Vector3.y))),
new(OpCodes.Mul),
new(OpCodes.Stfld, Field(typeof(Vector3), nameof(Vector3.y))),

// targetScale.z = evScale.z * localScale.z
new(OpCodes.Ldloca_S, targetScale.LocalIndex),
new(OpCodes.Ldloc_S, evScale.LocalIndex),
new(OpCodes.Ldfld, Field(typeof(Vector3), nameof(Vector3.z))),
new(OpCodes.Ldloc_S, localScale.LocalIndex),
new(OpCodes.Ldfld, Field(typeof(Vector3), nameof(Vector3.z))),
new(OpCodes.Mul),
new(OpCodes.Stfld, Field(typeof(Vector3), nameof(Vector3.z))),

// ragdoll.gameObject.transform.localScale = targetScale
new(OpCodes.Ldloc_1),
new(OpCodes.Callvirt, PropertyGetter(typeof(BasicRagdoll), nameof(BasicRagdoll.gameObject))),
new(OpCodes.Callvirt, PropertyGetter(typeof(GameObject), nameof(GameObject.transform))),
new(OpCodes.Ldloc_S, targetScale.LocalIndex),

// newScale = Vector3::Scale(ragdollScale, SpawningRagdollEventArgs::Scale);
new(OpCodes.Call, Method(typeof(Vector3), nameof(Vector3.Scale), new[] { typeof(Vector3), typeof(Vector3) })),

// BasicRagdoll::gameObject::transform::localScale = targetScale
new(OpCodes.Callvirt, PropertySetter(typeof(Transform), nameof(Transform.localScale))),

// load ragdollInfo
new(OpCodes.Ldloc_S, ev.LocalIndex),
new(OpCodes.Callvirt, PropertyGetter(typeof(SpawningRagdollEventArgs), nameof(SpawningRagdollEventArgs.Info))),
});

newInstructions.InsertRange(newInstructions.Count - 2, new CodeInstruction[]
{
// ev.Player
// SpawningRagdollEventArgs::Player
new(OpCodes.Ldloc_S, ev.LocalIndex),
new(OpCodes.Callvirt, PropertyGetter(typeof(SpawningRagdollEventArgs), nameof(SpawningRagdollEventArgs.Player))),

Expand All @@ -171,10 +116,8 @@ private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstructi
new(OpCodes.Call, Method(typeof(Player), nameof(Player.OnSpawnedRagdoll))),
});

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

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

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

0 comments on commit c4e6422

Please sign in to comment.