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

New Hurt Event #2176

Merged
merged 10 commits into from
Nov 12, 2023
16 changes: 4 additions & 12 deletions Exiled.Events/EventArgs/Player/HurtingEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,10 @@ public HurtingEventArgs(Player target, DamageHandlerBase damageHandler)
Player = target;
}

/// <summary>
/// Gets the target player, who is going to be hurt.
/// </summary>
/// <inheritdoc/>
public Player Player { get; }

/// <summary>
/// Gets the attacker player.
/// </summary>
/// <inheritdoc/>
public Player Attacker { get; }

/// <summary>
Expand All @@ -56,14 +52,10 @@ public float Amount
set => DamageHandler.Damage = value;
}

/// <summary>
/// Gets or sets the <see cref="CustomDamageHandler" /> for the event.
/// </summary>
/// <inheritdoc/>
public CustomDamageHandler DamageHandler { get; set; }

/// <summary>
/// Gets or sets a value indicating whether or not the player will be dealt damage.
/// </summary>
/// <inheritdoc/>
public bool IsAllowed { get; set; } = true;
}
}
11 changes: 11 additions & 0 deletions Exiled.Events/Handlers/Player.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,11 @@ public class Player
/// </summary>
public static Event<HurtingEventArgs> Hurting { get; set; } = new();

/// <summary>
/// Invoked after hurting a <see cref="API.Features.Player"/>.
/// </summary>
public static Event<HurtEventArgs> Hurt { get; set; } = new();

/// <summary>
/// Invoked before a <see cref="API.Features.Player"/> dies.
/// </summary>
Expand Down Expand Up @@ -1024,6 +1029,12 @@ public static void OnItemAdded(ReferenceHub referenceHub, InventorySystem.Items.
/// <param name="ev">The <see cref="HurtingEventArgs"/> instance. </param>
public static void OnHurting(HurtingEventArgs ev) => Hurting.InvokeSafely(ev);

/// <summary>
/// Called ater a <see cref="API.Features.Player"/> being hurt.
/// </summary>
/// <param name="ev">The <see cref="HurtingEventArgs"/> instance. </param>
public static void OnHurt(HurtEventArgs ev) => Hurt.InvokeSafely(ev);

/// <summary>
/// Called before a <see cref="API.Features.Player"/> dies.
/// </summary>
Expand Down
62 changes: 62 additions & 0 deletions Exiled.Events/Patches/Events/Player/HurtEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// -----------------------------------------------------------------------
// <copyright file="HurtEventArgs.cs" company="Exiled Team">
louis1706 marked this conversation as resolved.
Show resolved Hide resolved
// Copyright (c) Exiled Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------

namespace Exiled.Events.EventArgs.Player
{
using API.Features;
using API.Features.DamageHandlers;

using Interfaces;

using CustomAttackerHandler = API.Features.DamageHandlers.AttackerDamageHandler;
using DamageHandlerBase = PlayerStatsSystem.DamageHandlerBase;

/// <summary>
/// Contains all information before a player gets damaged.
/// </summary>
public class HurtEventArgs : IAttackerEvent
{
/// <summary>
/// Initializes a new instance of the <see cref="HurtEventArgs" /> class.
/// </summary>
/// <param name="target">
/// <inheritdoc cref="Player" />
/// </param>
/// <param name="damageHandler">
/// <inheritdoc cref="DamageHandler" />
/// </param>
/// <param name="handlerOutput">
/// <inheritdoc cref="HandlerOutput" />
/// </param>
public HurtEventArgs(Player target, DamageHandlerBase damageHandler, DamageHandlerBase.HandlerOutput handlerOutput)
{
DamageHandler = new CustomDamageHandler(target, damageHandler);
Attacker = DamageHandler.BaseIs(out CustomAttackerHandler attackerDamageHandler) ? attackerDamageHandler.Attacker : null;
Player = target;
HandlerOutput = handlerOutput;
}

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

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

/// <summary>
/// Gets the amount of inflicted damage.
/// </summary>
public float Amount { get; }

/// <summary>
/// Gets or sets the action than will be made on the player.
/// </summary>
public DamageHandlerBase.HandlerOutput HandlerOutput { get; set; }

/// <inheritdoc/>
public CustomDamageHandler DamageHandler { get; set; }
}
}
26 changes: 24 additions & 2 deletions Exiled.Events/Patches/Events/Player/Hurting.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ namespace Exiled.Events.Patches.Events.Player

/// <summary>
/// Patches <see cref="PlayerStats.DealDamage(DamageHandlerBase)" />.
/// Adds the <see cref="Handlers.Player.Hurting" /> event.
/// Adds the <see cref="Handlers.Player.Hurting" /> event and <see cref="Handlers.Player.Hurt" /> event.
/// </summary>
[EventPatch(typeof(Handlers.Player), nameof(Handlers.Player.Hurting))]
[EventPatch(typeof(Handlers.Player), nameof(Handlers.Player.Hurt))]
[HarmonyPatch(typeof(PlayerStats), nameof(PlayerStats.DealDamage))]
internal static class Hurting
{
Expand All @@ -43,7 +44,7 @@ private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstructi
Label notRecontainment = generator.DefineLabel();
Label ret = generator.DefineLabel();

const int offset = 1;
int offset = 1;
int index = newInstructions.FindIndex(instruction => instruction.opcode == OpCodes.Ret) + offset;

newInstructions.InsertRange(
Expand Down Expand Up @@ -96,6 +97,27 @@ private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstructi
new(OpCodes.Brfalse, ret),
});

offset = 2;
index = newInstructions.FindIndex(instruction => instruction.operand == (object)Method(typeof(DamageHandlerBase), nameof(DamageHandlerBase.ApplyDamage))) + offset;

newInstructions.InsertRange(
index,
new[]
{
// HurtingEventArgs ev = new(player, handler, handleroutput)
louis1706 marked this conversation as resolved.
Show resolved Hide resolved
new CodeInstruction(OpCodes.Ldloc, player.LocalIndex),
new(OpCodes.Ldarg_1),
new(OpCodes.Ldloc_1),
new(OpCodes.Newobj, GetDeclaredConstructors(typeof(HurtEventArgs))[0]),
new(OpCodes.Dup),

// Handlers.Player.OnHurting(ev);
louis1706 marked this conversation as resolved.
Show resolved Hide resolved
new(OpCodes.Call, Method(typeof(Handlers.Player), nameof(Handlers.Player.OnHurt))),

// handlerOutput = ev.HandlerOutput;
new(OpCodes.Callvirt, PropertyGetter(typeof(HurtEventArgs), nameof(HurtEventArgs.HandlerOutput))),
new(OpCodes.Stloc_1),
});
newInstructions[newInstructions.Count - 1].WithLabels(ret);

for (int z = 0; z < newInstructions.Count; z++)
Expand Down
Loading