From b02a1d9a85798cab9cae8533529cbbbc1399d35a Mon Sep 17 00:00:00 2001 From: Avepy <54192195+Avepy@users.noreply.github.com> Date: Mon, 16 Dec 2024 13:52:18 +0100 Subject: [PATCH] refactor(server): OnWeaponDamageEvent and WeaponDamageResponse (#40) * refactor(server): OnWeaponDamageEvent and WeaponDamageResponse * refactor(server): OnWeaponDamageEvent and WeaponDamageResponse * refactor(server): OnWeaponDamageEvent and WeaponDamageResponse --- api/AltV.Net/Core.Events.cs | 82 ++++++++++++++++------- api/AltV.Net/Data/WeaponDamageResponse.cs | 23 +++++-- 2 files changed, 77 insertions(+), 28 deletions(-) diff --git a/api/AltV.Net/Core.Events.cs b/api/AltV.Net/Core.Events.cs index bce46bd84..7aa37724b 100644 --- a/api/AltV.Net/Core.Events.cs +++ b/api/AltV.Net/Core.Events.cs @@ -538,21 +538,69 @@ public void OnWeaponDamage(IntPtr eventPointer, IntPtr playerPointer, IntPtr ent OnWeaponDamageEvent(eventPointer, sourcePlayer, targetEntity, weapon, damage, shotOffset, bodyPart); } + /// + /// Handles the weapon damage event triggered in the game. + /// + /// + /// This method iterates through all registered event handlers for weapon damage events, + /// determines whether the event should be canceled, and updates the damage value if modified + /// by any handler. + /// + /// If any handler indicates cancellation, the event is marked as canceled. + /// If a damage override is provided, it updates the damage value. + /// public virtual void OnWeaponDamageEvent(IntPtr eventPointer, IPlayer sourcePlayer, IEntity targetEntity, - uint weapon, ushort damage, - Position shotOffset, BodyPart bodyPart) + uint weapon, ushort damage, Position shotOffset, BodyPart bodyPart) { + try + { + var (shouldCancel, weaponDamage) = + ProcessWeaponDamageEvents(sourcePlayer, targetEntity, weapon, damage, shotOffset, bodyPart); + + if (weaponDamage.HasValue) + { + unsafe + { + Alt.CoreImpl.Library.Server.Event_WeaponDamageEvent_SetDamageValue(eventPointer, + weaponDamage.Value); + } + } + + if (shouldCancel) + { + unsafe + { + Alt.CoreImpl.Library.Shared.Event_Cancel(eventPointer); + } + } + } + catch (Exception ex) + { + Alt.Log($"Unhandled exception in {nameof(OnWeaponDamageEvent)}: {ex}"); + } + } + + /// + /// Processes weapon damage events by invoking all registered event handlers and aggregating results. + /// + /// + /// A tuple containing a flag indicating if the event should be canceled and the aggregated weapon damage value. + /// + private (bool shouldCancel, uint? weaponDamage) ProcessWeaponDamageEvents(IPlayer sourcePlayer, + IEntity targetEntity, uint weapon, ushort damage, Position shotOffset, BodyPart bodyPart) + { + var shouldCancel = false; uint? weaponDamage = null; - var cancel = false; + foreach (var @delegate in WeaponDamageEventHandler.GetEvents()) { try { var result = @delegate(sourcePlayer, targetEntity, weapon, damage, shotOffset, bodyPart); - if (!result.notCancel) + if (result.Cancel) { - cancel = true; + shouldCancel = true; } if (result.Damage.HasValue) @@ -560,31 +608,17 @@ public virtual void OnWeaponDamageEvent(IntPtr eventPointer, IPlayer sourcePlaye weaponDamage ??= result.Damage.Value; } } - catch (TargetInvocationException exception) + catch (TargetInvocationException tex) { - Alt.Log("exception at event:" + "OnWeaponDamageEvent" + ":" + exception.InnerException); + Alt.Log($"TargetInvocationException in {nameof(ProcessWeaponDamageEvents)} handler: {tex.InnerException}"); } - catch (Exception exception) + catch (Exception ex) { - Alt.Log("exception at event:" + "OnWeaponDamageEvent" + ":" + exception); + Alt.Log($"Exception in {nameof(ProcessWeaponDamageEvents)} handler: {ex}"); } } - if (weaponDamage is not null) - { - unsafe - { - Alt.CoreImpl.Library.Server.Event_WeaponDamageEvent_SetDamageValue(eventPointer, weaponDamage.Value); - } - } - - if (cancel) - { - unsafe - { - Alt.CoreImpl.Library.Shared.Event_Cancel(eventPointer); - } - } + return (shouldCancel, weaponDamage); } public void OnPlayerChangeVehicleSeat(IntPtr vehiclePointer, IntPtr playerPointer, byte oldSeat, diff --git a/api/AltV.Net/Data/WeaponDamageResponse.cs b/api/AltV.Net/Data/WeaponDamageResponse.cs index 43bf4f694..840661a20 100644 --- a/api/AltV.Net/Data/WeaponDamageResponse.cs +++ b/api/AltV.Net/Data/WeaponDamageResponse.cs @@ -1,6 +1,21 @@ namespace AltV.Net.Data; -public record WeaponDamageResponse(bool notCancel, uint? Damage) { - public static implicit operator WeaponDamageResponse(bool val) => new WeaponDamageResponse(val, null); - public static implicit operator WeaponDamageResponse(uint val) => new WeaponDamageResponse(true, val); -}; \ No newline at end of file +/// +/// Represents the response to a weapon damage event, indicating whether the damage is processed and the amount of damage. +/// +public record WeaponDamageResponse(bool Cancel, uint? Damage) +{ + /// + /// Implicit conversion from a boolean value to . + /// Sets to the specified value and to null. + /// + /// Indicates whether the damage is processed. + public static implicit operator WeaponDamageResponse(bool cancel) => new(cancel, null); + + /// + /// Implicit conversion from an uint value to . + /// Sets to true and to the specified value. + /// + /// The amount of damage. + public static implicit operator WeaponDamageResponse(uint damage) => new(false, damage); +}