C#:
using Newtonsoft.Json;
using Oxide.Core;
using System;
using System.Linq;
using System.Collections.Generic;
namespace Oxide.Plugins
{
[Info("AttachmentExtension", "Scalbox", "1.0.1")]
[Description("Extends the use of attachments to more weapons")]
public class AttachmentExtension : RustPlugin
{
#region Fields
private Configuration _config;
private const string WeaponLasersightAttachmentName = "Weapon Lasersight";
private const string ExtendedMagazineAttachmentName = "Extended Magazine";
private const string HolosightAttachmentName = "Holosight";
private const string SilencerAttachmentName = "Silencer";
private const string ZoomScopeAttachmentName = "Zoom Scope";
private const string GasCompressionOverdriveAttachmentName = "Gas Compression Overdrive";
private const string MuzzleBoostAttachmentName = "Muzzle Boost";
private const string MuzzleBrakeAttachmentName = "Muzzle Brake";
private const string WeaponFlashlightAttachmentName = "Weapon Flashlight";
private const string TargetingAttachmentAttachmentName = "Targeting Attachment";
private const string BurstModuleAttachmentName = "Burst Module";
private const int BurstModuleItemID = 838308300; //Burst Module
// //Attachment Alias : ItemName
// private readonly Dictionary<string, string[]> _attachmentAliasToItemNameMappings = new()
// {
// { WeaponLasersightAttachmentName, new[] { "weapon.mod.lasersight" } },
// { ExtendedMagazineAttachmentName, new[] { "weapon.mod.extendedmags" } },
// { HolosightAttachmentName, new[] { "weapon.mod.holosight" } },
// { SilencerAttachmentName, new[] { "weapon.mod.silencer", "weapon.mod.sodacansilencer", "weapon.mod.oilfiltersilencer" } },
// { ZoomScopeAttachmentName, new[] { "weapon.mod.simplesight", "weapon.mod.small.scope", "weapon.mod.8x.scope" } },
// { GasCompressionOverdriveAttachmentName, new[] { "weapon.mod.gascompressionovedrive" } },
// { MuzzleBoostAttachmentName, new[] { "weapon.mod.muzzleboost" } },
// { MuzzleBrakeAttachmentName, new[] { "weapon.mod.muzzlebrake" } },
// { WeaponFlashlightAttachmentName, new[] { "weapon.mod.flashlight" } },
// { TargetingAttachmentAttachmentName, new[] { "weapon.mod.targetingattachment" } },
// { BurstModuleAttachmentName, new[] { "weapon.mod.burstmodule" } }
// };
//Attachment Alias : ItemDefinition
private readonly Dictionary<string, ItemDefinition[]> _attachmentAliasToItemDefinitionMappings = new()
{
{ WeaponLasersightAttachmentName, new[] { ItemManager.FindItemDefinition("weapon.mod.lasersight") } },
{ ExtendedMagazineAttachmentName, new[] { ItemManager.FindItemDefinition("weapon.mod.extendedmags") } },
{ HolosightAttachmentName, new[] { ItemManager.FindItemDefinition("weapon.mod.holosight") } },
{
SilencerAttachmentName,
new[]
{
ItemManager.FindItemDefinition("weapon.mod.silencer"), ItemManager.FindItemDefinition("weapon.mod.sodacansilencer"),
ItemManager.FindItemDefinition("weapon.mod.oilfiltersilencer")
}
},
{
ZoomScopeAttachmentName,
new[]
{
ItemManager.FindItemDefinition("weapon.mod.simplesight"), ItemManager.FindItemDefinition("weapon.mod.small.scope"),
ItemManager.FindItemDefinition("weapon.mod.8x.scope")
}
},
{ GasCompressionOverdriveAttachmentName, new[] { ItemManager.FindItemDefinition("weapon.mod.gascompressionovedrive") } },
{ MuzzleBoostAttachmentName, new[] { ItemManager.FindItemDefinition("weapon.mod.muzzleboost") } },
{ MuzzleBrakeAttachmentName, new[] { ItemManager.FindItemDefinition("weapon.mod.muzzlebrake") } },
{ WeaponFlashlightAttachmentName, new[] { ItemManager.FindItemDefinition("weapon.mod.flashlight") } },
{ TargetingAttachmentAttachmentName, new[] { ItemManager.FindItemDefinition("weapon.mod.targetingattachment") } },
{ BurstModuleAttachmentName, new[] { ItemManager.FindItemDefinition("weapon.mod.burstmodule") } }
};
//Attachment Alias : ItemSlot
private readonly Dictionary<string, ItemSlot[]> _attachmentAliasToItemSlotMappings = new()
{
{ WeaponLasersightAttachmentName, new[] { ItemSlot.UnderBarrel } },
{ ExtendedMagazineAttachmentName, new[] { ItemSlot.Magazine } },
{ HolosightAttachmentName, new[] { ItemSlot.Scope } },
{ SilencerAttachmentName, new[] { ItemSlot.Barrel, ItemSlot.Silencer } },
{ ZoomScopeAttachmentName, new[] { ItemSlot.Scope } },
{ GasCompressionOverdriveAttachmentName, new[] { ItemSlot.Internal } },
{ MuzzleBoostAttachmentName, new[] { ItemSlot.Barrel, ItemSlot.Silencer } },
{ MuzzleBrakeAttachmentName, new[] { ItemSlot.Barrel, ItemSlot.Silencer } },
{ WeaponFlashlightAttachmentName, new[] { ItemSlot.UnderBarrel } },
{ TargetingAttachmentAttachmentName, new[] { ItemSlot.InternalTargeting } },
{ BurstModuleAttachmentName, new[] { ItemSlot.Internal, ItemSlot.Scope } }
};
//ItemID : ItemDefinition, ItemName
private readonly Dictionary<int, (ItemDefinition ItemDef, string ItemName)> _allowedWeapons = new();
#endregion
#region Hook
// private void Init()
// {
// }
private void OnServerInitialized()
{
if (_config.Attachments.All(a => a.Value.IsNullOrEmpty() || a.Value.All(string.IsNullOrWhiteSpace)))
{
Puts("No Weapons attachments configured. Please check your config.");
Interface.Oxide.UnloadPlugin(Name);
return;
}
foreach (var attachment in _config.Attachments)
{
if (attachment.Value == null || attachment.Value.IsNullOrEmpty()) continue;
foreach (var weapon in attachment.Value)
{
if (string.IsNullOrEmpty(weapon)) continue;
var itemDef = ItemManager.FindItemDefinition(weapon);
if (!itemDef) continue;
_allowedWeapons.TryAdd(itemDef.itemid, (itemDef, itemDef.shortname));
}
}
}
private void Unload()
{
}
protected override void LoadConfig()
{
base.LoadConfig();
_config = Config.ReadObject<Configuration>();
if (!Equals(_config.VersionNumber, Version))
{
UpdateConfigValues();
_config.VersionNumber = Version;
}
SaveConfig();
}
private void UpdateConfigValues()
{
}
protected override void LoadDefaultConfig()
{
_config = Configuration.CreateConfig();
}
protected override void SaveConfig() => Config.WriteObject(_config);
private void OnItemAddedToContainer(ItemContainer container, Item item)
{
ExtendWeaponAttachment(item);
}
//TODO Se l'arma non è piu configurata, disabilita l'inserimento dell'attachment personalizzato.
//CanAcceptItem da solo non va bene, bisogna salvarsi l'ItemSlot aggiunto all'arma in un file dati, e rimuovere l'ItemSlot quando l'arma viene rimossa/aggiunta dal container
// ItemContainer.CanAcceptResult? CanAcceptItem(ItemContainer container, Item item, int targetPos)
// {
// // Verifiche di base sull'item e il giocatore
// if (item == null || item.info == null) return null;
//
// var player = item.GetOwnerPlayer();
// if (player == null || player.IsNpc) return null;
//
// // Controlla se l'item è un modulo burst o un'arma
// if (item.info.itemid != BurstModuleItemID && item.info.category != ItemCategory.Weapon) return null;
//
// // Ottiene l'arma dal container
// var weaponItem = container.parent;
// if (weaponItem == null || weaponItem.info == null) return null;
//
// // Verifica se l'arma è nella lista delle armi consentite
// if (!_allowedWeapons.ContainsKey(weaponItem.info.itemid)) return null;
//
// // Trova il gruppo di accessori corrispondente all'item
// var attachmentGroup = _attachmentAliasToItemDefinitionMappings.FirstOrDefault(a => a.Value.Any(def => def.itemid == item.info.itemid));
//
// // Verifica se il gruppo è valido
// if (string.IsNullOrWhiteSpace(attachmentGroup.Key) || attachmentGroup.Value.IsNullOrEmpty()) return null;
//
// // Controlla se l'accessorio è consentito per questa arma
// if (!_config.Attachments.TryGetValue(attachmentGroup.Key, out var allowedWeapons)) return null;
// if (allowedWeapons == null || allowedWeapons.IsNullOrEmpty()) return null;
//
// // Se l'arma non è nella lista delle armi consentite per questo accessorio, impedisci l'aggiunta
// if (!allowedWeapons.Contains(weaponItem.info.shortname)) return ItemContainer.CanAcceptResult.CannotAccept;
//
// return null;
// }
#endregion
#region Core
private void ExtendWeaponAttachment(Item weaponItem)
{
if (weaponItem == null || weaponItem.info == null) return;
if (weaponItem.info.itemid != BurstModuleItemID && weaponItem.info.category != ItemCategory.Weapon) return;
if (!_allowedWeapons.TryGetValue(weaponItem.info.itemid, out var allowedWeapon)) return;
if (weaponItem.contents?.availableSlots == null || weaponItem.contents.availableSlots.IsEmpty()) return;
var allowedAttachments = _config.Attachments
.Where(a => a.Value != null && a.Value.Any(w => w.Equals(weaponItem.info.shortname)))
.Select(a => a.Key).ToArray();
foreach (var allowedAttachment in allowedAttachments)
{
var itemSlots = _attachmentAliasToItemSlotMappings.GetValueOrDefault(allowedAttachment, Array.Empty<ItemSlot>());
if (itemSlots == null || itemSlots.Length == 0) continue;
foreach (var itemSlot in itemSlots)
{
// Add the targeting slot if it doesn't exist
if (!weaponItem.contents.availableSlots.Contains(itemSlot))
{
weaponItem.contents.availableSlots.Add(itemSlot);
// weaponItem.MarkDirty();
}
}
}
}
#endregion
#region Class
private class Configuration
{
//Attachments: ItemName (Weapon)
[JsonProperty("Attachments")] public Dictionary<string, string[]> Attachments;
public VersionNumber VersionNumber;
public static Configuration CreateConfig()
{
return new Configuration
{
Attachments = new Dictionary<string, string[]>
{
{ WeaponLasersightAttachmentName, Array.Empty<string>() },
{ ExtendedMagazineAttachmentName, Array.Empty<string>() },
{ HolosightAttachmentName, Array.Empty<string>() },
{ SilencerAttachmentName, Array.Empty<string>() },
{ ZoomScopeAttachmentName, Array.Empty<string>() },
{ GasCompressionOverdriveAttachmentName, Array.Empty<string>() },
{ MuzzleBoostAttachmentName, Array.Empty<string>() },
{ MuzzleBrakeAttachmentName, Array.Empty<string>() },
{ WeaponFlashlightAttachmentName, Array.Empty<string>() },
{
TargetingAttachmentAttachmentName, new[]
{
"lmg.m249",
"rifle.l96",
"rifle.bolt",
"hmlmg",
"smg.mp5"
}
},
{ BurstModuleAttachmentName, Array.Empty<string>() }
},
VersionNumber = OxideMod.Version
};
}
}
#endregion
}
}