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

feat: Fix Reload & Unload & ClipSize & Added Reloaded & UnLoaded #398

Merged
61 changes: 61 additions & 0 deletions EXILED/Exiled.API/Features/Items/Firearm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ public Firearm(BaseFirearm itemBase)
{
BarrelMagazine ??= (BarrelMagazine)Magazine.Get(ammoModule);
}

if (module is HitscanHitregModuleBase hitregModule)
{
HitscanHitregModule = hitregModule;
}
}
}

Expand Down Expand Up @@ -136,6 +141,11 @@ public static IReadOnlyDictionary<Player, Dictionary<FirearmType, AttachmentIden
/// </remarks>
public BarrelMagazine BarrelMagazine { get; }

/// <summary>
/// Gets a primaty magazine for current firearm.
/// </summary>
public HitscanHitregModuleBase HitscanHitregModule { get; }

/// <summary>
/// Gets or sets the amount of ammo in the firearm magazine.
/// </summary>
Expand Down Expand Up @@ -176,6 +186,57 @@ public int MaxMagazineAmmo
set => PrimaryMagazine.MaxAmmo = value;
}

/// <summary>
/// Gets or sets the damage for this firearm.
/// </summary>
public float Damage
{
get => HitscanHitregModule.BaseDamage;
set => HitscanHitregModule.BaseDamage = value;
}

/// <summary>
/// Gets or sets the inaccuracy for this firearm.
/// </summary>
public float Inaccuracy
{
get => HitscanHitregModule.BaseBulletInaccuracy;
set => HitscanHitregModule.BaseBulletInaccuracy = value;
}

/// <summary>
/// Gets or sets the penetration for this firearm.
/// </summary>
public float Penetration
{
get => HitscanHitregModule.BasePenetration;
set => HitscanHitregModule.BasePenetration = value;
}

/// <summary>
/// Gets or sets how much fast the value drop over the distance.
/// </summary>
public float DamageFalloffDistance
{
get => HitscanHitregModule.DamageFalloffDistance;
set => HitscanHitregModule.DamageFalloffDistance = value;
}

/// <summary>
/// Gets the damage for this firearm with attachement modifier.
/// </summary>
public float EffectiveDamage => HitscanHitregModule.EffectiveDamage;

/// <summary>
/// Gets the inaccuracy for this firearm with attachement modifier.
/// </summary>
public float EffectiveInaccuracy => HitscanHitregModule.CurrentInaccuracy;

/// <summary>
/// Gets the penetration for this firearm with attachement modifier.
/// </summary>
public float EffectivePenetration => HitscanHitregModule.DisplayPenetration;

/// <summary>
/// Gets or sets the amount of max ammo in the firearm barrel.
/// </summary>
Expand Down
76 changes: 34 additions & 42 deletions EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
namespace Exiled.CustomItems.API.Features
{
using System;
using System.Linq;

using Exiled.API.Enums;
using Exiled.API.Extensions;
using Exiled.API.Features;
using Exiled.API.Features.DamageHandlers;
Expand All @@ -19,8 +19,7 @@ namespace Exiled.CustomItems.API.Features

using InventorySystem.Items.Firearms.Attachments;
using InventorySystem.Items.Firearms.Attachments.Components;
using InventorySystem.Items.Firearms.BasicMessages;

using InventorySystem.Items.Firearms.Modules;
using UnityEngine;

using Firearm = Exiled.API.Features.Items.Firearm;
Expand Down Expand Up @@ -57,6 +56,8 @@ public override ItemType Type
/// <summary>
/// Gets or sets a value indicating how big of a clip the weapon will have.
/// </summary>
/// <remarks>Warning for <see cref="ItemType.GunShotgun"/> and <see cref="ItemType.GunRevolver"/>.
/// They are not fully compatible with this features.</remarks>
public virtual byte ClipSize { get; set; }

/// <summary>
Expand All @@ -76,9 +77,6 @@ public override ItemType Type
if (!Attachments.IsEmpty())
firearm.AddAttachment(Attachments);

firearm.MagazineAmmo = ClipSize;
firearm.MaxMagazineAmmo = ClipSize;

Pickup? pickup = firearm.CreatePickup(position);

if (pickup is null)
Expand All @@ -87,6 +85,9 @@ public override ItemType Type
return null;
}

if (ClipSize > 0)
firearm.MagazineAmmo = ClipSize;

pickup.Weight = Weight;
pickup.Scale = Scale;
if (previousOwner is not null)
Expand All @@ -104,8 +105,9 @@ public override ItemType Type
if (!Attachments.IsEmpty())
firearm.AddAttachment(Attachments);

if (ClipSize > 0)
firearm.MagazineAmmo = ClipSize;
int ammo = firearm.MagazineAmmo;
firearm.MaxMagazineAmmo = ClipSize;
Log.Debug($"{nameof(Name)}.{nameof(Spawn)}: Spawning weapon with {ammo} ammo.");
Pickup? pickup = firearm.CreatePickup(position);
pickup.Scale = Scale;
Expand All @@ -130,8 +132,8 @@ public override void Give(Player player, bool displayMessage = true)
if (!Attachments.IsEmpty())
firearm.AddAttachment(Attachments);

firearm.MagazineAmmo = ClipSize;
firearm.MaxMagazineAmmo = ClipSize;
if (ClipSize > 0)
firearm.MagazineAmmo = ClipSize;
}

Log.Debug($"{nameof(Give)}: Adding {item.Serial} to tracker.");
Expand All @@ -144,6 +146,7 @@ public override void Give(Player player, bool displayMessage = true)
protected override void SubscribeEvents()
{
Exiled.Events.Handlers.Player.ReloadingWeapon += OnInternalReloading;
Exiled.Events.Handlers.Player.ReloadedWeapon += OnInternalReloaded;
Exiled.Events.Handlers.Player.Shooting += OnInternalShooting;
Exiled.Events.Handlers.Player.Shot += OnInternalShot;
Exiled.Events.Handlers.Player.Hurting += OnInternalHurting;
Expand All @@ -155,6 +158,7 @@ protected override void SubscribeEvents()
protected override void UnsubscribeEvents()
{
Exiled.Events.Handlers.Player.ReloadingWeapon -= OnInternalReloading;
Exiled.Events.Handlers.Player.ReloadedWeapon -= OnInternalReloaded;
Exiled.Events.Handlers.Player.Shooting -= OnInternalShooting;
Exiled.Events.Handlers.Player.Shot -= OnInternalShot;
Exiled.Events.Handlers.Player.Hurting -= OnInternalHurting;
Expand All @@ -170,6 +174,14 @@ protected virtual void OnReloading(ReloadingWeaponEventArgs ev)
{
}

/// <summary>
/// Handles reloaded for custom weapons.
/// </summary>
/// <param name="ev"><see cref="ReloadedWeaponEventArgs"/>.</param>
protected virtual void OnReloaded(ReloadedWeaponEventArgs ev)
{
}

/// <summary>
/// Handles shooting for custom weapons.
/// </summary>
Expand Down Expand Up @@ -201,49 +213,29 @@ private void OnInternalReloading(ReloadingWeaponEventArgs ev)
if (!Check(ev.Player.CurrentItem))
return;

Log.Debug($"{nameof(Name)}.{nameof(OnInternalReloading)}: Reloading weapon. Calling external reload event..");
OnReloading(ev);

Log.Debug($"{nameof(Name)}.{nameof(OnInternalReloading)}: External event ended. {ev.IsAllowed}");
if (!ev.IsAllowed)
if (ClipSize > 0 && ev.Firearm.Base.GetTotalStoredAmmo() >= ClipSize)
{
Log.Debug($"{nameof(Name)}.{nameof(OnInternalReloading)}: External event turned is allowed to false, returning.");
ev.IsAllowed = false;
return;
}

Log.Debug($"{nameof(Name)}.{nameof(OnInternalReloading)}: Continuing with internal reload..");
ev.IsAllowed = false;

int remainingClip = ((Firearm)ev.Player.CurrentItem).MagazineAmmo;
OnReloading(ev);
}

if (remainingClip >= ClipSize)
private void OnInternalReloaded(ReloadedWeaponEventArgs ev)
{
if (!Check(ev.Player.CurrentItem))
return;

Log.Debug($"{ev.Player.Nickname} ({ev.Player.UserId}) [{ev.Player.Role}] is reloading a {Name} ({Id}) [{Type} ({remainingClip}/{ClipSize})]!");

AmmoType ammoType = ev.Firearm.AmmoType;

if (!ev.Player.Ammo.ContainsKey(ammoType.GetItemType()))
if (ClipSize > 0)
{
Log.Debug($"{nameof(Name)}.{nameof(OnInternalReloading)}: {ev.Player.Nickname} does not have ammo to reload this weapon.");
return;
int ammoChambered = ((AutomaticActionModule)ev.Firearm.Base.Modules.FirstOrDefault(x => x is AutomaticActionModule))?.SyncAmmoChambered ?? 0;
int ammodrop = -(ClipSize - ev.Firearm.MagazineAmmo) - ammoChambered;
ev.Firearm.MagazineAmmo = ClipSize - ammoChambered;
ev.Player.AddAmmo(ev.Firearm.AmmoType, (ushort)Mathf.Clamp(ammodrop, ushort.MinValue, ushort.MaxValue));
}

ev.Firearm.Reload();

byte amountToReload = (byte)Math.Min(ClipSize - remainingClip, ev.Player.Ammo[ammoType.GetItemType()]);

if (amountToReload <= 0)
return;

ev.Player.ReferenceHub.playerEffectsController.GetEffect<CustomPlayerEffects.Invisible>().Intensity = 0;

ev.Player.Ammo[ammoType.GetItemType()] -= amountToReload;
ev.Player.Inventory.SendAmmoNextFrame = true;

((Firearm)ev.Player.CurrentItem).MagazineAmmo = (byte)(((Firearm)ev.Player.CurrentItem).MagazineAmmo + amountToReload);

Log.Debug($"{ev.Player.Nickname} ({ev.Player.UserId}) [{ev.Player.Role}] reloaded a {Name} ({Id}) [{Type} ({((Firearm)ev.Player.CurrentItem).MagazineAmmo}/{ClipSize})]!");
OnReloaded(ev);
}

private void OnInternalShooting(ShootingEventArgs ev)
Expand Down
45 changes: 45 additions & 0 deletions EXILED/Exiled.Events/EventArgs/Player/ReloadedWeaponEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// -----------------------------------------------------------------------
// <copyright file="ReloadedWeaponEventArgs.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.Player
{
using API.Features;
using API.Features.Items;

using Interfaces;

/// <summary>
/// Contains all information after a player's weapon is reloaded.
/// </summary>
public class ReloadedWeaponEventArgs : IPlayerEvent, IFirearmEvent
{
/// <summary>
/// Initializes a new instance of the <see cref="ReloadedWeaponEventArgs" /> class.
/// </summary>
/// <param name="firearm">
/// <inheritdoc cref="Firearm" />
/// </param>
public ReloadedWeaponEventArgs(InventorySystem.Items.Firearms.Firearm firearm)
{
Firearm = Item.Get<Firearm>(firearm);
Player = Firearm.Owner;
}

/// <summary>
/// Gets the <see cref="API.Features.Items.Firearm" /> being reloaded.
/// </summary>
public Firearm Firearm { get; }

/// <inheritdoc/>
public Item Item => Firearm;

/// <summary>
/// Gets the player who's reloading the weapon.
/// </summary>
public Player Player { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public class ReloadingWeaponEventArgs : IPlayerEvent, IFirearmEvent, IDeniableEv
public ReloadingWeaponEventArgs(InventorySystem.Items.Firearms.Firearm firearm)
{
Firearm = Item.Get<Firearm>(firearm);
Firearm.Damage = 99555f;
Player = Firearm.Owner;
}

Expand Down
45 changes: 45 additions & 0 deletions EXILED/Exiled.Events/EventArgs/Player/UnloadedWeaponEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// -----------------------------------------------------------------------
// <copyright file="UnloadedWeaponEventArgs.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.Player
{
using API.Features;
using API.Features.Items;

using Interfaces;

/// <summary>
/// Contains all information after a player's weapon is unloaded.
/// </summary>
public class UnloadedWeaponEventArgs : IPlayerEvent, IFirearmEvent
{
/// <summary>
/// Initializes a new instance of the <see cref="UnloadedWeaponEventArgs" /> class.
/// </summary>
/// <param name="firearm">
/// <inheritdoc cref="Firearm" />
/// </param>
public UnloadedWeaponEventArgs(InventorySystem.Items.Firearms.Firearm firearm)
{
Firearm = Item.Get<Firearm>(firearm);
Player = Firearm.Owner;
}

/// <summary>
/// Gets the <see cref="API.Features.Items.Firearm" /> being unloaded.
/// </summary>
public Firearm Firearm { get; }

/// <inheritdoc/>
public Item Item => Firearm;

/// <summary>
/// Gets the player who's unloading the weapon.
/// </summary>
public Player Player { get; }
}
}
22 changes: 22 additions & 0 deletions EXILED/Exiled.Events/Handlers/Player.cs
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,11 @@ public class Player
/// </summary>
public static Event<ReloadingWeaponEventArgs> ReloadingWeapon { get; set; } = new();

/// <summary>
/// Invoked after a <see cref="API.Features.Player"/> reloads a weapon.
/// </summary>
public static Event<ReloadedWeaponEventArgs> ReloadedWeapon { get; set; } = new();

/// <summary>
/// Invoked before spawning a <see cref="API.Features.Player"/>.
/// </summary>
Expand Down Expand Up @@ -428,6 +433,11 @@ public class Player
/// </summary>
public static Event<UnloadingWeaponEventArgs> UnloadingWeapon { get; set; } = new();

/// <summary>
/// Invoked after a <see cref="API.Features.Player"/> unloads a weapon.
/// </summary>
public static Event<UnloadedWeaponEventArgs> UnloadedWeapon { get; set; } = new();

/// <summary>
/// Invoked before a <see cref="API.Features.Player"/> triggers an aim action.
/// </summary>
Expand Down Expand Up @@ -837,6 +847,12 @@ public class Player
/// <param name="ev">The <see cref="ReloadingWeaponEventArgs"/> instance.</param>
public static void OnReloadingWeapon(ReloadingWeaponEventArgs ev) => ReloadingWeapon.InvokeSafely(ev);

/// <summary>
/// Called after a <see cref="API.Features.Player"/> reloads a weapon.
/// </summary>
/// <param name="ev">The <see cref="ReloadedWeaponEventArgs"/> instance.</param>
public static void OnReloadedWeapon(ReloadedWeaponEventArgs ev) => ReloadedWeapon.InvokeSafely(ev);

/// <summary>
/// Called before spawning a <see cref="API.Features.Player"/>.
/// </summary>
Expand Down Expand Up @@ -939,6 +955,12 @@ public class Player
/// <param name="ev">The <see cref="UnloadingWeaponEventArgs"/> instance.</param>
public static void OnUnloadingWeapon(UnloadingWeaponEventArgs ev) => UnloadingWeapon.InvokeSafely(ev);

/// <summary>
/// Called after a <see cref="API.Features.Player"/> unloads a weapon.
/// </summary>
/// <param name="ev">The <see cref="UnloadedWeaponEventArgs"/> instance.</param>
public static void OnUnloadedWeapon(UnloadedWeaponEventArgs ev) => UnloadedWeapon.InvokeSafely(ev);

/// <summary>
/// Called before a <see cref="API.Features.Player"/> triggers an aim action.
/// </summary>
Expand Down
Loading
Loading