Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System.Collections.Generic;
- using System.Text;
- using Oxide.Core.Configuration;
- using Oxide.Core;
- using System;
- using System.Linq;
- using Oxide.Core.Libraries.Covalence;
- using System.Text.RegularExpressions;
- namespace Oxide.Plugins
- {
- //Body part scaling from k1lly0u's plugin, with permission (thanks, k1lly0u)
- //Further code cleanup/improvement with help of k1lly0u
- [Info("Weapon Damage Scaler", "Shady", "1.1.8", ResourceId = 1594)]
- [Description("Scale damage per weapon, ammo types, skins, prefabs, and per body part.")]
- internal class WeaponDamageScaler : RustPlugin
- {
- private readonly Dictionary<ulong, string> skinIDName = new Dictionary<ulong, string>();
- private WeaponData weaponData;
- private DynamicConfigFile wData;
- private float GlobalDamageScale;
- private readonly Array buildingGrades = Enum.GetValues(typeof(BuildingGrade.Enum));
- private readonly HashSet<string> prefabNames = new HashSet<string>();
- private readonly List<string> _forbiddenTags = new List<string> { "</color>", "</size>", "<b>", "</b>", "<i>", "</i>" };
- private readonly Regex _colorRegex = new Regex("(<color=.+?>)");
- private readonly Regex _sizeRegex = new Regex("(<size=.+?>)");
- #region Data Management
- private class ItemStructure
- {
- public string Name;
- public float GlobalModifier = 1.0f;
- public Dictionary<string, float> IndividualParts = new Dictionary<string, float>();
- public Dictionary<string, float> PrefabModifiers = new Dictionary<string, float>();
- }
- private class WeaponData { public Dictionary<string, ItemStructure> Weapons = new Dictionary<string, ItemStructure>(); }
- private void InitializeWeaponData()
- {
- var skinNameDir = new List<string>();
- foreach (var kvp in Rust.Workshop.Approved.All)
- {
- var skin = kvp.Value;
- if (skin.Skinnable.Category == Rust.Workshop.Category.Weapon) skinNameDir.Add(skin.Name);
- }
- ItemStructure outStructure;
- for (int i = 0; i < ItemManager.itemList.Count; i++)
- {
- var definition = ItemManager.itemList[i];
- if (definition == null) continue;
- if ((definition.category == ItemCategory.Weapon || definition.category == ItemCategory.Tool || definition.category == ItemCategory.Ammunition) && !definition.shortname.Contains("mod") && !weaponData.Weapons.TryGetValue(definition.shortname, out outStructure)) weaponData.Weapons[definition.shortname] = new ItemStructure { Name = definition.displayName.english, GlobalModifier = 1.0f, PrefabModifiers = new Dictionary<string, float>(), IndividualParts = CreateBodypartList() };
- var skinDir = ItemSkinDirectory.ForItem(definition) ?? null;
- if (skinDir != null && skinDir.Length > 0 && (definition.category == ItemCategory.Weapon || definition.category == ItemCategory.Tool))
- {
- for (int j = 0; j < skinDir.Length; j++)
- {
- var skin = skinDir[j];
- var name = skin.invItem?.displayName?.english ?? skin.name;
- if (!skinNameDir.Contains(name)) skinNameDir.Add(name);
- }
- }
- }
- for (int i = 0; i < skinNameDir.Count; i++)
- {
- var skin = skinNameDir[i];
- if (!weaponData.Weapons.TryGetValue(skin, out outStructure)) weaponData.Weapons[skin] = new ItemStructure { Name = skin, GlobalModifier = 1.0f, PrefabModifiers = new Dictionary<string, float>(), IndividualParts = CreateBodypartList() };
- }
- SaveData();
- }
- private Dictionary<string, float> CreateBodypartList()
- {
- Dictionary<string, float> newData = new Dictionary<string, float>();
- for (int i = 0; i < Bodyparts.Length; i++) newData.Add(Bodyparts[i], 1.0f);
- return newData;
- }
- private void SaveData() => wData?.WriteObject(weaponData);
- private void LoadData()
- {
- try
- {
- wData = Interface.Oxide.DataFileSystem.GetFile("damagescaler_data");
- weaponData = Interface.GetMod().DataFileSystem.ReadObject<WeaponData>("damagescaler_data");
- InitializeWeaponData();
- }
- catch (Exception ex)
- {
- PrintError(ex.ToString());
- PrintWarning("Unable to load data, creating new datafile!");
- weaponData = new WeaponData();
- }
- }
- #endregion
- #region Config
- protected override void LoadDefaultConfig()
- {
- Config["GlobalDamageScaler"] = GlobalDamageScale = GetConfig("GlobalDamageScaler", 1.0f);
- SaveConfig();
- }
- private T GetConfig<T>(string name, T defaultValue)
- {
- if (Config[name] == null) return defaultValue;
- return (T)Convert.ChangeType(Config[name], typeof(T));
- }
- public string[] Bodyparts = new string[]
- {
- "r_forearm",
- "l_forearm",
- "l_upperarm",
- "r_upperarm",
- "r_hand",
- "l_hand",
- "pelvis",
- "l_hip",
- "r_hip",
- "spine3",
- "spine4",
- "spine1",
- "spine2",
- "r_knee",
- "r_foot",
- "r_toe",
- "l_knee",
- "l_foot",
- "l_toe",
- "head",
- "neck",
- "jaw",
- "r_eye",
- "l_eye"
- };
- #endregion
- #region Localization
- protected override void LoadDefaultMessages()
- {
- var messages = new Dictionary<string, string>
- {
- //DO NOT EDIT LANGUAGE FILES HERE!
- {"noPerms", "You do not have permission to use this command!"},
- {"invalidSyntax", "Invalid Syntax, usage example: setscale <weaponname> <x.x>"},
- {"itemSkinNotFound", "Item/Skin: \"" + "{item}" + "\" does not exist, syntax example: setscale <WeaponOrAmmoOrSkinName> <x.x>" },
- {"invalidSyntaxBodyPart", "<color=orange>/scalebp weapon <shortname> <bone> <amount></color> - Scale damage done for <shortname> to <bone>"},
- {"bodyPartExample", "<color=orange>-- ex. /scalebp weapon rifle.ak pelvis 1.25</color> - Damage done from a assault rifle to a pelvis is set to 125%"},
- {"scaleList", "<color=orange>/scalebp list</color> - Displays all bones"},
- {"shortnameNotFound", "Could not find a weapon with the shortname: <color=orange>{0}</color>"},
- {"bonePartNotFound", "Could not find a bone called: <color=orange>{0}</color>. Check /scalebp list"},
- {"bodyPartExample2", "<color=orange>/scalebp weapon <shortname> <bone> <amount></color>"},
- {"successfullyChangedValueBP","You have changed <color=orange>{0}'s</color> damage against <color=orange>{1}</color> to <color=orange>{2}</color>x damage" },
- {"alreadySameValue", "This is already the value for the selected item!"},
- {"scaledItem", "Scaled \"" + "{engName}" + "\" (" + "{shortName}" + ") " + "to: " + "{scaledValue}"},
- {"prefabNotExist", "Prefab/Building grade does not exist: {0}" },
- {"scaledPrefab", "Scaled Prefab/Building grade \"{0}\" by {1} for weapon {2}" },
- };
- lang.RegisterMessages(messages, this);
- }
- private string GetMessage(string key, string steamId = null) => lang.GetMessage(key, this, steamId);
- #endregion
- #region Oxide Hooks
- private void OnServerInitialized()
- {
- var strs = GameManifest.Current.pooledStrings;
- for (int i = 0; i < strs.Length; i++)
- {
- var str = strs[i].str ?? string.Empty;
- prefabNames.Add(str);
- }
- for (int i = 0; i < ItemManager.itemList.Count; i++)
- {
- var item = ItemManager.itemList[i];
- var skinDir = ItemSkinDirectory.ForItem(item);
- if (skinDir == null || skinDir.Length < 1) continue;
- for (int j = 0; j < skinDir.Length; j++)
- {
- var skin = skinDir[j];
- ulong skinID;
- if (ulong.TryParse(skin.id.ToString(), out skinID)) skinIDName[skinID] = (skin.invItem?.displayName?.english ?? skin.name);
- }
- }
- foreach (var kvp in Rust.Workshop.Approved.All)
- {
- var val = kvp.Value;
- skinIDName[val.WorkshopdId] = val.Name;
- }
- LoadData();
- }
- private void Init()
- {
- RegisterPerm("weapondamagescaler.setscale");
- RegisterPerm("weapondamagescaler.setscalebp");
- RegisterPerm("weapondamagescaler.allowed");
- AddCovalenceCommand("setscale", nameof(CmdSetScale));
- AddCovalenceCommand("scalebp", nameof(cmdScaleBP));
- LoadDefaultConfig();
- LoadDefaultMessages();
- }
- private void Unload() => SaveData();
- private void OnExplosiveThrown(BasePlayer player, BaseEntity entity)
- {
- if (player == null || entity == null) return;
- var sb = Facepunch.Pool.Get<StringBuilder>();
- try
- {
- ItemStructure itemStruct;
- var prefabName = sb.Clear().Append(entity.ShortPrefabName).Replace("_", ".").Replace(".deployed", string.Empty).ToString();
- if (weaponData.Weapons.TryGetValue(prefabName, out itemStruct))
- {
- var c4 = entity?.GetComponent<TimedExplosive>() ?? null;
- if (c4 != null) for (int i = 0; i < c4.damageTypes.Count; i++) c4.damageTypes[i].amount *= itemStruct?.GlobalModifier ?? 1f;
- }
- }
- finally { Facepunch.Pool.FreeUnmanaged(ref sb); }
- }
- private void OnRocketLaunched(BasePlayer player, BaseEntity entity)
- {
- var explosive = entity as TimedExplosive;
- if (explosive == null) return;
- var sb = Facepunch.Pool.Get<StringBuilder>();
- try
- {
- var ammoName = sb.Clear().Append("ammo.").Append(entity.ShortPrefabName).Replace("_", ".").ToString();
- ItemStructure itemStruct;
- if (weaponData.Weapons.TryGetValue(ammoName, out itemStruct)) for (int i = 0; i < explosive.damageTypes.Count; i++) explosive.damageTypes[i].amount *= itemStruct?.GlobalModifier ?? 1f;
- }
- finally { Facepunch.Pool.FreeUnmanaged(ref sb); }
- }
- private void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo hitInfo)
- {
- if (entity == null || hitInfo == null) return;
- var type = hitInfo?.damageTypes?.GetMajorityDamageType() ?? Rust.DamageType.Generic;
- if (type == Rust.DamageType.Suicide) return;
- var attacker = hitInfo?.Initiator as BasePlayer;
- if (attacker != null && HasPermID(attacker.UserIDString, "weapondamagescaler.allowed"))
- {
- if (GlobalDamageScale != 1.0f) hitInfo?.damageTypes?.ScaleAll(GlobalDamageScale);
- else ScaleDealtDamage(hitInfo);
- }
- }
- #endregion
- #region Commands
- private void CmdSetScale(IPlayer player, string command, string[] args)
- {
- if (!HasPerm(player, "weapondamagescaler.setscale"))
- {
- SendReply(player, GetMessage("noPerms", player.Id));
- return;
- }
- if (args.Length <= 1)
- {
- SendReply(player, GetMessage("invalidSyntax", player.Id));
- return;
- }
- var itemName = args[0].ToLower();
- var englishName = GetEnglishName(itemName);
- var prefabName = (args.Length > 2) ? args[2].ToLower() : string.Empty;
- var shortName = string.Empty;
- foreach (var entry in weaponData.Weapons)
- {
- if (entry.Value.Name.Equals(itemName, StringComparison.OrdinalIgnoreCase))
- {
- shortName = entry.Key;
- break;
- }
- else if (entry.Key.Equals(itemName, StringComparison.OrdinalIgnoreCase))
- {
- shortName = entry.Key;
- break;
- }
- }
- if (string.IsNullOrEmpty(shortName)) shortName = skinIDName?.Where(p => p.Value.ToLower() == itemName)?.FirstOrDefault().Value ?? string.Empty;
- ItemStructure itemStruct;
- if (string.IsNullOrEmpty(shortName) || !weaponData.Weapons.TryGetValue(shortName, out itemStruct))
- {
- SendReply(player, GetMessage("itemSkinNotFound", player.Id).Replace("{item}", englishName));
- return;
- }
- var value = 0f;
- if (!float.TryParse(args[1], out value))
- {
- SendReply(player, GetMessage("invalidSyntax", player.Id));
- return;
- }
- if (!string.IsNullOrEmpty(shortName))
- {
- if (!string.IsNullOrEmpty(prefabName))
- {
- if (!PrefabExists(prefabName) && !GradeExists(prefabName))
- {
- SendReply(player, string.Format(GetMessage("prefabNotExist", player.Id), prefabName));
- return;
- }
- if (weaponData.Weapons[shortName].PrefabModifiers == null || weaponData.Weapons[shortName].PrefabModifiers.Count < 1) weaponData.Weapons[shortName].PrefabModifiers = new Dictionary<string, float>();
- weaponData.Weapons[shortName].PrefabModifiers[prefabName] = value;
- SendReply(player, string.Format(GetMessage("scaledPrefab", player.Id), prefabName, value, englishName));
- return;
- }
- if (weaponData.Weapons[shortName].GlobalModifier == value)
- {
- SendReply(player, GetMessage("alreadySameValue", player.Id));
- return;
- }
- weaponData.Weapons[shortName].GlobalModifier = value;
- var sb = new StringBuilder(GetMessage("scaledItem", player.Id));
- var finalstring =
- sb
- .Replace("{engName}", englishName)
- .Replace("{shortName}", shortName)
- .Replace("{scaledValue}", value.ToString())
- .ToString();
- SendReply(player, finalstring);
- }
- else SendReply(player, GetMessage("invalidSyntax", player.Id));
- }
- private void cmdScaleBP(IPlayer player, string command, string[] args)
- {
- if (!HasPerm(player, "weapondamagescaler.setscalebp"))
- {
- SendReply(player, GetMessage("noPerms", player.Id));
- return;
- }
- if (args.Length < 1)
- {
- SendReply(player, GetMessage("invalidSyntaxBodyPart", player.Id));
- SendReply(player, GetMessage("bodyPartExample", player.Id));
- SendReply(player, GetMessage("scaleList", player.Id)); //send in three messages to prevent it going invisible from character limit(?)
- return;
- }
- switch (args[0].ToLower())
- {
- case "weapon":
- if (args.Length >= 3)
- {
- var shortName = string.Empty;
- var engName = args[1].ToLower();
- foreach (var entry in weaponData.Weapons)
- {
- if (entry.Value.Name.ToLower() == engName)
- {
- shortName = entry.Key;
- break;
- }
- else if (entry.Key.ToLower() == engName)
- {
- shortName = entry.Key;
- break;
- }
- }
- if (!string.IsNullOrEmpty(shortName))
- {
- if (weaponData.Weapons.ContainsKey(shortName))
- {
- if (weaponData.Weapons[shortName].IndividualParts.ContainsKey(args[2].ToLower()))
- {
- float i = 0;
- if (args.Length == 4)
- if (!float.TryParse(args[3], out i)) i = 1.0f;
- weaponData.Weapons[shortName].IndividualParts[args[2].ToLower()] = i;
- SaveData();
- SendReply(player, string.Format(GetMessage("successfullyChangedValueBP", player.Id), args[1], args[2], i));
- return;
- }
- SendReply(player, string.Format(GetMessage("bonePartNotFound", player.Id), args[2]));
- return;
- }
- SendReply(player, string.Format(GetMessage("shortnameNotFound", player.Id), args[1]));
- return;
- }
- }
- SendReply(player, GetMessage("bodyPartExample2", player.Id));
- return;
- case "list":
- var bpPlayer = player?.Object as BasePlayer;
- if (bpPlayer == null) return;
- var BPsb = new StringBuilder();
- for (int i = 0; i < Bodyparts.Length; i++)
- {
- var bp = Bodyparts[i];
- var bpName = FirstUpper(bpPlayer?.skeletonProperties?.FindBone(StringPool.Get(bp))?.name?.english ?? bp);
- BPsb.AppendLine(bp + " (" + bpName + "), ");
- }
- SendReply(bpPlayer, BPsb.ToString().TrimEnd().TrimEnd(','));
- return;
- }
- }
- #endregion
- #region Util
- private string GetSkinName(ulong skinID)
- {
- string skinName;
- skinIDName.TryGetValue(skinID, out skinName);
- return skinName;
- }
- private ItemDefinition GetItemDefFromPrefabName(string shortprefabName)
- {
- if (string.IsNullOrEmpty(shortprefabName)) return null;
- var adjName = shortprefabName.Replace("_deployed", "").Replace(".deployed", "").Replace("_", "").Replace(".entity", "");
- var def = ItemManager.FindItemDefinition(adjName);
- if (def != null) return def;
- adjName = shortprefabName.Replace("_deployed", "").Replace(".deployed", "").Replace("_", ".").Replace(".entity", "");
- return ItemManager.FindItemDefinition(adjName);
- }
- //this code feels messy but it works I guess
- private void ScaleDealtDamage(HitInfo hitInfo)
- {
- if (hitInfo == null || hitInfo?.damageTypes == null) return;
- if (hitInfo?.Weapon == null && hitInfo?.WeaponPrefab == null) hitInfo.WeaponPrefab = hitInfo.Weapon = hitInfo?.InitiatorPlayer?.GetHeldEntity()?.GetComponent<AttackEntity>() ?? null;
- if (hitInfo?.Weapon == null && hitInfo?.WeaponPrefab == null) return;
- var bodypart = StringPool.Get((hitInfo?.HitBone ?? 0)) ?? string.Empty;
- var wepPrefab = hitInfo?.Weapon?.ShortPrefabName ?? hitInfo?.WeaponPrefab?.ShortPrefabName ?? string.Empty;
- var weaponName = hitInfo?.Weapon?.GetItem()?.info?.shortname ?? hitInfo?.WeaponPrefab?.GetItem()?.info?.shortname ?? string.Empty;
- if (string.IsNullOrEmpty(weaponName) && !string.IsNullOrEmpty(wepPrefab) && !wepPrefab.Contains("rocket") && !wepPrefab.Contains("explosive")) weaponName = GetItemDefFromPrefabName(wepPrefab)?.shortname ?? string.Empty;
- var ammoName = hitInfo?.Weapon?.GetItem()?.GetHeldEntity()?.GetComponent<BaseProjectile>()?.primaryMagazine?.ammoType?.shortname ?? string.Empty;
- if (string.IsNullOrEmpty(ammoName)) ammoName = (hitInfo?.Weapon ?? hitInfo?.WeaponPrefab ?? null)?.GetComponent<BaseProjectile>()?.primaryMagazine?.ammoType?.shortname ?? string.Empty;
- var skinName = GetSkinName(hitInfo?.Weapon?.GetItem()?.skin ?? 0);
- ItemStructure weaponInfo = null;
- ItemStructure ammoInfo = null;
- ItemStructure skinInfo = null;
- if (!string.IsNullOrEmpty(weaponName)) weaponData.Weapons.TryGetValue(weaponName, out weaponInfo);
- if (!string.IsNullOrEmpty(ammoName)) weaponData.Weapons.TryGetValue(ammoName, out ammoInfo);
- if (!string.IsNullOrEmpty(skinName)) weaponData.Weapons.TryGetValue(skinName, out skinInfo);
- var ammoMod = ammoInfo?.GlobalModifier ?? 1.0f;
- var skinMod = skinInfo?.GlobalModifier ?? 1.0f;
- var prefabName = hitInfo?.HitEntity?.ShortPrefabName ?? string.Empty;
- var gradeName = (hitInfo?.HitEntity?.GetComponent<BuildingBlock>()?.grade ?? BuildingGrade.Enum.None).ToString().ToLower();
- var prefabModWeapon = 1.0f;
- var prefabModAmmo = 1.0f;
- var prefabModSkin = 1.0f;
- var individualModWeapon = 1.0f;
- var individualModAmmo = 1.0f;
- var individualModSkin = 1.0f;
- if (weaponInfo != null)
- {
- if (!weaponInfo.PrefabModifiers.TryGetValue(prefabName, out prefabModWeapon) && !weaponInfo.PrefabModifiers.TryGetValue(gradeName, out prefabModWeapon)) prefabModWeapon = 1.0f;
- if (!weaponInfo.IndividualParts.TryGetValue(bodypart, out individualModWeapon)) individualModWeapon = 1.0f;
- }
- if (ammoInfo != null)
- {
- if (!ammoInfo.PrefabModifiers.TryGetValue(prefabName, out prefabModAmmo) && !ammoInfo.PrefabModifiers.TryGetValue(gradeName, out prefabModAmmo)) prefabModAmmo = 1.0f;
- if (!ammoInfo.IndividualParts.TryGetValue(bodypart, out individualModAmmo)) individualModAmmo = 1.0f;
- }
- if (skinInfo != null)
- {
- if (skinInfo != null && !skinInfo.PrefabModifiers.TryGetValue(prefabName, out prefabModSkin) && !skinInfo.PrefabModifiers.TryGetValue(gradeName, out prefabModSkin)) prefabModSkin = 1.0f;
- if (!skinInfo.IndividualParts.TryGetValue(bodypart, out individualModSkin)) individualModSkin = 1.0f;
- }
- var prefabMod = (prefabModWeapon + prefabModAmmo + prefabModSkin) - 2;
- var globalMod = weaponInfo?.GlobalModifier ?? 1.0f;
- var individualMod = (individualModWeapon + individualModSkin + individualModAmmo) - 2;
- var totalMod = (globalMod + individualMod + ammoMod + prefabMod + skinMod) - 4;
- if (totalMod != 1.0f) hitInfo?.damageTypes?.ScaleAll(totalMod);
- }
- //Borrowed RemoveTags from BetterChat//
- //Modified quite a bit
- private string RemoveTags(string phrase)
- {
- if (string.IsNullOrEmpty(phrase)) return phrase;
- // Replace Color Tags
- phrase = _colorRegex.Replace(phrase, string.Empty);
- // Replace Size Tags
- phrase = _sizeRegex.Replace(phrase, string.Empty);
- var phraseSB = Facepunch.Pool.Get<StringBuilder>();
- try
- {
- phraseSB.Clear().Append(phrase);
- for (int i = 0; i < _forbiddenTags.Count; i++) phraseSB.Replace(_forbiddenTags[i], string.Empty);
- return phraseSB.ToString();
- }
- finally { Facepunch.Pool.FreeUnmanaged(ref phraseSB); }
- }
- private void RegisterPerm(string perm) => permission.RegisterPermission(perm, this);
- private bool HasPermID(string userID, string perm) => permission.UserHasPermission(userID, perm);
- private bool HasPerm(IPlayer player, string perm) => player?.HasPermission(perm) ?? false;
- private void SendReply(IPlayer player, string message)
- {
- if (player == null || string.IsNullOrEmpty(message)) return;
- if (player.IsServer || player?.Object == null) message = RemoveTags(message); //remove tags for console (may no longer be needed? - needs to be checked)
- player.Message(message);
- }
- private bool PrefabExists(string prefabName)
- {
- if (string.IsNullOrEmpty(prefabName)) return false;
- return prefabNames.Any(p => p.EndsWith(prefabName, StringComparison.OrdinalIgnoreCase) || p.EndsWith(prefabName + ".prefab", StringComparison.OrdinalIgnoreCase));
- }
- private bool GradeExists(string gradeName)
- {
- if (string.IsNullOrEmpty(gradeName)) return false;
- foreach (var grade in buildingGrades) if (grade.ToString().Equals(gradeName, StringComparison.OrdinalIgnoreCase)) return true;
- return false;
- }
- private string GetEnglishName(string shortName) { return ItemManager.FindItemDefinition(shortName)?.displayName?.english ?? shortName; }
- private string FirstUpper(string original)
- {
- if (string.IsNullOrEmpty(original)) return string.Empty;
- var charArray = original.ToCharArray();
- charArray[0] = char.ToUpper(charArray[0]);
- return new string(charArray);
- }
- #endregion
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment