C#:
// Requires: CustomItemDefinitions
// Reference: 0Harmony
#if CARBON
using HarmonyLib;
#else
using HarmonyLib;
#endif
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using UnityEngine;
using System.Reflection.Emit;
using static Oxide.Plugins.CustomItemDefinitions;
namespace Oxide.Plugins {
[Info("Customizable Weapons", "0xF [dsc.gg/0xf-plugins]", "1.5.21")]
public class CustomizableWeapons : RustPlugin {
#region Consts
public const ItemContainer.Flag NoSortify = (ItemContainer.Flag)(8192) | (ItemContainer.Flag)(16384);
private const ItemDefinition.Flag CUSTOMWEAPON_FLAG = (ItemDefinition.Flag)(32768);
#endregion
#region Variables
private static CustomizableWeapons Plugin;
#endregion
#region PluginReference
[PluginReference]
private Plugin RustTranslationAPI;
#endregion
#region Permissions
const string giveCommandPerm = "customizableweapons.give";
const string iconShowPerm = "customizableweapons.icon.show";
const string iconHidePerm = "customizableweapons.icon.hide";
#endregion
#region Hooks
private void Init() {
Plugin = this;
permission.RegisterPermission(giveCommandPerm, this);
permission.RegisterPermission(iconShowPerm, this);
permission.RegisterPermission(iconHidePerm, this);
LoadConfig();
if (config.GlobalSettings.GiveOptions.Attachments == null) config.GlobalSettings.GiveOptions.Attachments = ItemManager.itemDictionaryByName.Keys.Where(shortname => shortname.StartsWith("weapon.mod")).ToDictionary(x => x, x => false);
config.DataItems.Initialize(this);
RegisterCustomItemDefinitions();
SaveConfig();
LoadLang();
List<WeaponData> weaponDatas = new List<WeaponData>();
weaponDatas.AddRange(config.DataItems.Default.Values);
foreach (var list in config.DataItems.Permissions) weaponDatas.AddRange(list.Value.Values);
weaponDatas.AddRange(config.DataItems.Custom.Values);
foreach (var _wd in weaponDatas) {
if (_wd.DamageTypes == null) continue;
if (_wd.DamageTypeList == null) _wd.DamageTypeList = new Dictionary<string, Rust.DamageTypeList>();
foreach (var ammo_pair in _wd.DamageTypes) {
if (!_wd.DamageTypeList.ContainsKey(ammo_pair.Key)) _wd.DamageTypeList[ammo_pair.Key] = new Rust.DamageTypeList();
for (int i = 0; i < DamageTypes.Count; i++) {
Rust.DamageType type = DamageTypes[i];
string DamageTypeName = DamageTypeNames.Values.ElementAt(i);
if (_wd.DamageTypes[ammo_pair.Key].ContainsKey(DamageTypeName)) _wd.DamageTypeList[ammo_pair.Key].Add(type, _wd.DamageTypes[ammo_pair.Key][DamageTypeName]);
}
;
}
}
foreach (var perm in config.DataItems.Permissions) permission.RegisterPermission($"customizableweapons.{perm.Key}", this);
}
void RegisterCustomItemDefinitions() {
foreach ((string shortname, CustomItem item) in config.DataItems.Custom) {
ItemDefinition parentDefinition = ItemManager.FindItemDefinition(item.Shortname);
if (parentDefinition == null) continue;
ItemDefinition registeredDefinition = CustomItemDefinitions.RegisterPluginItemDefinition(new CustomItemDefinition {
shortname = shortname, parentItemId = parentDefinition.itemid, maxStackSize = 1, flags = CUSTOMWEAPON_FLAG, defaultName = item.Name, defaultDescription = item.Description, defaultSkinId = item.SkinId, itemMods = new List<ItemMod>(parentDefinition.itemMods) {
new ItemModEntitySkinner() {
skinID = item.SkinId
}
}
.ToArray()
}
, this);
}
}
private class ItemModEntitySkinner : ItemMod {
public override void OnItemCreated(Item item) {
base.OnItemCreated(item);
if (skinID > 0) {
BaseEntity heldEntity = item.GetHeldEntity();
if (heldEntity == null) return;
heldEntity.skinID = skinID;
heldEntity.SendNetworkUpdate();
}
}
public ulong skinID;
}
private void OnServerInitialized() {
LoadIcon();
BasePlayer.activePlayerList.ToList().ForEach(player => AddUiIcon(player));
}
private void OnUserPermissionGranted(string playerId, string perm) {
if (perm != iconShowPerm && perm != iconHidePerm) return;
BasePlayer player = BasePlayer.Find(playerId);
if (player == null) return;
OnPermissionsChanged(player);
}
private void OnUserPermissionRevoked(string playerId, string perm) {
if (perm != iconShowPerm && perm != iconHidePerm) return;
BasePlayer player = BasePlayer.Find(playerId);
if (player == null) return;
OnPermissionsChanged(player);
}
private void OnGroupPermissionGranted(string groupName, string perm) {
if (perm != iconShowPerm && perm != iconHidePerm) return;
BasePlayer.activePlayerList.ToList().ForEach(p => OnPermissionsChanged(p));
}
private void OnGroupPermissionRevoked(string groupName, string perm) {
if (perm != iconShowPerm && perm != iconHidePerm) return;
BasePlayer.activePlayerList.ToList().ForEach(p => OnPermissionsChanged(p));
}
private object OnWeaponReload(BaseProjectile weapon, BasePlayer player) {
Item item = weapon.GetCachedItem();
if (item == null) return null;
WeaponData weaponData;
if (TryGetWeaponData(player, item, out weaponData)) {
if (weaponData.FastReload) {
if (weapon.TryReloadMagazine(player.inventory, -1)) {
weapon.SetHeld(false);
weapon.SendChildrenNetworkUpdateImmediate();
timer.Once(0.2f, () => {
if (player.GetActiveItem().uid == weapon.ownerItemUID) weapon.SetHeld(true);
}
);
return false;
}
}
}
return null;
}
void OnMagazineReload(BaseProjectile weapon, IAmmoContainer ammoSource, BasePlayer owner) {
SetupMagizineCapacity(weapon);
}
private object OnWeaponModChange(BaseProjectile weapon, BasePlayer player) {
if (weapon == null) return null;
var currentCapacity = weapon.primaryMagazine.capacity;
SetupMagizineCapacity(weapon);
if (!config.GlobalSettings.DisableUnload) {
if (currentCapacity == weapon.primaryMagazine.capacity) return false;
if (weapon.primaryMagazine.contents > 0 && weapon.primaryMagazine.contents > weapon.primaryMagazine.capacity) {
Item item = weapon.GetItem();
if (item != null && player != null) weapon.UnloadAmmo(item, player);
}
}
return false;
}
void OnImpactEffectCreate(HitInfo info) {
AttackEntity weapon = info.Weapon;
if (weapon != null) {
CustomItem customItem;
Item item = weapon.GetCachedItem();
if (item == null || item.info) return;
if (item.info.HasFlag(CUSTOMWEAPON_FLAG) && TryGetCustomItem(item.info, out customItem)) {
BaseEntity hitEntity = info.HitEntity;
if (hitEntity.IsValid()) {
if (customItem.EffectsEntity.ElecticBalls > 0) for (int i = 0; i < customItem.EffectsEntity.ElecticBalls; i++) Effect.server.Run("assets/prefabs/locks/keypad/effects/lock.code.shock.prefab", info.HitPositionWorld + UnityEngine.Random.insideUnitSphere * 1.5f);
}
else {
if (customItem.EffectsGround.ElecticBall) Effect.server.Run("assets/prefabs/locks/keypad/effects/lock.code.shock.prefab", info.HitPositionWorld);
}
}
}
}
void UpdateItemName(Item item) {
if (item == null) return;
NextTick(() => {
ItemDefinition itemDef = item.info;
if (itemDef == null) return;
CustomItem customItem;
if (itemDef.HasFlag(CUSTOMWEAPON_FLAG) && TryGetCustomItem(itemDef, out customItem)) {
var nameLangKey = $"{itemDef.shortname}:Name";
var itemName = GetMessage(nameLangKey, item.GetOwnerPlayer()?.UserIDString);
if (itemName == nameLangKey) itemName = customItem.Name;
SetName(item, customItem, itemName);
if (customItem.SkinId != 0) item.skin = customItem.SkinId;
item.MarkDirty();
}
else {
WeaponData weaponData;
if (TryGetWeaponData(item.GetOwnerPlayer(), item, out weaponData)) {
SetName(item, weaponData);
item.MarkDirty();
}
}
}
);
}
private void OnItemAddedToContainer(ItemContainer container, Item item) {
if (!container.HasFlag(ItemContainer.Flag.IsPlayer)) return;
if (container.playerOwner?.inventory?.loot?.IsLooting() != false) return;
if (!IsWeapon(item)) return;
UpdateItemName(item);
NextTick(() => {
SetupMagizineCapacity(item.GetHeldEntity() as BaseProjectile);
}
);
}
private void OnRocketLaunched(BasePlayer player, BaseEntity entity) {
var explosion = entity?.GetComponent<TimedExplosive>();
if (explosion == null) return;
Item item = player.GetActiveItem();
if (item == null) return;
UpdateHitDamage(explosion.damageTypes, item, player);
}
private void OnExplosiveThrown(BasePlayer player, BaseEntity entity) {
var explosion = entity?.GetComponent<TimedExplosive>();
if (explosion == null) return;
Item item = player.GetActiveItem();
if (item == null) return;
UpdateHitDamage(explosion.damageTypes, item, player);
}
private void OnExplosiveDropped(BasePlayer player, BaseEntity entity) {
var explosion = entity?.GetComponent<TimedExplosive>();
if (explosion == null) return;
Item item = player.GetActiveItem();
if (item == null) return;
UpdateHitDamage(explosion.damageTypes, item, player);
}
void OnEntityTakeDamage(BaseCombatEntity victim, HitInfo info) {
BasePlayer initiator = info.Initiator as BasePlayer;
if (initiator == null) return;
if (info.Weapon == null) {
Item activeItem = initiator.GetActiveItem();
if (activeItem != null) {
AttackEntity attackHeldEntity = activeItem.GetHeldEntity() as AttackEntity;
if (info.WeaponPrefab != null && attackHeldEntity != null && attackHeldEntity.PrefabName != info.WeaponPrefab.PrefabName) return;
info.Weapon = attackHeldEntity;
}
}
if (info.Weapon == null) return;
var item = info.Weapon.GetCachedItem();
if (item == null) return;
var ammoType = string.Empty;
if (info.Weapon is BaseProjectile) ammoType = (info.Weapon as BaseProjectile).primaryMagazine.ammoType.shortname;
else if (info.Weapon is BaseMelee) ammoType = "melee";
else if(info.Weapon is ThrownWeapon) ammoType = "throw";
else if(info.Weapon is FlameThrower) ammoType = "ammo.lowgrade";
if (!string.IsNullOrEmpty(ammoType)) {
float coef = 1f;
if (DefaultDamageWeapons.TryGetValue(item.info.shortname, out Dictionary<string, Rust.DamageTypeList> damageListByAmmo) && damageListByAmmo.TryGetValue(ammoType, out Rust.DamageTypeList damageList)) coef = info.damageTypes.Total() / damageList.Total();
UpdateHitDamage(info, initiator, coef);
}
else UpdateHitDamage(info, initiator);
if (info.HitEntity as DecayEntity) {
if (info.damageTypes.Has(Rust.DamageType.Cold)) info.damageTypes.Scale(Rust.DamageType.Cold, 0f);
if (info.damageTypes.Has(Rust.DamageType.Poison)) info.damageTypes.Scale(Rust.DamageType.Poison, 0f);
if (info.damageTypes.Has(Rust.DamageType.Bleeding)) info.damageTypes.Scale(Rust.DamageType.Bleeding, 0f);
if (info.damageTypes.Has(Rust.DamageType.Hunger)) info.damageTypes.Scale(Rust.DamageType.Hunger, 0f);
if (info.damageTypes.Has(Rust.DamageType.Thirst)) info.damageTypes.Scale(Rust.DamageType.Thirst, 0f);
if (info.damageTypes.Has(Rust.DamageType.Suicide)) info.damageTypes.Scale(Rust.DamageType.Suicide, 0f);
if (info.damageTypes.Has(Rust.DamageType.ElectricShock)) info.damageTypes.Scale(Rust.DamageType.ElectricShock, 0f);
if (info.damageTypes.Has(Rust.DamageType.Drowned)) info.damageTypes.Scale(Rust.DamageType.Drowned, 0f);
if (info.damageTypes.Has(Rust.DamageType.Fall)) info.damageTypes.Scale(Rust.DamageType.Fall, 0f);
if (info.damageTypes.Has(Rust.DamageType.Heat)) info.damageTypes.Scale(Rust.DamageType.Heat, 0f);
}
//Effects
BasePlayer victimPlayer = victim.ToPlayer();
if (victimPlayer && TryGetWeaponData(initiator as BasePlayer, item, out WeaponData weaponData)) {
var effects = weaponData.EffectsEntity;
if (!effects.RadPoison.Equals(0)) {
float rad = effects.RadPoison * victimPlayer.RadiationExposureFraction();
if (rad > 0) victimPlayer.metabolism.radiation_poison.value = Mathf.Clamp(victimPlayer.metabolism.radiation_poison.value + rad, victimPlayer.metabolism.radiation_poison.min, effects.ValuesSettings.MaxRadPoison);
}
if (!effects.Bleeding.Equals(0)) victimPlayer.metabolism.bleeding.value = Mathf.Clamp(victimPlayer.metabolism.bleeding.value + effects.Bleeding, victimPlayer.metabolism.bleeding.min, effects.ValuesSettings.MaxBleading);
if (!effects.Temperature.Equals(0)) {
float temperature = effects.Temperature;
if (temperature < 0) {
var ColdExposureFraction = (1f - Mathf.Clamp(victimPlayer.baseProtection.amounts[(int)Rust.DamageType.ColdExposure], 0f, 1f));
temperature *= ColdExposureFraction;
}
if (temperature != 0) victimPlayer.metabolism.temperature.value = Mathf.Clamp(victimPlayer.metabolism.temperature.value + temperature, effects.ValuesSettings.MinTemperature, effects.ValuesSettings.MaxTemperature);
}
if (!effects.Hunger.Equals(0)) victimPlayer.metabolism.calories.Subtract(effects.Hunger);
if (!effects.Thirst.Equals(0)) victimPlayer.metabolism.hydration.Subtract(effects.Thirst);
if (!effects.Wetness.Equals(0)) victimPlayer.metabolism.wetness.value = Mathf.Clamp(victimPlayer.metabolism.wetness.value + effects.Wetness, victimPlayer.metabolism.wetness.min, effects.ValuesSettings.MaxWetness);
}
}
private void OnLoseCondition(Item item, ref float amount) {
if (!IsWeapon(item)) return;
BasePlayer owner = item.GetOwnerPlayer();
if (owner == null) return;
WeaponData weaponData;
if (TryGetWeaponData(owner, item, out weaponData)) {
if (weaponData.Unbreakable) amount = 0f;
else amount = (amount / (weaponData.Durability / item.info.condition.max)) * (item.maxCondition / item.info.condition.max);
}
}
private void OnPlayerRespawned(BasePlayer player) => AddUiIcon(player);
private void OnPlayerConnected(BasePlayer player) => AddUiIcon(player);
private void OnPlayerLootEnd(PlayerLoot playerLoot) {
var player = (BasePlayer)playerLoot.baseEntity;
if (playerLoot.entitySource == RelationshipManager.ServerInstance) {
DestroyUI(player);
playerLoot.containers.Where(c => c.entityOwner == RelationshipManager.ServerInstance && c.capacity == 0).ToList().ForEach(c => c.Kill());
}
}
void OnLootEntity(BasePlayer player, BaseEntity entity) {
NextTick(() => {
foreach (var item in player.inventory.AllItems()) {
item.MarkDirty();
}
}
);
}
void OnLootEntityEnd(BasePlayer player, BaseCombatEntity entity) {
NextTick(() => {
foreach (var item in player.inventory.AllItems()) {
item.MarkDirty();
}
}
);
}
void OnAmmoSwitch(BaseProjectile baseProjectile, BasePlayer owner) {
UpdateItemName(baseProjectile.GetCachedItem());
}
void Loaded() {
Harmony.Init(this.Name);
Harmony.Patch();
}
void Unload() {
Harmony.UnpatchAll();
BasePlayer.allPlayerList.ToList().ForEach(player => {
DestroyUI(player);
DestroyIcon(player);
}
);
}
#endregion
public static class Harmony {
private static string Name;
#if CARBON
private static Harmony _harmony;
#else
//private static Harmony _harmony;
#endif
public static void Init(string name) {
Name = name;
#if CARBON
Instance = new HarmonyLib.Harmony(name);
#else
//Instance = HarmonyInstance.Create(name);
#endif
}
public static void Patch() {
//Instance.Patch(AccessTools.Method(typeof(Item), "Save"), postfix: new HarmonyMethod(typeof(Patches), "Item_Save"));
}
public static void UnpatchAll() {
//Instance.UnpatchAll(Name);
}
}
static partial class Patches {
internal static void Item_Save(Item __instance, ref ProtoBuf.Item __result) {
if (!SaveRestore.IsSaving && Plugin.IsWeapon(__instance) && __result.streamerName != null && __result.streamerName.StartsWith("\n")) {
ItemContainer container = __instance.parent;
if (container != null) {
BasePlayer player = container.playerOwner;
if (player != null && !player.IsNpc && !player.inventory.loot.IsLooting()) __result.name = __result.streamerName;
}
}
}
}
#region Commands
[ConsoleCommand("cw.reload")]
private void ConsoleCommandReload(ConsoleSystem.Arg arg) {
if (arg.Player() != null) {
if (!arg.Player().IsAdmin) {
SendReply(arg, "This command is only allowed to administrators");
return;
}
}
Server.Command($"o.reload {Name}");
if (arg.Player() != null) {
SendReply(arg, "Items successfully reloaded!");
return;
}
Puts("Items successfully reloaded");
}
[ConsoleCommand("cw.create")]
private void ConsoleCommandCreate(ConsoleSystem.Arg arg) {
if (arg.Player() != null) {
if (!arg.Player().IsAdmin) {
SendReply(arg, "This command is only allowed to administrators");
return;
}
}
if (arg.Args.IsNullOrEmpty() || arg.Args?.Count() != 2) {
if (arg.Player() != null) {
SendReply(arg, "Usage: cw.create <new unique shortname> <shortname>");
return;
}
PrintWarning("Usage: cw.create <new unique shortname> <shortname>");
return;
}
var name = arg.Args[0];
if (name.Contains(" ")) {
if(arg.Player() != null) {
SendReply(arg, "No spaces are allowed in the unique shortname!");
return;
}
PrintError("No spaces are allowed in the unique shortname!");
return;
}
var shortname = arg.Args[1];
if (config.DataItems.CustomFs.ExistsDatafile(name)) {
if (arg.Player() != null) {
SendReply(arg, "A file with this name already exists, delete it or create it under another name.");
return;
}
PrintWarning("A file with this name already exists, delete it or create it under another name.");
return;
}
if (!config.DataItems.Default.ContainsKey(shortname)) {
if (arg.Player() != null) {
SendReply(arg, $"The shortname '{shortname}' is not suitable, try another one, you can find available shortnames in the 'Default' folder");
return;
}
PrintWarning($"The shortname '{shortname}' is not suitable, try another one, you can find available shortnames in the 'Default' folder");
return;
}
var defaultItem = config.DataItems.Default[shortname];
CustomItem newItem = new CustomItem() {
Shortname = shortname, SkinId = 0, Name = name, Description = "", Unbreakable = defaultItem.Unbreakable, Durability = defaultItem.Durability, MagazineCapacity = defaultItem.MagazineCapacity, DamageTypes = defaultItem.DamageTypes, DamageTypeList = defaultItem.DamageTypeList
}
;
config.DataItems.CustomFs.WriteObject<CustomItem>(name, newItem);
config.DataItems.Custom[name] = newItem;
if (arg.Player() != null) {
SendReply(arg, $"Custom item with name '{name}' added!");
return;
}
Puts($"Custom item with name '{name}' added!");
}
[ConsoleCommand("cw.give")]
private void ConsoleCommandGive(ConsoleSystem.Arg arg) {
string nickname = "SERVER";
BasePlayer player = arg.Player();
if (player != null) {
if (!player.IsAdmin && !permission.UserHasPermission(player.UserIDString, giveCommandPerm)) {
arg.ReplyWith("You don't have permission to use this command.");
return;
}
nickname = player.displayName;
}
if (arg.Args.IsNullOrEmpty() || arg.Args?.Count() > 2 || arg.Args?.Count() < 1) {
if (player != null) {
arg.ReplyWith("Usage: cw.give <steamid/nickname> <custom item name>");
return;
}
PrintWarning("Usage: cw.give <steamid/nickname> <custom item name>");
return;
}
BasePlayer playerToGive = arg.Player();
if (arg.Args?.Count() == 2) {
playerToGive = BasePlayer.Find(arg.Args[0]);
if (playerToGive == null) {
if (player != null) {
arg.ReplyWith($"Player '{arg.Args[0]}' is offline or not exists.");
return;
}
PrintError($"Player '{arg.Args[0]}' is offline or not exists.");
return;
}
}
string uniqueShortname = arg.Args?.Last();
CustomItem customItem;
if (TryGetCustomItemByKey(uniqueShortname, out customItem)) {
Item itemToGive = ItemManager.CreateByName(uniqueShortname, 1, customItem.SkinId);
var nameLangKey = $"{uniqueShortname}:Name";
var itemName = GetMessage(nameLangKey, playerToGive.UserIDString);
if (itemName == nameLangKey) itemName = customItem.Name;
if (itemToGive.contents != null) {
foreach (var shortname in config.GlobalSettings.GiveOptions.Attachments.Where(pair => pair.Value).Select(x => x.Key)) {
Item item = ItemManager.CreateByName(shortname, 1, 0UL);
if (!item.MoveToContainer(itemToGive.contents, -1, true, false, null, true)) item.Remove(0f);
}
}
var heldEntity = itemToGive.GetHeldEntity();
if (heldEntity is BaseProjectile) {
BaseProjectile weapon = (heldEntity as BaseProjectile);
weapon.primaryMagazine.capacity = customItem.MagazineCapacity;
weapon.primaryMagazine.definition.builtInSize = customItem.MagazineCapacity;
weapon.primaryMagazine.contents = customItem.MagazineCapacity;
}
if (heldEntity is ThrownWeapon && itemToGive.MaxStackable() > 1) itemToGive.amount = 100;
if (!playerToGive.inventory.GiveItem(itemToGive)) {
itemToGive.Remove(0f);
arg.ReplyWith("Couldn't give item (inventory full?)");
PrintWarning($"{nickname}[{(player == null ? "0" : player.UserIDString)}] failed to give a custom item [{uniqueShortname}] to player {playerToGive.displayName}[{(player == null ? "0" : playerToGive.UserIDString)}]!");
return;
}
SetName(itemToGive, customItem, itemName);
itemToGive.skin = customItem.SkinId;
itemToGive.MarkDirty();
heldEntity.skinID = customItem.SkinId;
heldEntity.SendNetworkUpdate();
if (arg.Player() != null) arg.ReplyWith($"Item [{uniqueShortname}] added to {playerToGive.displayName}'s inventory!");
PrintWarning($"{nickname}[{(player == null ? "0" : player.UserIDString)}] gave {playerToGive.displayName}[{(playerToGive == null ? "0" : playerToGive.UserIDString)}] custom item [{uniqueShortname}]!");
}
else {
if (arg.Player() != null) {
arg.ReplyWith($"Item with name \"{uniqueShortname}\" was not found!");
return;
}
PrintError($"Item with name \"{uniqueShortname}\" was not found!");
}
}
#endregion
#region Classes
public class CustomItem : WeaponData {
public class UISettings {
[JsonProperty(PropertyName = "Name Color (or use <color></color> in name)")]
public string NameColor {
get;
set;
}
= "1 1 1 1";
[JsonProperty(PropertyName = "Frame Color")]
public string FrameColor {
get;
set;
}
= "0.94 0.75 0.15 1";
}
[JsonProperty(PropertyName = "Name")]
public string Name {
get;
set;
}
= "";
[JsonProperty(PropertyName = "Description")]
public string Description {
get;
set;
}
= "";
[JsonProperty(PropertyName = "SkinId")]
public ulong SkinId {
get;
set;
}
= 0;
//[JsonProperty(PropertyName = "Permission for use")]
//public string Permission { get; set; } = string.Empty;
[JsonProperty(PropertyName = "UI Settings")]
public UISettings UiSettings {
get;
set;
}
= new UISettings();
}
public class WeaponData {
public class EffectsEntitySettings {
public class __ValuesSettings {
[JsonProperty(PropertyName = "Max Radiation Poison")]
public float MaxRadPoison {
get;
set;
}
= 500;
[JsonProperty(PropertyName = "Max Bleading")]
public float MaxBleading {
get;
set;
}
= 100;
[JsonProperty(PropertyName = "Min Temperature")]
public float MinTemperature {
get;
set;
}
= -100;
[JsonProperty(PropertyName = "Max Temperature")]
public float MaxTemperature {
get;
set;
}
= 100;
[JsonProperty(PropertyName = "Max Wetness")]
public float MaxWetness {
get;
set;
}
= 100;
}
[JsonProperty(PropertyName = "Maximum and minimum values in the accumulation")]
public __ValuesSettings ValuesSettings {
get;
set;
}
= new __ValuesSettings();
[JsonProperty(PropertyName = "Radiation Poison")]
public float RadPoison {
get;
set;
}
[JsonProperty(PropertyName = "Bleading")]
public float Bleeding {
get;
set;
}
[JsonProperty(PropertyName = "Temperature")]
public float Temperature {
get;
set;
}
[JsonProperty(PropertyName = "Hunger")]
public float Hunger {
get;
set;
}
[JsonProperty(PropertyName = "Thirst")]
public float Thirst {
get;
set;
}
[JsonProperty(PropertyName = "Wetness")]
public float Wetness {
get;
set;
}
[JsonProperty(PropertyName = "Number of electric balls (recommended to 10)")]
public int ElecticBalls {
get;
set;
}
}
public class EffectsGroundSettings {
[JsonProperty(PropertyName = "Electric Ball")]
public bool ElecticBall {
get;
set;
}
}
[JsonProperty(PropertyName = "Shortname")]
public string Shortname {
get;
set;
}
[JsonProperty(PropertyName = "Unbreakable", NullValueHandling = NullValueHandling.Ignore)]
public bool Unbreakable {
get;
set;
}
[JsonProperty(PropertyName = "Durability", DefaultValueHandling = DefaultValueHandling.Ignore)]
public float Durability {
get;
set;
}
[JsonProperty(PropertyName = "Fast Reload")]
public bool FastReload {
get;
set;
}
= false;
[JsonProperty(PropertyName = "Magazine Capacity", DefaultValueHandling = DefaultValueHandling.Ignore)]
public int MagazineCapacity {
get;
set;
}
[JsonProperty(PropertyName = "Effects when hit")]
public EffectsEntitySettings EffectsEntity {
get;
set;
}
= new EffectsEntitySettings();
[JsonProperty(PropertyName = "Effects when hit the ground")]
public EffectsGroundSettings EffectsGround {
get;
set;
}
= new EffectsGroundSettings();
[JsonProperty(PropertyName = "Base damage by type & ammo", NullValueHandling = NullValueHandling.Ignore)]
public Dictionary<string, Dictionary<string, float>> DamageTypes {
get;
set;
}
[JsonIgnore]
public Dictionary<string, Rust.DamageTypeList> DamageTypeList {
get;
set;
}
= new Dictionary<string, Rust.DamageTypeList>();
}
#endregion
#region Fields
private static List<Rust.DamageType> DamageTypesExсeptions = new List<Rust.DamageType>() {
Rust.DamageType.Generic, Rust.DamageType.LAST, Rust.DamageType.Decay, Rust.DamageType.RadiationExposure, Rust.DamageType.ColdExposure, Rust.DamageType.Fun_Water, Rust.DamageType.Suicide, Rust.DamageType.Fall,
}
;
private static List<Rust.DamageType> DamageTypes = Enum.GetValues(typeof(Rust.DamageType)).Cast<Rust.DamageType>().Where(type => !DamageTypesExсeptions.Contains(type)).ToList();
private static Dictionary<Rust.DamageType, string> DamageTypeNames = DamageTypes.ToDictionary(type => type, type => Enum.GetName(typeof(Rust.DamageType), type));
private static Dictionary<string, Dictionary<string, Rust.DamageTypeList>> DefaultDamageWeapons = new Dictionary<string, Dictionary<string, Rust.DamageTypeList>>();
#endregion
#region Methods
private void SetName(Item item, WeaponData weaponData, string itemName = null) {
if (item == null || weaponData == null) return;
item.name = itemName;
item.streamerName = null;
if (!config.ItemSelectInfo) return;
BasePlayer owner = item.GetOwnerPlayer();
Dictionary<string, string> translation = null;
if (RustTranslationAPI != null && (itemName == null || itemName == string.Empty)) translation = RustTranslationAPI.Call<Dictionary<string, string>>("GetTranslations", lang.GetLanguage(owner?.UserIDString));
if (itemName == null || itemName == string.Empty) {
if (translation == null || !translation.TryGetValue($"{item.info.shortname}", out itemName)) itemName = item.info.displayName.translated;
}
Rust.DamageTypeList damageTypeListToRender = null;
BaseEntity heldEntity = item.GetHeldEntity();
if (heldEntity != null) {
BaseProjectile baseProjectile = heldEntity as BaseProjectile;
if (baseProjectile != null && baseProjectile.primaryMagazine != null) {
ItemDefinition ammoDef = baseProjectile.primaryMagazine.ammoType;
if (ammoDef != null) {
weaponData.DamageTypeList.TryGetValue(ammoDef.shortname, out damageTypeListToRender);
}
}
}
if (damageTypeListToRender == null && weaponData.DamageTypeList.Count > 0) damageTypeListToRender = weaponData.DamageTypeList.First().Value;
if (damageTypeListToRender == null) return;
Dictionary<string, float> FieldsForRender = DamageTypes.ToDictionary(x => GetMessage(DamageTypeNames[x], owner?.UserIDString), x => damageTypeListToRender.Get(x));
FieldsForRender = FieldsForRender.Where(i => i.Value != 0f).ToDictionary(i => i.Key, i => i.Value);
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(string.Concat(Enumerable.Repeat("\n", FieldsForRender.Count * 2 + 8)));
stringBuilder.Append($"\n{itemName}");
stringBuilder.Append("\n\t\t\t\t\t\t\t\t\t\t\t\t" + GetMessage(LangKeys.ItemInfoPanelHeader, owner?.UserIDString));
foreach (var pair in FieldsForRender) {
string keyWithoutRichtext = Regex.Replace(pair.Key, "<.*?>", String.Empty);
stringBuilder.Append("\n\t\t\t\t\t\t\t\t\t\t\t\t ");
stringBuilder.Append(" " + keyWithoutRichtext);
stringBuilder.Append("\n\t\t\t\t\t\t\t\t\t\t\t\t\t ");
stringBuilder.Append(pair.Value);
}
stringBuilder.Append("\n\n\t\t\t\t\t\t\t\t\t\t\t\t" + GetMessage(LangKeys.CharacteristicsPanelHeader, owner?.UserIDString));
stringBuilder.Append("\n\t\t\t\t\t\t\t\t\t\t\t\t " + GetMessage(LangKeys.MagazineCapacity, owner?.UserIDString));
stringBuilder.Append("\n\t\t\t\t\t\t\t\t\t\t\t\t\t " + weaponData.MagazineCapacity);
stringBuilder.Append("\n\t\t\t\t\t\t\t\t\t\t\t\t " + GetMessage(LangKeys.MaxDurability, owner?.UserIDString));
stringBuilder.Append("\n\t\t\t\t\t\t\t\t\t\t\t\t\t " + weaponData.Durability);
stringBuilder.Append("\n\t\t\t\t\t\t\t\t\t\t\t\t " + GetMessage(LangKeys.Unbreakable, owner?.UserIDString));
stringBuilder.Append("\n\t\t\t\t\t\t\t\t\t\t\t\t\t " + (weaponData.Unbreakable ? GetMessage(LangKeys.Yes, owner?.UserIDString) : GetMessage(LangKeys.No, owner?.UserIDString)));
item.streamerName = stringBuilder.ToString();
item.MarkDirty();
}
private bool TryGetCustomItem(Item item, out CustomItem customItem) => TryGetCustomItem(item.info, out customItem);
private bool TryGetCustomItem(ItemDefinition info, out CustomItem customItem) {
if (!info.HasFlag(CUSTOMWEAPON_FLAG) || !TryGetCustomItemByKey(info.shortname, out customItem)) {
customItem = null;
return false;
}
return true;
}
private bool HasCustomItemWithKey(string key) {
return config.DataItems.Custom.ContainsKey(key);
}
private bool TryGetCustomItemByKey(string key, out CustomItem customItem) {
if (key == null || config?.DataItems?.Custom == null) {
customItem = null;
return false;
}
return config.DataItems.Custom.TryGetValue(key, out customItem);
}
private bool TryGetWeaponData(BasePlayer player, Item item, out WeaponData weaponData) => TryGetWeaponData(player, item.info, out weaponData);
private bool TryGetWeaponData(BasePlayer player, ItemDefinition info, out WeaponData weaponData) {
CustomItem customItem;
if (TryGetCustomItem(info, out customItem)) {
weaponData = customItem;
return true;
}
else return TryGetDefaultWeaponData(player, info, out weaponData);
}
private bool TryGetDefaultWeaponData(BasePlayer player, Item item, out WeaponData weaponData) => TryGetDefaultWeaponData(player, item.info, out weaponData);
private bool TryGetDefaultWeaponData(BasePlayer player, ItemDefinition info, out WeaponData weaponData) {
try {
if (!config.DataItems.Default.TryGetValue(info.shortname, out weaponData)) return false;
if (player != null) {
foreach (var perm in config.DataItems.Permissions) {
WeaponData tempWd = null;
if (perm.Value.TryGetValue(info.shortname, out tempWd) && permission.UserHasPermission(player.UserIDString, $"customizableweapons.{perm.Key}")) {
weaponData = tempWd;
break;
}
}
}
return weaponData != null;
}
catch {
weaponData = default(WeaponData);
return false;
}
}
private bool IsWeapon(Item item) {
var heldEntity = item.GetHeldEntity();
return heldEntity is BaseProjectile || heldEntity is BaseMelee || heldEntity is ThrownWeapon || heldEntity is FlameThrower;
}
private void UpdateHitDamage(HitInfo info, BaseEntity entity, float scale = 1f) {
// Yeni eklenen kontrol
if (config.GlobalSettings.DisableWeaponDamage) {
return;
// Eğer yapılandırmada silah hasarı devre dışı bırakıldıysa, bu işlemi atla
}
if (info.Weapon is BaseProjectile) {
var shootableWeapon = info.Weapon as BaseProjectile;
var item = shootableWeapon.GetCachedItem();
if (item == null) return;
var ammotypeShortname = shootableWeapon.primaryMagazine.ammoType.shortname;
if (ammotypeShortname == null) return;
WeaponData weaponData = null;
if (TryGetWeaponData(entity.ToPlayer(), item, out weaponData)) {
Rust.DamageTypeList damageTypeList = null;
if (!weaponData.DamageTypeList.TryGetValue(ammotypeShortname, out damageTypeList)) {
PrintWarning($"There is no damage list in the item configuration (Shortname: {weaponData.Shortname})");
return;
}
for (int i = 0; i < damageTypeList.types.Length; i++) {
info.damageTypes.types[i] = damageTypeList.types[i] * scale;
}
}
}
// Melee ve diğer silah tipleri için devam eder...if (info.Weapon is BaseProjectile)
{
var shootableWeapon = info.Weapon as BaseProjectile;
var item = shootableWeapon.GetCachedItem();
if (item == null) return;
var ammotypeShortname = shootableWeapon.primaryMagazine.ammoType.shortname;
if (ammotypeShortname == null) return;
WeaponData weaponData = null;
if (TryGetWeaponData(entity.ToPlayer(), item, out weaponData)) {
Rust.DamageTypeList damageTypeList = null;
if (!weaponData.DamageTypeList.TryGetValue(ammotypeShortname, out damageTypeList)) {
PrintWarning($"There is no damage list in the item configuration (Shortname: {weaponData.Shortname})");
return;
}
for (int i = 0; i < damageTypeList.types.Length; i++) {
info.damageTypes.types[i] = damageTypeList.types[i] * scale;
}
}
}
else if (info.Weapon is BaseMelee) {
var meleeWeapon = info.Weapon as BaseMelee;
var item = meleeWeapon.GetCachedItem();
if (item == null) return;
string attackType = (info.IsProjectile() ? "throw" : "melee");
WeaponData weaponData = null;
if (TryGetWeaponData(entity.ToPlayer(), item, out weaponData)) {
Rust.DamageTypeList damageTypeList = null;
if (!weaponData.DamageTypeList.TryGetValue(attackType, out damageTypeList)) {
PrintWarning($"There is no damage list in the item configuration (Shortname: {weaponData.Shortname})");
return;
}
for (int i = 0; i < damageTypeList.types.Length; i++) info.damageTypes.types[i] = damageTypeList.types[i] * scale;
}
}
else if (info.Weapon is FlameThrower) {
var flameThrower = info.Weapon as FlameThrower;
var item = flameThrower.GetCachedItem();
if (item == null) return;
WeaponData weaponData = null;
if (TryGetWeaponData(entity.ToPlayer(), item, out weaponData)) {
Rust.DamageTypeList damageTypeList = null;
if (!weaponData.DamageTypeList.TryGetValue("ammo.lowgrade", out damageTypeList)) {
PrintWarning($"There is no damage list in the item configuration (Shortname: {weaponData.Shortname})");
return;
}
for (int i = 0; i < damageTypeList.types.Length; i++) info.damageTypes.types[i] = damageTypeList.types[i] * scale;
}
}
}
private void UpdateHitDamage(List<Rust.DamageTypeEntry> damageTypes, Item item, BaseEntity entity, float scale = 1f) {
if (item == null || damageTypes == null) return;
var type = string.Empty;
var heldEntity = item.GetHeldEntity();
if (heldEntity is BaseProjectile) type = (heldEntity as BaseProjectile).primaryMagazine.ammoType.shortname;
if (heldEntity is ThrownWeapon) type = "throw";
if (heldEntity is FlameThrower) type = "ammo.lowgrade";
WeaponData weaponData;
if (TryGetWeaponData(entity.ToPlayer(), item, out weaponData)) {
if (weaponData.DamageTypeList == null) return;
Rust.DamageTypeList damageTypeList = null;
if (!weaponData.DamageTypeList.TryGetValue(type, out damageTypeList)) {
PrintWarning($"There is no damage list in the item configuration (Shortname: {weaponData.Shortname})");
return;
}
if (damageTypeList.types.Length > 0) {
damageTypes.Clear();
for (int i = 0; i < damageTypeList.types.Length; i++) {
damageTypes.Add(new Rust.DamageTypeEntry() {
type = (Rust.DamageType)i, amount = damageTypeList.types[i] * scale
}
);
}
}
}
}
void SetupMagizineCapacity(BaseProjectile weapon) {
if (weapon == null) return;
// Yeni eklenen kontrol
if (config.GlobalSettings.DisableMagazineCapacity) {
re
// ... [Code preview truncated due to length. Full source in attached file] ...