From 72e93841f4a9cbb52844f138959fdc0fbb098a0d Mon Sep 17 00:00:00 2001 From: Banalny-Banan Date: Mon, 23 Dec 2024 15:48:04 +0200 Subject: [PATCH 1/7] Added Ammo and MaxAmmo back with setters --- EXILED/Exiled.API/Features/Items/Firearm.cs | 72 ++++++++++++++++++--- 1 file changed, 64 insertions(+), 8 deletions(-) diff --git a/EXILED/Exiled.API/Features/Items/Firearm.cs b/EXILED/Exiled.API/Features/Items/Firearm.cs index 98cd780c2..3514d24b2 100644 --- a/EXILED/Exiled.API/Features/Items/Firearm.cs +++ b/EXILED/Exiled.API/Features/Items/Firearm.cs @@ -161,11 +161,6 @@ public int BarrelAmmo } } - /// - /// Gets the total amount of ammo in the firearm. - /// - public int TotalAmmo => Base.GetTotalStoredAmmo(); - /// /// Gets or sets the max ammo for this firearm. /// @@ -193,12 +188,73 @@ public int MaxBarrelAmmo } /// - /// Gets the total amount of ammo in the firearm. + /// Gets or sets the maximum amount of ammo in the firearm. + /// + public int MaxAmmo + { + get => Base.GetTotalMaxAmmo(); + set + { + int difference = value - MaxAmmo; + PrimaryMagazine.MaxAmmo = Mathf.Clamp(PrimaryMagazine.MaxAmmo + difference, 0, byte.MaxValue); + } + } + + /// + /// Gets or sets the amount of ammo in the firearm. /// - public int TotalMaxAmmo => Base.GetTotalMaxAmmo(); + public int Ammo + { + get => Base.GetTotalStoredAmmo(); + set + { + // Magazines that contain most of the ammo and can be reloaded + IPrimaryAmmoContainerModule primaryContainer = PrimaryMagazine.Magazine; + + // Barrels that may contain some ammo in them + var automaticActionBarrel = BarrelMagazine.AmmoContainerModule as AutomaticActionModule; + + // Other type of barrels that also contain ammo but don't have AmmoStored setter + var pumpActionBarrel = BarrelMagazine.AmmoContainerModule as PumpActionModule; + + value = Mathf.Clamp(value, 0, Base is ParticleDisruptor ? 254 : byte.MaxValue); + + // Set everything to 0 + primaryContainer?.ServerModifyAmmo(-primaryContainer.AmmoStored); + + if (automaticActionBarrel is not null) + { + automaticActionBarrel.AmmoStored = 0; + } + else if (pumpActionBarrel is not null) + { + pumpActionBarrel.SyncCocked = 0; + pumpActionBarrel.SyncChambered = 0; + } + + if (value == 0) + return; + + // Distribute the ammo between containers + if (primaryContainer is not null) + { + var addedAmmo = Mathf.Clamp(byte.MaxValue - primaryContainer.AmmoStored, 0, value); + primaryContainer.ServerModifyAmmo(addedAmmo); + } + else if (pumpActionBarrel is not null) + { + var addedAmmo = Mathf.Clamp(byte.MaxValue - pumpActionBarrel.SyncChambered, 0, value); + pumpActionBarrel.SyncCocked = addedAmmo; + } + + // Reload action modules + pumpActionBarrel?.Pump(); + automaticActionBarrel?.ServerCycleAction(); + } + } /// - /// Gets or sets a ammo drain per shoot. + /// Gets or sets the ammo drain per shoot. /// /// /// Always by default. From a5888d1f8eb8df6bd8d5add5742b3acd8e4d9e2c Mon Sep 17 00:00:00 2001 From: Banalny-Banan Date: Mon, 23 Dec 2024 15:56:35 +0200 Subject: [PATCH 2/7] Now using exiled magazines --- EXILED/Exiled.API/Features/Items/Firearm.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/EXILED/Exiled.API/Features/Items/Firearm.cs b/EXILED/Exiled.API/Features/Items/Firearm.cs index 3514d24b2..f6277cfdc 100644 --- a/EXILED/Exiled.API/Features/Items/Firearm.cs +++ b/EXILED/Exiled.API/Features/Items/Firearm.cs @@ -212,10 +212,10 @@ public int Ammo IPrimaryAmmoContainerModule primaryContainer = PrimaryMagazine.Magazine; // Barrels that may contain some ammo in them - var automaticActionBarrel = BarrelMagazine.AmmoContainerModule as AutomaticActionModule; + var automaticActionBarrel = BarrelMagazine as AutomaticBarrelMagazine; // Other type of barrels that also contain ammo but don't have AmmoStored setter - var pumpActionBarrel = BarrelMagazine.AmmoContainerModule as PumpActionModule; + var pumpActionBarrel = BarrelMagazine as PumpBarrelMagazine; value = Mathf.Clamp(value, 0, Base is ParticleDisruptor ? 254 : byte.MaxValue); @@ -224,12 +224,12 @@ public int Ammo if (automaticActionBarrel is not null) { - automaticActionBarrel.AmmoStored = 0; + automaticActionBarrel.Ammo = 0; } else if (pumpActionBarrel is not null) { - pumpActionBarrel.SyncCocked = 0; - pumpActionBarrel.SyncChambered = 0; + pumpActionBarrel.CockedAmmo = 0; + pumpActionBarrel.Ammo = 0; } if (value == 0) @@ -243,13 +243,13 @@ public int Ammo } else if (pumpActionBarrel is not null) { - var addedAmmo = Mathf.Clamp(byte.MaxValue - pumpActionBarrel.SyncChambered, 0, value); - pumpActionBarrel.SyncCocked = addedAmmo; + var addedAmmo = Mathf.Clamp(byte.MaxValue - pumpActionBarrel.Ammo, 0, value); + pumpActionBarrel.Ammo = addedAmmo; } // Reload action modules - pumpActionBarrel?.Pump(); - automaticActionBarrel?.ServerCycleAction(); + pumpActionBarrel?.PumpBarrel.Pump(); + automaticActionBarrel?.AutomaticBarrel.ServerCycleAction(); } } From f3f8860b1aa79dbeecbe772ea272183e72e425bd Mon Sep 17 00:00:00 2001 From: Banalny-Banan Date: Mon, 23 Dec 2024 16:02:18 +0200 Subject: [PATCH 3/7] Preferences methods are now static cause they can be --- EXILED/Exiled.API/Features/Items/Firearm.cs | 328 +++++++++++--------- 1 file changed, 173 insertions(+), 155 deletions(-) diff --git a/EXILED/Exiled.API/Features/Items/Firearm.cs b/EXILED/Exiled.API/Features/Items/Firearm.cs index f6277cfdc..cff010ad9 100644 --- a/EXILED/Exiled.API/Features/Items/Firearm.cs +++ b/EXILED/Exiled.API/Features/Items/Firearm.cs @@ -352,6 +352,178 @@ public RecoilSettings Recoil public static Firearm Create(FirearmType type) => type is not FirearmType.None ? (Firearm)Create(type.GetItemType()) : null; + /// + /// Adds or replaces an existing preference to the . + /// + /// The of which must be added. + /// The to add. + /// The [] to add. + public static void AddPreference(Player player, FirearmType itemType, AttachmentIdentifier[] attachments) + { + foreach (KeyValuePair> kvp in PlayerPreferences) + { + if (kvp.Key != player) + continue; + + if (AttachmentsServerHandler.PlayerPreferences.TryGetValue(player.ReferenceHub, out Dictionary dictionary)) + dictionary[itemType.GetItemType()] = attachments.GetAttachmentsCode(); + } + } + + /// + /// Adds or replaces an existing preference to the . + /// + /// The of which must be added. + /// The of and [] to add. + public static void AddPreference(Player player, KeyValuePair preference) => AddPreference(player, preference.Key, preference.Value); + + /// + /// Adds or replaces an existing preference to the . + /// + /// The of which must be added. + /// The of and [] to add. + public static void AddPreference(Player player, Dictionary preference) + { + foreach (KeyValuePair kvp in preference) + AddPreference(player, kvp); + } + + /// + /// Adds or replaces an existing preference to the . + /// + /// The of of which must be added. + /// The to add. + /// The [] to add. + public static void AddPreference(IEnumerable players, FirearmType type, AttachmentIdentifier[] attachments) + { + foreach (Player player in players) + AddPreference(player, type, attachments); + } + + /// + /// Adds or replaces an existing preference to the . + /// + /// The of of which must be added. + /// The of and [] to add. + public static void AddPreference(IEnumerable players, KeyValuePair preference) + { + foreach (Player player in players) + AddPreference(player, preference.Key, preference.Value); + } + + /// + /// Adds or replaces an existing preference to the . + /// + /// The of of which must be added. + /// The of and [] to add. + public static void AddPreference(IEnumerable players, Dictionary preference) + { + foreach ((Player player, KeyValuePair kvp) in players.SelectMany(player => preference.Select(kvp => (player, kvp)))) + AddPreference(player, kvp); + } + + /// + /// Removes a preference from the if it already exists. + /// + /// The of which must be removed. + /// The to remove. + public static void RemovePreference(Player player, FirearmType type) + { + foreach (KeyValuePair> kvp in PlayerPreferences) + { + if (kvp.Key != player) + continue; + + if (AttachmentsServerHandler.PlayerPreferences.TryGetValue(player.ReferenceHub, out Dictionary dictionary)) + dictionary[type.GetItemType()] = type.GetBaseCode(); + } + } + + /// + /// Removes a preference from the if it already exists. + /// + /// The of of which must be removed. + /// The to remove. + public static void RemovePreference(IEnumerable players, FirearmType type) + { + foreach (Player player in players) + RemovePreference(player, type); + } + + /// + /// Removes a preference from the if it already exists. + /// + /// The of which must be removed. + /// The of to remove. + public static void RemovePreference(Player player, IEnumerable types) + { + foreach (FirearmType itemType in types) + RemovePreference(player, itemType); + } + + /// + /// Removes a preference from the if it already exists. + /// + /// The of of which must be removed. + /// The of to remove. + public static void RemovePreference(IEnumerable players, IEnumerable types) + { + foreach ((Player player, FirearmType firearmType) in players.SelectMany(player => types.Select(itemType => (player, itemType)))) + RemovePreference(player, firearmType); + } + + /// + /// Clears all the existing preferences from . + /// + /// The of which must be cleared. + public static void ClearPreferences(Player player) + { + if (AttachmentsServerHandler.PlayerPreferences.TryGetValue(player.ReferenceHub, out Dictionary dictionary)) + { + foreach (KeyValuePair kvp in dictionary) + dictionary[kvp.Key] = kvp.Key.GetFirearmType().GetBaseCode(); + } + } + + /// + /// Clears all the existing preferences from . + /// + /// The of of which must be cleared. + public static void ClearPreferences(IEnumerable players) + { + foreach (Player player in players) + ClearPreferences(player); + } + + /// + /// Clears all the existing preferences from . + /// + public static void ClearPreferences() + { + foreach (Player player in Player.List) + ClearPreferences(player); + } + + /// + /// Tries to get a specific module of the . + /// + /// The type of the module to get. + /// Module if found, otherwise . + /// Whether to ignore submodules. + /// A value indicating whether the module was found. + /// + /// Modules are a part of the new firearm system. They define the behaviour of a firearm. + /// They are magazines that store ammo, barrels that shoot, and even recoil patterns. + /// By altering their settings it is possible to do almost anything with a given weapon. + /// + /// + /// + /// + /// + /// + public bool TryGetModule(out T module, bool ignoreSubmodules = true) + => Base.TryGetModule(out module, ignoreSubmodules); + /// /// Adds a to the firearm. /// @@ -550,158 +722,6 @@ public bool TryGetAttachment(AttachmentName attachmentName, out Attachment firea return true; } - /// - /// Adds or replaces an existing preference to the . - /// - /// The of which must be added. - /// The to add. - /// The [] to add. - public void AddPreference(Player player, FirearmType itemType, AttachmentIdentifier[] attachments) - { - foreach (KeyValuePair> kvp in PlayerPreferences) - { - if (kvp.Key != player) - continue; - - if (AttachmentsServerHandler.PlayerPreferences.TryGetValue(player.ReferenceHub, out Dictionary dictionary)) - dictionary[itemType.GetItemType()] = attachments.GetAttachmentsCode(); - } - } - - /// - /// Adds or replaces an existing preference to the . - /// - /// The of which must be added. - /// The of and [] to add. - public void AddPreference(Player player, KeyValuePair preference) => AddPreference(player, preference.Key, preference.Value); - - /// - /// Adds or replaces an existing preference to the . - /// - /// The of which must be added. - /// The of and [] to add. - public void AddPreference(Player player, Dictionary preference) - { - foreach (KeyValuePair kvp in preference) - AddPreference(player, kvp); - } - - /// - /// Adds or replaces an existing preference to the . - /// - /// The of of which must be added. - /// The to add. - /// The [] to add. - public void AddPreference(IEnumerable players, FirearmType type, AttachmentIdentifier[] attachments) - { - foreach (Player player in players) - AddPreference(player, type, attachments); - } - - /// - /// Adds or replaces an existing preference to the . - /// - /// The of of which must be added. - /// The of and [] to add. - public void AddPreference(IEnumerable players, KeyValuePair preference) - { - foreach (Player player in players) - AddPreference(player, preference.Key, preference.Value); - } - - /// - /// Adds or replaces an existing preference to the . - /// - /// The of of which must be added. - /// The of and [] to add. - public void AddPreference(IEnumerable players, Dictionary preference) - { - foreach ((Player player, KeyValuePair kvp) in players.SelectMany(player => preference.Select(kvp => (player, kvp)))) - AddPreference(player, kvp); - } - - /// - /// Removes a preference from the if it already exists. - /// - /// The of which must be removed. - /// The to remove. - public void RemovePreference(Player player, FirearmType type) - { - foreach (KeyValuePair> kvp in PlayerPreferences) - { - if (kvp.Key != player) - continue; - - if (AttachmentsServerHandler.PlayerPreferences.TryGetValue(player.ReferenceHub, out Dictionary dictionary)) - dictionary[type.GetItemType()] = type.GetBaseCode(); - } - } - - /// - /// Removes a preference from the if it already exists. - /// - /// The of of which must be removed. - /// The to remove. - public void RemovePreference(IEnumerable players, FirearmType type) - { - foreach (Player player in players) - RemovePreference(player, type); - } - - /// - /// Removes a preference from the if it already exists. - /// - /// The of which must be removed. - /// The of to remove. - public void RemovePreference(Player player, IEnumerable types) - { - foreach (FirearmType itemType in types) - RemovePreference(player, itemType); - } - - /// - /// Removes a preference from the if it already exists. - /// - /// The of of which must be removed. - /// The of to remove. - public void RemovePreference(IEnumerable players, IEnumerable types) - { - foreach ((Player player, FirearmType firearmType) in players.SelectMany(player => types.Select(itemType => (player, itemType)))) - RemovePreference(player, firearmType); - } - - /// - /// Clears all the existing preferences from . - /// - /// The of which must be cleared. - public void ClearPreferences(Player player) - { - if (AttachmentsServerHandler.PlayerPreferences.TryGetValue(player.ReferenceHub, out Dictionary dictionary)) - { - foreach (KeyValuePair kvp in dictionary) - dictionary[kvp.Key] = kvp.Key.GetFirearmType().GetBaseCode(); - } - } - - /// - /// Clears all the existing preferences from . - /// - /// The of of which must be cleared. - public void ClearPreferences(IEnumerable players) - { - foreach (Player player in players) - ClearPreferences(player); - } - - /// - /// Clears all the existing preferences from . - /// - public void ClearPreferences() - { - foreach (Player player in Player.List) - ClearPreferences(player); - } - /// /// Reloads current . /// @@ -722,9 +742,7 @@ public void Reload() /// New object. public override Item Clone() { - Firearm cloneableItem = new(Type) - { - }; + Firearm cloneableItem = new(Type); // TODO Not finish /* From 85db023b757ee4d405c39978e2a27e1ed967fc72 Mon Sep 17 00:00:00 2001 From: Banalny-Banan Date: Mon, 23 Dec 2024 16:03:24 +0200 Subject: [PATCH 4/7] Aiming check now uses module interface instead of a derived type --- EXILED/Exiled.API/Features/Items/Firearm.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EXILED/Exiled.API/Features/Items/Firearm.cs b/EXILED/Exiled.API/Features/Items/Firearm.cs index cff010ad9..615682e90 100644 --- a/EXILED/Exiled.API/Features/Items/Firearm.cs +++ b/EXILED/Exiled.API/Features/Items/Firearm.cs @@ -280,7 +280,7 @@ public int Ammo /// /// Gets a value indicating whether the firearm is being aimed. /// - public bool Aiming => Base.TryGetModule(out LinearAdsModule module) && module.AdsTarget; + public bool Aiming => Base.TryGetModule(out IAdsModule module) && module.AdsTarget; /// /// Gets a value indicating whether the firearm's flashlight module is enabled. From fdde4de104dcb111dbec674ab3372ca3607d2278 Mon Sep 17 00:00:00 2001 From: Banalny-Banan Date: Mon, 23 Dec 2024 16:18:20 +0200 Subject: [PATCH 5/7] backward compatibility for TotalAmmo & TotalMaxAmmo --- EXILED/Exiled.API/Features/Items/Firearm.cs | 22 ++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/EXILED/Exiled.API/Features/Items/Firearm.cs b/EXILED/Exiled.API/Features/Items/Firearm.cs index 615682e90..2730d1733 100644 --- a/EXILED/Exiled.API/Features/Items/Firearm.cs +++ b/EXILED/Exiled.API/Features/Items/Firearm.cs @@ -187,6 +187,26 @@ public int MaxBarrelAmmo } } + /// + /// Gets or sets the maximum amount of ammo in the firearm. + /// + [Obsolete("Use MaxAmmo instead.")] + public int TotalMaxAmmo + { + get => MaxAmmo; + set => MaxAmmo = value; + } + + /// + /// Gets or sets the amount of ammo in the firearm. + /// + [Obsolete("Use Ammo instead.")] + public int TotalAmmo + { + get => Ammo; + set => Ammo = value; + } + /// /// Gets or sets the maximum amount of ammo in the firearm. /// @@ -352,7 +372,7 @@ public RecoilSettings Recoil public static Firearm Create(FirearmType type) => type is not FirearmType.None ? (Firearm)Create(type.GetItemType()) : null; - /// + /// /// Adds or replaces an existing preference to the . /// /// The of which must be added. From cf9aba7f83e0dfc7824449a493f872654bc6cd5d Mon Sep 17 00:00:00 2001 From: Banalny-Banan Date: Mon, 23 Dec 2024 20:39:15 +0200 Subject: [PATCH 6/7] sync fix --- EXILED/Exiled.API/Features/Items/Firearm.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/EXILED/Exiled.API/Features/Items/Firearm.cs b/EXILED/Exiled.API/Features/Items/Firearm.cs index 2730d1733..32bbf5f9f 100644 --- a/EXILED/Exiled.API/Features/Items/Firearm.cs +++ b/EXILED/Exiled.API/Features/Items/Firearm.cs @@ -229,7 +229,7 @@ public int Ammo set { // Magazines that contain most of the ammo and can be reloaded - IPrimaryAmmoContainerModule primaryContainer = PrimaryMagazine.Magazine; + PrimaryMagazine primaryContainer = PrimaryMagazine; // Barrels that may contain some ammo in them var automaticActionBarrel = BarrelMagazine as AutomaticBarrelMagazine; @@ -240,7 +240,10 @@ public int Ammo value = Mathf.Clamp(value, 0, Base is ParticleDisruptor ? 254 : byte.MaxValue); // Set everything to 0 - primaryContainer?.ServerModifyAmmo(-primaryContainer.AmmoStored); + if (primaryContainer is not null) + { + primaryContainer.Ammo = 0; + } if (automaticActionBarrel is not null) { @@ -258,8 +261,8 @@ public int Ammo // Distribute the ammo between containers if (primaryContainer is not null) { - var addedAmmo = Mathf.Clamp(byte.MaxValue - primaryContainer.AmmoStored, 0, value); - primaryContainer.ServerModifyAmmo(addedAmmo); + var addedAmmo = Mathf.Clamp(byte.MaxValue - primaryContainer.Ammo, 0, value); + primaryContainer.Ammo = addedAmmo; } else if (pumpActionBarrel is not null) { From e29f0229f535183eab57f0bf1907c97bb024033b Mon Sep 17 00:00:00 2001 From: Banalny-Banan Date: Tue, 24 Dec 2024 00:50:02 +0200 Subject: [PATCH 7/7] more utility methods --- EXILED/Exiled.API/Features/Items/Firearm.cs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/EXILED/Exiled.API/Features/Items/Firearm.cs b/EXILED/Exiled.API/Features/Items/Firearm.cs index 32bbf5f9f..1aec2e8e4 100644 --- a/EXILED/Exiled.API/Features/Items/Firearm.cs +++ b/EXILED/Exiled.API/Features/Items/Firearm.cs @@ -745,6 +745,27 @@ public bool TryGetAttachment(AttachmentName attachmentName, out Attachment firea return true; } + /// + /// Gets stats of the attachments of the firearm. + /// + /// The to get. + /// The value of the specified parameter. + public float GetAttachmentsValue(AttachmentParam parameter) => Base.AttachmentsValue(parameter); + + /// + /// Checks if the firearm has a specific advantage. + /// + /// The to check. + /// A value indicating whether the firearm has the specified advantage. + public bool HasAdvantage(AttachmentDescriptiveAdvantages flag) => Base.HasAdvantageFlag(flag); + + /// + /// Checks if the firearm has a specific downside. + /// + /// The to check. + /// A value indicating whether the firearm has the specified downside. + public bool HasDownside(AttachmentDescriptiveDownsides flag) => Base.HasDownsideFlag(flag); + /// /// Reloads current . ///