diff --git a/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.6.9/bepInEx/plugins/Faupi-MunitionsExpert.dll b/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.6.9/bepInEx/plugins/Faupi-MunitionsExpert.dll deleted file mode 100644 index 8ce0f37..0000000 Binary files a/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.6.9/bepInEx/plugins/Faupi-MunitionsExpert.dll and /dev/null differ diff --git a/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.6.9/user/mods/Faupi-MunitionsExpert 1.6.9/res/translations.json b/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.6.9/user/mods/Faupi-MunitionsExpert 1.6.9/res/translations.json deleted file mode 100644 index 530c6ff..0000000 --- a/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.6.9/user/mods/Faupi-MunitionsExpert 1.6.9/res/translations.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "en": { - "DAMAGE": "Damage", - "PENETRATION": "Armor penetration", - "ARMOR DAMAGE": "Damage to armor", - "FRAGMENTATION CHANCE": "Fragmentation chance", - "RICOCHET CHANCE": "Ricochet chance", - "ME_class": "Class", - "ME_noarmor": "Unarmored" - }, - "cz": { - "DAMAGE": "Poškození", - "PENETRATION": "Průbojnost", - "ARMOR DAMAGE": "Poškození brnění", - "FRAGMENTATION CHANCE": "Šance na fragmentaci", - "RICOCHET CHANCE": "Šance na odraz", - "ME_class": "Třída", - "ME_noarmor": "Neobrněný" - }, - "pl": { - "DAMAGE": "Szkoda", - "PENETRATION": "Penetracja pancerza", - "ARMOR DAMAGE": "Uszkodzenie zbroi", - "FRAGMENTATION CHANCE": "Szansa na fragmentację", - "RICOCHET CHANCE": "Szansa na rykoszet", - "ME_class": "Klasa", - "ME_noarmor": "Nieumiejętny" - }, - "po": { - "DAMAGE": "Dano", - "PENETRATION": "Penetração de armadura", - "ARMOR DAMAGE": "Danos à armadura", - "FRAGMENTATION CHANCE": "Chance de fragmentação", - "RICOCHET CHANCE": "Chance de ricochete", - "ME_class": "Classe", - "ME_noarmor": "Sem armadura" - }, - "ch": { - "DAMAGE": "损坏", - "PENETRATION": "护甲穿透", - "ARMOR DAMAGE": "对盔甲的伤害", - "FRAGMENTATION CHANCE": "碎片机会", - "RICOCHET CHANCE": "跳弹机会", - "ME_class": "类", - "ME_noarmor": "无所作为" - }, - "ru": { - "DAMAGE": "Повреждать", - "PENETRATION": "Бронепробиваемость", - "ARMOR DAMAGE": "Повреждение брони", - "FRAGMENTATION CHANCE": "Вероятность фрагментации", - "RICOCHET CHANCE": "Шанс рикошета", - "ME_class": "Класс", - "ME_noarmor": "Без оружия" - }, - "es": { - "DAMAGE": "Daño", - "PENETRATION": "Penetración de armadura", - "ARMOR DAMAGE": "Daño a la armadura", - "FRAGMENTATION CHANCE": "Posibilidad de fragmentación", - "RICOCHET CHANCE": "Oportunidad de rebote", - "ME_class": "Clase", - "ME_noarmor": "Sin armadura" - }, - "es-mx": { - "DAMAGE": "Daño", - "PENETRATION": "Penetración de armadura", - "ARMOR DAMAGE": "Daño a la armadura", - "FRAGMENTATION CHANCE": "Posibilidad de fragmentación", - "RICOCHET CHANCE": "Oportunidad de rebote", - "ME_class": "Clase", - "ME_noarmor": "Sin armadura" - }, - "ge": { - "DAMAGE": "Schaden", - "PENETRATION": "Rüstungsdurchdringung", - "ARMOR DAMAGE": "Beschädigung der Rüstung", - "FRAGMENTATION CHANCE": "Fragmentierung Chance", - "RICOCHET CHANCE": "Querschläger-Chance", - "ME_class": "Klasse", - "ME_noarmor": "Ungepanzert" - }, - "sk": { - "DAMAGE": "Poškodenie", - "PENETRATION": "Prienik do brnenia", - "ARMOR DAMAGE": "Poškodenie brnenia", - "FRAGMENTATION CHANCE": "Šanca na fragmentáciu", - "RICOCHET CHANCE": "Šanca na odraz", - "ME_class": "Trieda", - "ME_noarmor": "Neozbrojený" - }, - "tu": { - "DAMAGE": "Hasar", - "PENETRATION": "Zırh penetrasyon", - "ARMOR DAMAGE": "Zırhta hasar", - "FRAGMENTATION CHANCE": "Parçalanma şansı", - "RICOCHET CHANCE": "Sekme şansı", - "ME_class": "Sınıf", - "ME_noarmor": "zırhsız" - }, - "it": { - "DAMAGE": "Danno", - "PENETRATION": "Penetrazione dell'armatura", - "ARMOR DAMAGE": "Danni all'armatura", - "FRAGMENTATION CHANCE": "Possibilità di frammentazione", - "RICOCHET CHANCE": "Possibilità di rimbalzo", - "ME_class": "Classe", - "ME_noarmor": "Disarmato" - }, - "jp": { - "DAMAGE": "ダメージ", - "PENETRATION": "装甲貫通", - "ARMOR DAMAGE": "鎧の損傷", - "FRAGMENTATION CHANCE": "断片化の可能性", - "RICOCHET CHANCE": "跳ね返るチャンス", - "ME_class": "クラス", - "ME_noarmor": "無装甲" - }, - "fr": { - "DAMAGE": "Dommage", - "PENETRATION": "Pénétration d'armure", - "ARMOR DAMAGE": "Dommages à l'armure", - "FRAGMENTATION CHANCE": "Chance de fragmentation", - "RICOCHET CHANCE": "Chance de ricochet", - "ME_class": "Classe", - "ME_noarmor": "Sans armure" - }, - "hu": { - "DAMAGE": "Kár", - "PENETRATION": "Páncélátütő", - "ARMOR DAMAGE": "A páncél sérülése", - "FRAGMENTATION CHANCE": "Töredezettség esélye", - "RICOCHET CHANCE": "Ricochet esély", - "ME_class": "Osztály", - "ME_noarmor": "Fegyvertelen" - } -} \ No newline at end of file diff --git a/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.6.9/user/mods/Faupi-MunitionsExpert 1.6.9/src/MunitionsExpert.ts b/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.6.9/user/mods/Faupi-MunitionsExpert 1.6.9/src/MunitionsExpert.ts deleted file mode 100644 index 4cc6d44..0000000 --- a/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.6.9/user/mods/Faupi-MunitionsExpert 1.6.9/src/MunitionsExpert.ts +++ /dev/null @@ -1,108 +0,0 @@ -import type { DependencyContainer } from "tsyringe"; -import { IPreAkiLoadMod } from "@spt-aki/models/external/IPreAkiLoadMod"; -import { IPostAkiLoadMod } from "@spt-aki/models/external/IPostAkiLoadMod"; -import { DynamicRouterModService } from "@spt-aki/services/mod/dynamicRouter/DynamicRouterModService" -import { DatabaseServer } from "@spt-aki/servers/DatabaseServer" -import { JsonUtil } from "@spt-aki/utils/JsonUtil" -import { IDatabaseTables } from "@spt-aki/models/spt/server/IDatabaseTables"; -import { PreAkiModLoader } from "@spt-aki/loaders/PreAkiModLoader"; - -class MunitionsExpert implements IPreAkiLoadMod, IPostAkiLoadMod -{ - private database: DatabaseServer; - private router: DynamicRouterModService; - private json: JsonUtil; - private modLoader: PreAkiModLoader; - private table: IDatabaseTables; - private globalLocale: { [x: string]: { interface: { [x: string]: any; }; }; }; - private translations: { [x: string]: any; }; - private items: { [x: string]: any; }; - private path: { resolve: (arg0: string) => any; }; - private cfg: { BulletBackgroundColours: boolean; }; - - public preAkiLoad(container: DependencyContainer) - { - this.router = container.resolve("DynamicRouterModService"); - this.json = container.resolve("JsonUtil"); - this.translations = require("../res/translations.json"); - this.path = require("path"); - this.cfg = require("./config.json"); - this.hookRoutes(); - } - - public postAkiLoad(container: DependencyContainer) - { - this.modLoader = container.resolve("PreAkiModLoader"); - this.database = container.resolve("DatabaseServer"); - this.table = this.database.getTables(); - this.globalLocale = this.table.locales.global; - this.items = this.table.templates.items; - this.updateLocalization(); - this.changeBulletColour(); - } - - private updateLocalization() - { - for (const language in this.translations) - { - if (!(language in this.globalLocale)) - { - continue; - } - - const attrKvPair = this.translations[language]; - for (const attrKey in attrKvPair) - { - const attrValue = attrKvPair[attrKey]; - - this.globalLocale[language][attrKey] = attrValue; - } - } - } - - private hookRoutes() - { - this.router.registerDynamicRouter( - "MunitionsExpert", - [ - { - url: "/MunitionsExpert/GetInfo", - action: (url, info, sessionId, output) => - { - return this.json.serialize(this.path.resolve(this.modLoader.getModPath("Faupi-MunitionsExpert 1.6.9"))); - } - } - ], - "MunitionsExpert" - ) - } - - changeBulletColour() - { - if (this.cfg.BulletBackgroundColours === true) - { - for (const i in this.items) - { - const item = this.items[i] - - //set baground colour of ammo depending on pen - if (item._parent === "5485a8684bdc2da71d8b4567") - { - const pen = item._props.PenetrationPower - let colour = "" - - pen > 60 ? colour = "red" : //SuperHighPen - pen > 50 ? colour = "yellow" : //HighPen - pen > 40 ? colour = "violet" : //MedHighPen - pen > 30 ? colour = "blue" : //MedPen - pen > 20 ? colour = "green" : //LowMedPen - colour = "grey" //LowPen - item._props.BackgroundColor = colour - } - } - } - } -} - -module.exports = { mod: new MunitionsExpert() }; - diff --git a/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.7.0/bepInEx/plugins/Faupi-MunitionsExpert/Faupi-MunitionsExpert.dll b/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.7.0/bepInEx/plugins/Faupi-MunitionsExpert/Faupi-MunitionsExpert.dll new file mode 100644 index 0000000..cd6718a Binary files /dev/null and b/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.7.0/bepInEx/plugins/Faupi-MunitionsExpert/Faupi-MunitionsExpert.dll differ diff --git a/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.6.9/user/mods/Faupi-MunitionsExpert 1.6.9/res/armorDamage.png b/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.7.0/bepInEx/plugins/Faupi-MunitionsExpert/armorDamage.png similarity index 100% rename from Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.6.9/user/mods/Faupi-MunitionsExpert 1.6.9/res/armorDamage.png rename to Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.7.0/bepInEx/plugins/Faupi-MunitionsExpert/armorDamage.png diff --git a/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.6.9/user/mods/Faupi-MunitionsExpert 1.6.9/res/ricochet.png b/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.7.0/bepInEx/plugins/Faupi-MunitionsExpert/ricochet.png similarity index 100% rename from Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.6.9/user/mods/Faupi-MunitionsExpert 1.6.9/res/ricochet.png rename to Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.7.0/bepInEx/plugins/Faupi-MunitionsExpert/ricochet.png diff --git a/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.6.9/user/mods/Faupi-MunitionsExpert 1.6.9/LICENSE.txt b/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.7.0/user/mods/Faupi-MunitionsExpert 1.7.0/LICENSE.txt similarity index 100% rename from Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.6.9/user/mods/Faupi-MunitionsExpert 1.6.9/LICENSE.txt rename to Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.7.0/user/mods/Faupi-MunitionsExpert 1.7.0/LICENSE.txt diff --git a/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.6.9/user/mods/Faupi-MunitionsExpert 1.6.9/package.json b/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.7.0/user/mods/Faupi-MunitionsExpert 1.7.0/package.json similarity index 96% rename from Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.6.9/user/mods/Faupi-MunitionsExpert 1.6.9/package.json rename to Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.7.0/user/mods/Faupi-MunitionsExpert 1.7.0/package.json index e16d760..3155503 100644 --- a/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.6.9/user/mods/Faupi-MunitionsExpert 1.6.9/package.json +++ b/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.7.0/user/mods/Faupi-MunitionsExpert 1.7.0/package.json @@ -1,11 +1,11 @@ { "name": "MunitionsExpert", "author": "Faupi", - "version": "1.6.9", + "updatedBy": "CWX", + "version": "1.7.0", "license": "NCSA Open Source", "main": "./src/MunitionsExpert.js", "akiVersion": "3.5.0", - "updatedBy": "CWX", "scripts": { "setup": "npm i", "build": "node ./packageBuild.ts" diff --git a/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.7.0/user/mods/Faupi-MunitionsExpert 1.7.0/src/MunitionsExpert.ts b/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.7.0/user/mods/Faupi-MunitionsExpert 1.7.0/src/MunitionsExpert.ts new file mode 100644 index 0000000..87192d8 --- /dev/null +++ b/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.7.0/user/mods/Faupi-MunitionsExpert 1.7.0/src/MunitionsExpert.ts @@ -0,0 +1,58 @@ +import type { DependencyContainer } from "tsyringe"; +import { IPostAkiLoadMod } from "@spt-aki/models/external/IPostAkiLoadMod"; +import { DatabaseServer } from "@spt-aki/servers/DatabaseServer" +import { ITemplateItem } from "@spt-aki/models/eft/common/tables/ITemplateItem"; + +class MunitionsExpert implements IPostAkiLoadMod +{ + private database: DatabaseServer; + private items: Record; + private cfg: { BulletBackgroundColours: boolean; } = require("./config.json"); + + public postAkiLoad(container: DependencyContainer) + { + this.database = container.resolve("DatabaseServer"); + this.items = this.database.getTables().templates.items; + this.changeBulletColour(); + } + + private changeBulletColour() + { + if (this.cfg.BulletBackgroundColours) + { + for (const i in this.items) + { + //set background colour of ammo depending on pen + if (this.items[i]._parent === "5485a8684bdc2da71d8b4567") + { + const pen = this.items[i]._props.PenetrationPower; + + switch (true) + { + case (pen > 60): + this.items[i]._props.BackgroundColor = "red"; + break; + case (pen > 50): + this.items[i]._props.BackgroundColor = "yellow"; + break; + case (pen > 40): + this.items[i]._props.BackgroundColor = "violet"; + break; + case (pen > 30): + this.items[i]._props.BackgroundColor = "blue"; + break; + case (pen > 20): + this.items[i]._props.BackgroundColor = "green"; + break; + default: + this.items[i]._props.BackgroundColor = "grey"; + break; + } + } + } + } + } +} + +module.exports = { mod: new MunitionsExpert() }; + diff --git a/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.6.9/user/mods/Faupi-MunitionsExpert 1.6.9/src/config.json b/Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.7.0/user/mods/Faupi-MunitionsExpert 1.7.0/src/config.json similarity index 100% rename from Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.6.9/user/mods/Faupi-MunitionsExpert 1.6.9/src/config.json rename to Faupi-MunitionsExpert/Built/Faupi-MunitionsExpert 1.7.0/user/mods/Faupi-MunitionsExpert 1.7.0/src/config.json diff --git a/Faupi-MunitionsExpert/MunitionsExpert/MunitionsExpert/CachedAttributesPatch.cs b/Faupi-MunitionsExpert/MunitionsExpert/MunitionsExpert/CachedAttributesPatch.cs deleted file mode 100644 index e8a159e..0000000 --- a/Faupi-MunitionsExpert/MunitionsExpert/MunitionsExpert/CachedAttributesPatch.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Aki.Reflection.Patching; -using EFT.InventoryLogic; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; - -namespace MunitionsExpert -{ - internal class CachedAttributesPatch : ModulePatch - { - protected override MethodBase GetTargetMethod() - { - return typeof(AmmoTemplate).GetMethod("GetCachedReadonlyQualities", BindingFlags.Instance | BindingFlags.Public); - } - - [PatchPostfix] - private static void PatchPostfix(ref AmmoTemplate __instance, ref List __result) - { - if (!__result.Any((ItemAttributeClass a) => (Attributes.ENewItemAttributeId)a.Id == Attributes.ENewItemAttributeId.Damage)) - { - //MunitionsExpert.FormatExistingAttributes(ref __result, __instance); - Plugin.AddNewAttributes(ref __result, __instance); - } - } - } -} \ No newline at end of file diff --git a/Faupi-MunitionsExpert/MunitionsExpert/MunitionsExpert/MunitionsExpertPlugin.cs b/Faupi-MunitionsExpert/MunitionsExpert/MunitionsExpert/MunitionsExpertPlugin.cs new file mode 100644 index 0000000..a113c90 --- /dev/null +++ b/Faupi-MunitionsExpert/MunitionsExpert/MunitionsExpert/MunitionsExpertPlugin.cs @@ -0,0 +1,147 @@ +using BepInEx; +using Comfort.Common; +using EFT.InventoryLogic; +using MunitionsExpert.Patches; +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using UnityEngine; +using UnityEngine.Networking; + +namespace MunitionsExpert +{ + [BepInPlugin("com.Faupi.MunitionsExpert", "Faupi-MunitionsExpert", "1.7.0")] + public class MunitionsExpertPlugin : BaseUnityPlugin + { + public static Dictionary iconCache = new Dictionary(); + + private void Awake() + { + CacheIcons(); + new CachedAttributesPatch().Enable(); + new StaticIconsPatch().Enable(); + } + + public static void CacheIcons() + { + iconCache.Add(Attributes.ENewItemAttributeId.Damage, Resources.Load("characteristics/icons/icon_info_damage")); + iconCache.Add(Attributes.ENewItemAttributeId.FragmentationChance, Resources.Load("characteristics/icons/icon_info_shrapnelcount")); + iconCache.Add(EItemAttributeId.LightBleedingDelta, Resources.Load("characteristics/icons/icon_info_bloodloss")); + iconCache.Add(EItemAttributeId.HeavyBleedingDelta, Resources.Load("characteristics/icon_info_hydration")); + iconCache.Add(Attributes.ENewItemAttributeId.Penetration, Resources.Load("characteristics/icon_info_penetration")); + _ = LoadTexture(Attributes.ENewItemAttributeId.ArmorDamage, Path.Combine(Directory.GetCurrentDirectory(), "BepInEx/plugins/Faupi-MunitionsExpert/armorDamage.png")); + _ = LoadTexture(Attributes.ENewItemAttributeId.RicochetChance, Path.Combine(Directory.GetCurrentDirectory(), "BepInEx/plugins/Faupi-MunitionsExpert/ricochet.png")); + } + + public static async Task LoadTexture(Enum id, string path) + { + var unityWebRequest = UnityWebRequestTexture.GetTexture(path); + if (unityWebRequest != null) + { + unityWebRequest.SendWebRequest(); + + while (!unityWebRequest.isDone) + { + await Task.Delay(5); + } + + if (unityWebRequest.responseCode != 200) + { + Debug.LogError($"[MunitionsExpert]: Request Error - {unityWebRequest.responseCode}: {unityWebRequest.error}"); + } + else + { + Debug.LogError($"[MunitionsExpert]: Request Success - {id} from {path}"); + var cachedTexture = DownloadHandlerTexture.GetContent(unityWebRequest); + iconCache.Add(id, Sprite.Create(cachedTexture, new Rect(0, 0, cachedTexture.width, cachedTexture.height), new Vector2(0, 0))); + } + } + } + + public static void AddNewAttributes(ref List attributes, AmmoTemplate template) + { + var totalDamage = template.Damage * template.ProjectileCount; + var damageString = totalDamage.ToString(); + + if (template.ProjectileCount > 1) + { + damageString += $" ({template.Damage} x {template.ProjectileCount})"; + } + + var damageAttribute = new ItemAttributeClass(Attributes.ENewItemAttributeId.Damage) + { + Name = Attributes.ENewItemAttributeId.Damage.GetName(), + Base = () => totalDamage, + StringValue = () => damageString, + DisplayType = () => EItemAttributeDisplayType.Compact + }; + attributes.Add(damageAttribute); + + if (template.ArmorDamage > 0) + { + var armorDamageAttribute = new ItemAttributeClass(Attributes.ENewItemAttributeId.ArmorDamage) + { + Name = Attributes.ENewItemAttributeId.ArmorDamage.GetName(), + Base = () => template.ArmorDamage, + StringValue = () => $"{template.ArmorDamage}%", + DisplayType = () => EItemAttributeDisplayType.Compact + }; + attributes.Add(armorDamageAttribute); + } + + if (template.PenetrationPower > 0) + { + string GetStringValue() + { + int ratedClass = 0; + + if (!Singleton.Instantiated) { return $"[MunitionsExpert]: CLASS_DATA_MISSING {template.PenetrationPower}"; } + var armorClasses = Singleton.Instance.Armor.ArmorClass; + + for (var i = 0; i < armorClasses.Length; i++) + { + if (armorClasses[i].Resistance > template.PenetrationPower) continue; + + ratedClass = Math.Max(ratedClass, i); + } + + return $"{(ratedClass > 0 ? $"Class {ratedClass}" : "Unarmored")} ({template.PenetrationPower})"; + } + + ItemAttributeClass penetrationAttribute = new ItemAttributeClass(Attributes.ENewItemAttributeId.Penetration) + { + Name = Attributes.ENewItemAttributeId.Penetration.GetName(), + Base = () => template.PenetrationPower, + StringValue = GetStringValue, + DisplayType = () => EItemAttributeDisplayType.Compact + }; + attributes.Add(penetrationAttribute); + } + + if (template.FragmentationChance > 0) + { + ItemAttributeClass fragmentationAttribute = new ItemAttributeClass(Attributes.ENewItemAttributeId.FragmentationChance) + { + Name = Attributes.ENewItemAttributeId.FragmentationChance.GetName(), + Base = () => template.FragmentationChance, + StringValue = () => $"{template.FragmentationChance * 100}%", + DisplayType = () => EItemAttributeDisplayType.Compact + }; + attributes.Add(fragmentationAttribute); + } + + if (template.RicochetChance > 0) + { + ItemAttributeClass ricochetAttribute = new ItemAttributeClass(Attributes.ENewItemAttributeId.RicochetChance) + { + Name = Attributes.ENewItemAttributeId.RicochetChance.GetName(), + Base = () => template.RicochetChance, + StringValue = () => $"{template.RicochetChance * 100}%", + DisplayType = () => EItemAttributeDisplayType.Compact + }; + attributes.Add(ricochetAttribute); + } + } + } +} diff --git a/Faupi-MunitionsExpert/MunitionsExpert/MunitionsExpert/Patches/CachedAttributesPatch.cs b/Faupi-MunitionsExpert/MunitionsExpert/MunitionsExpert/Patches/CachedAttributesPatch.cs new file mode 100644 index 0000000..6c9dca5 --- /dev/null +++ b/Faupi-MunitionsExpert/MunitionsExpert/MunitionsExpert/Patches/CachedAttributesPatch.cs @@ -0,0 +1,25 @@ +using Aki.Reflection.Patching; +using EFT.InventoryLogic; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace MunitionsExpert.Patches +{ + internal class CachedAttributesPatch : ModulePatch + { + protected override MethodBase GetTargetMethod() + { + return typeof(AmmoTemplate).GetMethod("GetCachedReadonlyQualities", BindingFlags.Instance | BindingFlags.Public); + } + + [PatchPostfix] + private static void PatchPostfix(ref AmmoTemplate __instance, ref List __result) + { + if (__result.All(a => (Attributes.ENewItemAttributeId)a.Id != Attributes.ENewItemAttributeId.Damage)) + { + MunitionsExpertPlugin.AddNewAttributes(ref __result, __instance); + } + } + } +} \ No newline at end of file diff --git a/Faupi-MunitionsExpert/MunitionsExpert/MunitionsExpert/Patches/StaticIconsPatch.cs b/Faupi-MunitionsExpert/MunitionsExpert/MunitionsExpert/Patches/StaticIconsPatch.cs new file mode 100644 index 0000000..46afb94 --- /dev/null +++ b/Faupi-MunitionsExpert/MunitionsExpert/MunitionsExpert/Patches/StaticIconsPatch.cs @@ -0,0 +1,35 @@ +using System; +using System.Reflection; +using Aki.Reflection.Patching; +using EFT.UI; +using UnityEngine; + +namespace MunitionsExpert.Patches +{ + internal class StaticIconsPatch : ModulePatch + { + protected override MethodBase GetTargetMethod() + { + return typeof(StaticIcons).GetMethod("GetAttributeIcon", BindingFlags.Instance | BindingFlags.Public); + } + + [PatchPrefix] + private static bool PatchPrefix(ref Sprite __result, Enum id) + { + if (id == null || !MunitionsExpertPlugin.iconCache.ContainsKey(id)) + { + return true; + } + + var sprite = MunitionsExpertPlugin.iconCache[id]; + + if (sprite != null) + { + __result = sprite; + return false; + } + + return true; + } + } +} \ No newline at end of file diff --git a/Faupi-MunitionsExpert/MunitionsExpert/MunitionsExpert/Program.cs b/Faupi-MunitionsExpert/MunitionsExpert/MunitionsExpert/Program.cs deleted file mode 100644 index 133e318..0000000 --- a/Faupi-MunitionsExpert/MunitionsExpert/MunitionsExpert/Program.cs +++ /dev/null @@ -1,155 +0,0 @@ -using Aki.Common.Http; -using Aki.Common.Utils; -using BepInEx; -using Comfort.Common; -using EFT.InventoryLogic; -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading.Tasks; -using UnityEngine; -using UnityEngine.Networking; -using static MunitionsExpert.Attributes; - -namespace MunitionsExpert -{ - [BepInPlugin("com.Faupi.MunitionsExpert", "Faupi-MunitionsExpert", "1.6.9")] - public class Plugin : BaseUnityPlugin - { - public static Dictionary iconCache = new Dictionary(); - public static List penAttributes = new List(); - public static string modPath; - - private void Awake() - { - GetPath(); - new CachedAttributesPatch().Enable(); - new StaticIconsPatch().Enable(); - CacheIcons(); - } - - private void GetPath() - { - var mod = RequestHandler.GetJson($"/MunitionsExpert/GetInfo"); - modPath = Json.Deserialize(mod); - } - - public static void CacheIcons() - { - iconCache.Add(ENewItemAttributeId.Damage, Resources.Load("characteristics/icons/icon_info_damage")); - iconCache.Add(ENewItemAttributeId.FragmentationChance, Resources.Load("characteristics/icons/icon_info_shrapnelcount")); - iconCache.Add(EItemAttributeId.LightBleedingDelta, Resources.Load("characteristics/icons/icon_info_bloodloss")); - iconCache.Add(EItemAttributeId.HeavyBleedingDelta, Resources.Load("characteristics/icon_info_hydration")); - iconCache.Add(ENewItemAttributeId.Penetration, Resources.Load("characteristics/icon_info_penetration")); - _ = LoadTexture(ENewItemAttributeId.ArmorDamage, Path.Combine(modPath, "res\\armorDamage.png")); - _ = LoadTexture(ENewItemAttributeId.RicochetChance, Path.Combine(modPath, "res\\armorDamage.png")); - } - - public static async Task LoadTexture(Enum id, string path) - { - using (UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(path)) - { - uwr.SendWebRequest(); - - while (!uwr.isDone) - await Task.Delay(5); - - if (uwr.responseCode != 200) - { - //Log.Error($"[{modName}] Request error {uwr.responseCode}: {uwr.error}"); - } - else - { - // Get downloaded asset bundle - //Log.Info($"[{modName}] Retrieved texture! {id.ToString()} from {path}"); - Texture2D cachedTexture = DownloadHandlerTexture.GetContent(uwr); - iconCache.Add(id, Sprite.Create(cachedTexture, new Rect(0, 0, cachedTexture.width, cachedTexture.height), new Vector2(0, 0))); - } - } - } - - public static void AddNewAttributes(ref List attributes, AmmoTemplate template) - { - int projCount = template.ProjectileCount; - int totalDamage = template.Damage * template.ProjectileCount; - - string damageStr = totalDamage.ToString(); // Total damage - if (template.ProjectileCount > 1) - { - damageStr += $" ({template.Damage} x {template.ProjectileCount})"; // Add the "damage calculation" after total damage (damage per pellet * pellet count) - } - - ItemAttributeClass at_damage = new ItemAttributeClass(ENewItemAttributeId.Damage) - { - Name = ENewItemAttributeId.Damage.GetName(), - Base = () => totalDamage, - StringValue = () => damageStr, - DisplayType = () => EItemAttributeDisplayType.Compact - }; - attributes.Add(at_damage); - - if (template.ArmorDamage > 0) - { - ItemAttributeClass at_armordmg = new ItemAttributeClass(ENewItemAttributeId.ArmorDamage) - { - Name = ENewItemAttributeId.ArmorDamage.GetName(), - Base = () => template.ArmorDamage, - StringValue = () => $"{(template.ArmorDamage).ToString()}%", - DisplayType = () => EItemAttributeDisplayType.Compact - }; - attributes.Add(at_armordmg); - } - - if (template.PenetrationPower > 0) - { - string getStringValue() - { - int ratedClass = 0; - - if (!Singleton.Instantiated) { return $"CLASS_DATA_MISSING {template.PenetrationPower.ToString()}"; } - var classes = Singleton.Instance.Armor.ArmorClass; - for (int i = 0; i < classes.Length; i++) - { - if (classes[i].Resistance > template.PenetrationPower) continue; - ratedClass = Math.Max(ratedClass, i); - } - - return $"{(ratedClass > 0 ? $"{"ME_class".Localized()} {ratedClass}" : "ME_noarmor".Localized())} ({template.PenetrationPower.ToString()})"; - } - - ItemAttributeClass at_pen = new ItemAttributeClass(ENewItemAttributeId.Penetration) - { - Name = ENewItemAttributeId.Penetration.GetName(), - Base = () => template.PenetrationPower, - StringValue = getStringValue, - DisplayType = () => EItemAttributeDisplayType.Compact - }; - attributes.Add(at_pen); - } - - if (template.FragmentationChance > 0) - { - ItemAttributeClass at_frag = new ItemAttributeClass(ENewItemAttributeId.FragmentationChance) - { - Name = ENewItemAttributeId.FragmentationChance.GetName(), - Base = () => template.FragmentationChance, - StringValue = () => $"{(template.FragmentationChance * 100).ToString()}%", - DisplayType = () => EItemAttributeDisplayType.Compact - }; - attributes.Add(at_frag); - } - - if (template.RicochetChance > 0) - { - ItemAttributeClass at_ricochet = new ItemAttributeClass(ENewItemAttributeId.RicochetChance) - { - Name = ENewItemAttributeId.RicochetChance.GetName(), - Base = () => template.RicochetChance, - StringValue = () => $"{(template.RicochetChance * 100).ToString()}%", - DisplayType = () => EItemAttributeDisplayType.Compact - }; - attributes.Add(at_ricochet); - } - } - } -} diff --git a/Faupi-MunitionsExpert/MunitionsExpert/MunitionsExpert/StaticIconsPatch.cs b/Faupi-MunitionsExpert/MunitionsExpert/MunitionsExpert/StaticIconsPatch.cs deleted file mode 100644 index e59e35a..0000000 --- a/Faupi-MunitionsExpert/MunitionsExpert/MunitionsExpert/StaticIconsPatch.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Reflection; -using Aki.Reflection.Patching; -using EFT.UI; -using UnityEngine; - -namespace MunitionsExpert -{ - internal class StaticIconsPatch : ModulePatch - { - protected override MethodBase GetTargetMethod() - { - return typeof(StaticIcons).GetMethod("GetAttributeIcon", BindingFlags.Instance | BindingFlags.Public); - } - - [PatchPrefix] - private static bool PatchPrefix(ref Sprite __result, Enum id) - { - if (id == null || !Plugin.iconCache.ContainsKey(id)) - { - return true; - } - - Sprite sprite = Plugin.iconCache[id]; - - if (sprite != null) - { - __result = sprite; - return false; - } - - return true; - } - } -} \ No newline at end of file diff --git a/Faupi-MunitionsExpert/server/dist/package.json b/Faupi-MunitionsExpert/server/dist/package.json index e16d760..3155503 100644 --- a/Faupi-MunitionsExpert/server/dist/package.json +++ b/Faupi-MunitionsExpert/server/dist/package.json @@ -1,11 +1,11 @@ { "name": "MunitionsExpert", "author": "Faupi", - "version": "1.6.9", + "updatedBy": "CWX", + "version": "1.7.0", "license": "NCSA Open Source", "main": "./src/MunitionsExpert.js", "akiVersion": "3.5.0", - "updatedBy": "CWX", "scripts": { "setup": "npm i", "build": "node ./packageBuild.ts" diff --git a/Faupi-MunitionsExpert/server/dist/res/armorDamage.png b/Faupi-MunitionsExpert/server/dist/res/armorDamage.png deleted file mode 100644 index 70d5e40..0000000 Binary files a/Faupi-MunitionsExpert/server/dist/res/armorDamage.png and /dev/null differ diff --git a/Faupi-MunitionsExpert/server/dist/res/ricochet.png b/Faupi-MunitionsExpert/server/dist/res/ricochet.png deleted file mode 100644 index 27f371e..0000000 Binary files a/Faupi-MunitionsExpert/server/dist/res/ricochet.png and /dev/null differ diff --git a/Faupi-MunitionsExpert/server/dist/res/translations.json b/Faupi-MunitionsExpert/server/dist/res/translations.json deleted file mode 100644 index 530c6ff..0000000 --- a/Faupi-MunitionsExpert/server/dist/res/translations.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "en": { - "DAMAGE": "Damage", - "PENETRATION": "Armor penetration", - "ARMOR DAMAGE": "Damage to armor", - "FRAGMENTATION CHANCE": "Fragmentation chance", - "RICOCHET CHANCE": "Ricochet chance", - "ME_class": "Class", - "ME_noarmor": "Unarmored" - }, - "cz": { - "DAMAGE": "Poškození", - "PENETRATION": "Průbojnost", - "ARMOR DAMAGE": "Poškození brnění", - "FRAGMENTATION CHANCE": "Šance na fragmentaci", - "RICOCHET CHANCE": "Šance na odraz", - "ME_class": "Třída", - "ME_noarmor": "Neobrněný" - }, - "pl": { - "DAMAGE": "Szkoda", - "PENETRATION": "Penetracja pancerza", - "ARMOR DAMAGE": "Uszkodzenie zbroi", - "FRAGMENTATION CHANCE": "Szansa na fragmentację", - "RICOCHET CHANCE": "Szansa na rykoszet", - "ME_class": "Klasa", - "ME_noarmor": "Nieumiejętny" - }, - "po": { - "DAMAGE": "Dano", - "PENETRATION": "Penetração de armadura", - "ARMOR DAMAGE": "Danos à armadura", - "FRAGMENTATION CHANCE": "Chance de fragmentação", - "RICOCHET CHANCE": "Chance de ricochete", - "ME_class": "Classe", - "ME_noarmor": "Sem armadura" - }, - "ch": { - "DAMAGE": "损坏", - "PENETRATION": "护甲穿透", - "ARMOR DAMAGE": "对盔甲的伤害", - "FRAGMENTATION CHANCE": "碎片机会", - "RICOCHET CHANCE": "跳弹机会", - "ME_class": "类", - "ME_noarmor": "无所作为" - }, - "ru": { - "DAMAGE": "Повреждать", - "PENETRATION": "Бронепробиваемость", - "ARMOR DAMAGE": "Повреждение брони", - "FRAGMENTATION CHANCE": "Вероятность фрагментации", - "RICOCHET CHANCE": "Шанс рикошета", - "ME_class": "Класс", - "ME_noarmor": "Без оружия" - }, - "es": { - "DAMAGE": "Daño", - "PENETRATION": "Penetración de armadura", - "ARMOR DAMAGE": "Daño a la armadura", - "FRAGMENTATION CHANCE": "Posibilidad de fragmentación", - "RICOCHET CHANCE": "Oportunidad de rebote", - "ME_class": "Clase", - "ME_noarmor": "Sin armadura" - }, - "es-mx": { - "DAMAGE": "Daño", - "PENETRATION": "Penetración de armadura", - "ARMOR DAMAGE": "Daño a la armadura", - "FRAGMENTATION CHANCE": "Posibilidad de fragmentación", - "RICOCHET CHANCE": "Oportunidad de rebote", - "ME_class": "Clase", - "ME_noarmor": "Sin armadura" - }, - "ge": { - "DAMAGE": "Schaden", - "PENETRATION": "Rüstungsdurchdringung", - "ARMOR DAMAGE": "Beschädigung der Rüstung", - "FRAGMENTATION CHANCE": "Fragmentierung Chance", - "RICOCHET CHANCE": "Querschläger-Chance", - "ME_class": "Klasse", - "ME_noarmor": "Ungepanzert" - }, - "sk": { - "DAMAGE": "Poškodenie", - "PENETRATION": "Prienik do brnenia", - "ARMOR DAMAGE": "Poškodenie brnenia", - "FRAGMENTATION CHANCE": "Šanca na fragmentáciu", - "RICOCHET CHANCE": "Šanca na odraz", - "ME_class": "Trieda", - "ME_noarmor": "Neozbrojený" - }, - "tu": { - "DAMAGE": "Hasar", - "PENETRATION": "Zırh penetrasyon", - "ARMOR DAMAGE": "Zırhta hasar", - "FRAGMENTATION CHANCE": "Parçalanma şansı", - "RICOCHET CHANCE": "Sekme şansı", - "ME_class": "Sınıf", - "ME_noarmor": "zırhsız" - }, - "it": { - "DAMAGE": "Danno", - "PENETRATION": "Penetrazione dell'armatura", - "ARMOR DAMAGE": "Danni all'armatura", - "FRAGMENTATION CHANCE": "Possibilità di frammentazione", - "RICOCHET CHANCE": "Possibilità di rimbalzo", - "ME_class": "Classe", - "ME_noarmor": "Disarmato" - }, - "jp": { - "DAMAGE": "ダメージ", - "PENETRATION": "装甲貫通", - "ARMOR DAMAGE": "鎧の損傷", - "FRAGMENTATION CHANCE": "断片化の可能性", - "RICOCHET CHANCE": "跳ね返るチャンス", - "ME_class": "クラス", - "ME_noarmor": "無装甲" - }, - "fr": { - "DAMAGE": "Dommage", - "PENETRATION": "Pénétration d'armure", - "ARMOR DAMAGE": "Dommages à l'armure", - "FRAGMENTATION CHANCE": "Chance de fragmentation", - "RICOCHET CHANCE": "Chance de ricochet", - "ME_class": "Classe", - "ME_noarmor": "Sans armure" - }, - "hu": { - "DAMAGE": "Kár", - "PENETRATION": "Páncélátütő", - "ARMOR DAMAGE": "A páncél sérülése", - "FRAGMENTATION CHANCE": "Töredezettség esélye", - "RICOCHET CHANCE": "Ricochet esély", - "ME_class": "Osztály", - "ME_noarmor": "Fegyvertelen" - } -} \ No newline at end of file diff --git a/Faupi-MunitionsExpert/server/dist/src/MunitionsExpert.ts b/Faupi-MunitionsExpert/server/dist/src/MunitionsExpert.ts index 4cc6d44..87192d8 100644 --- a/Faupi-MunitionsExpert/server/dist/src/MunitionsExpert.ts +++ b/Faupi-MunitionsExpert/server/dist/src/MunitionsExpert.ts @@ -1,103 +1,53 @@ import type { DependencyContainer } from "tsyringe"; -import { IPreAkiLoadMod } from "@spt-aki/models/external/IPreAkiLoadMod"; import { IPostAkiLoadMod } from "@spt-aki/models/external/IPostAkiLoadMod"; -import { DynamicRouterModService } from "@spt-aki/services/mod/dynamicRouter/DynamicRouterModService" import { DatabaseServer } from "@spt-aki/servers/DatabaseServer" -import { JsonUtil } from "@spt-aki/utils/JsonUtil" -import { IDatabaseTables } from "@spt-aki/models/spt/server/IDatabaseTables"; -import { PreAkiModLoader } from "@spt-aki/loaders/PreAkiModLoader"; +import { ITemplateItem } from "@spt-aki/models/eft/common/tables/ITemplateItem"; -class MunitionsExpert implements IPreAkiLoadMod, IPostAkiLoadMod +class MunitionsExpert implements IPostAkiLoadMod { private database: DatabaseServer; - private router: DynamicRouterModService; - private json: JsonUtil; - private modLoader: PreAkiModLoader; - private table: IDatabaseTables; - private globalLocale: { [x: string]: { interface: { [x: string]: any; }; }; }; - private translations: { [x: string]: any; }; - private items: { [x: string]: any; }; - private path: { resolve: (arg0: string) => any; }; - private cfg: { BulletBackgroundColours: boolean; }; - - public preAkiLoad(container: DependencyContainer) - { - this.router = container.resolve("DynamicRouterModService"); - this.json = container.resolve("JsonUtil"); - this.translations = require("../res/translations.json"); - this.path = require("path"); - this.cfg = require("./config.json"); - this.hookRoutes(); - } + private items: Record; + private cfg: { BulletBackgroundColours: boolean; } = require("./config.json"); public postAkiLoad(container: DependencyContainer) { - this.modLoader = container.resolve("PreAkiModLoader"); this.database = container.resolve("DatabaseServer"); - this.table = this.database.getTables(); - this.globalLocale = this.table.locales.global; - this.items = this.table.templates.items; - this.updateLocalization(); + this.items = this.database.getTables().templates.items; this.changeBulletColour(); } - private updateLocalization() + private changeBulletColour() { - for (const language in this.translations) - { - if (!(language in this.globalLocale)) - { - continue; - } - - const attrKvPair = this.translations[language]; - for (const attrKey in attrKvPair) - { - const attrValue = attrKvPair[attrKey]; - - this.globalLocale[language][attrKey] = attrValue; - } - } - } - - private hookRoutes() - { - this.router.registerDynamicRouter( - "MunitionsExpert", - [ - { - url: "/MunitionsExpert/GetInfo", - action: (url, info, sessionId, output) => - { - return this.json.serialize(this.path.resolve(this.modLoader.getModPath("Faupi-MunitionsExpert 1.6.9"))); - } - } - ], - "MunitionsExpert" - ) - } - - changeBulletColour() - { - if (this.cfg.BulletBackgroundColours === true) + if (this.cfg.BulletBackgroundColours) { for (const i in this.items) { - const item = this.items[i] - - //set baground colour of ammo depending on pen - if (item._parent === "5485a8684bdc2da71d8b4567") + //set background colour of ammo depending on pen + if (this.items[i]._parent === "5485a8684bdc2da71d8b4567") { - const pen = item._props.PenetrationPower - let colour = "" - - pen > 60 ? colour = "red" : //SuperHighPen - pen > 50 ? colour = "yellow" : //HighPen - pen > 40 ? colour = "violet" : //MedHighPen - pen > 30 ? colour = "blue" : //MedPen - pen > 20 ? colour = "green" : //LowMedPen - colour = "grey" //LowPen - item._props.BackgroundColor = colour + const pen = this.items[i]._props.PenetrationPower; + + switch (true) + { + case (pen > 60): + this.items[i]._props.BackgroundColor = "red"; + break; + case (pen > 50): + this.items[i]._props.BackgroundColor = "yellow"; + break; + case (pen > 40): + this.items[i]._props.BackgroundColor = "violet"; + break; + case (pen > 30): + this.items[i]._props.BackgroundColor = "blue"; + break; + case (pen > 20): + this.items[i]._props.BackgroundColor = "green"; + break; + default: + this.items[i]._props.BackgroundColor = "grey"; + break; + } } } } diff --git a/Faupi-MunitionsExpert/server/package.json b/Faupi-MunitionsExpert/server/package.json index e16d760..3155503 100644 --- a/Faupi-MunitionsExpert/server/package.json +++ b/Faupi-MunitionsExpert/server/package.json @@ -1,11 +1,11 @@ { "name": "MunitionsExpert", "author": "Faupi", - "version": "1.6.9", + "updatedBy": "CWX", + "version": "1.7.0", "license": "NCSA Open Source", "main": "./src/MunitionsExpert.js", "akiVersion": "3.5.0", - "updatedBy": "CWX", "scripts": { "setup": "npm i", "build": "node ./packageBuild.ts" diff --git a/Faupi-MunitionsExpert/server/res/armorDamage.png b/Faupi-MunitionsExpert/server/res/armorDamage.png deleted file mode 100644 index 70d5e40..0000000 Binary files a/Faupi-MunitionsExpert/server/res/armorDamage.png and /dev/null differ diff --git a/Faupi-MunitionsExpert/server/res/ricochet.png b/Faupi-MunitionsExpert/server/res/ricochet.png deleted file mode 100644 index 27f371e..0000000 Binary files a/Faupi-MunitionsExpert/server/res/ricochet.png and /dev/null differ diff --git a/Faupi-MunitionsExpert/server/res/translations.json b/Faupi-MunitionsExpert/server/res/translations.json deleted file mode 100644 index 530c6ff..0000000 --- a/Faupi-MunitionsExpert/server/res/translations.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "en": { - "DAMAGE": "Damage", - "PENETRATION": "Armor penetration", - "ARMOR DAMAGE": "Damage to armor", - "FRAGMENTATION CHANCE": "Fragmentation chance", - "RICOCHET CHANCE": "Ricochet chance", - "ME_class": "Class", - "ME_noarmor": "Unarmored" - }, - "cz": { - "DAMAGE": "Poškození", - "PENETRATION": "Průbojnost", - "ARMOR DAMAGE": "Poškození brnění", - "FRAGMENTATION CHANCE": "Šance na fragmentaci", - "RICOCHET CHANCE": "Šance na odraz", - "ME_class": "Třída", - "ME_noarmor": "Neobrněný" - }, - "pl": { - "DAMAGE": "Szkoda", - "PENETRATION": "Penetracja pancerza", - "ARMOR DAMAGE": "Uszkodzenie zbroi", - "FRAGMENTATION CHANCE": "Szansa na fragmentację", - "RICOCHET CHANCE": "Szansa na rykoszet", - "ME_class": "Klasa", - "ME_noarmor": "Nieumiejętny" - }, - "po": { - "DAMAGE": "Dano", - "PENETRATION": "Penetração de armadura", - "ARMOR DAMAGE": "Danos à armadura", - "FRAGMENTATION CHANCE": "Chance de fragmentação", - "RICOCHET CHANCE": "Chance de ricochete", - "ME_class": "Classe", - "ME_noarmor": "Sem armadura" - }, - "ch": { - "DAMAGE": "损坏", - "PENETRATION": "护甲穿透", - "ARMOR DAMAGE": "对盔甲的伤害", - "FRAGMENTATION CHANCE": "碎片机会", - "RICOCHET CHANCE": "跳弹机会", - "ME_class": "类", - "ME_noarmor": "无所作为" - }, - "ru": { - "DAMAGE": "Повреждать", - "PENETRATION": "Бронепробиваемость", - "ARMOR DAMAGE": "Повреждение брони", - "FRAGMENTATION CHANCE": "Вероятность фрагментации", - "RICOCHET CHANCE": "Шанс рикошета", - "ME_class": "Класс", - "ME_noarmor": "Без оружия" - }, - "es": { - "DAMAGE": "Daño", - "PENETRATION": "Penetración de armadura", - "ARMOR DAMAGE": "Daño a la armadura", - "FRAGMENTATION CHANCE": "Posibilidad de fragmentación", - "RICOCHET CHANCE": "Oportunidad de rebote", - "ME_class": "Clase", - "ME_noarmor": "Sin armadura" - }, - "es-mx": { - "DAMAGE": "Daño", - "PENETRATION": "Penetración de armadura", - "ARMOR DAMAGE": "Daño a la armadura", - "FRAGMENTATION CHANCE": "Posibilidad de fragmentación", - "RICOCHET CHANCE": "Oportunidad de rebote", - "ME_class": "Clase", - "ME_noarmor": "Sin armadura" - }, - "ge": { - "DAMAGE": "Schaden", - "PENETRATION": "Rüstungsdurchdringung", - "ARMOR DAMAGE": "Beschädigung der Rüstung", - "FRAGMENTATION CHANCE": "Fragmentierung Chance", - "RICOCHET CHANCE": "Querschläger-Chance", - "ME_class": "Klasse", - "ME_noarmor": "Ungepanzert" - }, - "sk": { - "DAMAGE": "Poškodenie", - "PENETRATION": "Prienik do brnenia", - "ARMOR DAMAGE": "Poškodenie brnenia", - "FRAGMENTATION CHANCE": "Šanca na fragmentáciu", - "RICOCHET CHANCE": "Šanca na odraz", - "ME_class": "Trieda", - "ME_noarmor": "Neozbrojený" - }, - "tu": { - "DAMAGE": "Hasar", - "PENETRATION": "Zırh penetrasyon", - "ARMOR DAMAGE": "Zırhta hasar", - "FRAGMENTATION CHANCE": "Parçalanma şansı", - "RICOCHET CHANCE": "Sekme şansı", - "ME_class": "Sınıf", - "ME_noarmor": "zırhsız" - }, - "it": { - "DAMAGE": "Danno", - "PENETRATION": "Penetrazione dell'armatura", - "ARMOR DAMAGE": "Danni all'armatura", - "FRAGMENTATION CHANCE": "Possibilità di frammentazione", - "RICOCHET CHANCE": "Possibilità di rimbalzo", - "ME_class": "Classe", - "ME_noarmor": "Disarmato" - }, - "jp": { - "DAMAGE": "ダメージ", - "PENETRATION": "装甲貫通", - "ARMOR DAMAGE": "鎧の損傷", - "FRAGMENTATION CHANCE": "断片化の可能性", - "RICOCHET CHANCE": "跳ね返るチャンス", - "ME_class": "クラス", - "ME_noarmor": "無装甲" - }, - "fr": { - "DAMAGE": "Dommage", - "PENETRATION": "Pénétration d'armure", - "ARMOR DAMAGE": "Dommages à l'armure", - "FRAGMENTATION CHANCE": "Chance de fragmentation", - "RICOCHET CHANCE": "Chance de ricochet", - "ME_class": "Classe", - "ME_noarmor": "Sans armure" - }, - "hu": { - "DAMAGE": "Kár", - "PENETRATION": "Páncélátütő", - "ARMOR DAMAGE": "A páncél sérülése", - "FRAGMENTATION CHANCE": "Töredezettség esélye", - "RICOCHET CHANCE": "Ricochet esély", - "ME_class": "Osztály", - "ME_noarmor": "Fegyvertelen" - } -} \ No newline at end of file diff --git a/Faupi-MunitionsExpert/server/src/MunitionsExpert.ts b/Faupi-MunitionsExpert/server/src/MunitionsExpert.ts index 4cc6d44..87192d8 100644 --- a/Faupi-MunitionsExpert/server/src/MunitionsExpert.ts +++ b/Faupi-MunitionsExpert/server/src/MunitionsExpert.ts @@ -1,103 +1,53 @@ import type { DependencyContainer } from "tsyringe"; -import { IPreAkiLoadMod } from "@spt-aki/models/external/IPreAkiLoadMod"; import { IPostAkiLoadMod } from "@spt-aki/models/external/IPostAkiLoadMod"; -import { DynamicRouterModService } from "@spt-aki/services/mod/dynamicRouter/DynamicRouterModService" import { DatabaseServer } from "@spt-aki/servers/DatabaseServer" -import { JsonUtil } from "@spt-aki/utils/JsonUtil" -import { IDatabaseTables } from "@spt-aki/models/spt/server/IDatabaseTables"; -import { PreAkiModLoader } from "@spt-aki/loaders/PreAkiModLoader"; +import { ITemplateItem } from "@spt-aki/models/eft/common/tables/ITemplateItem"; -class MunitionsExpert implements IPreAkiLoadMod, IPostAkiLoadMod +class MunitionsExpert implements IPostAkiLoadMod { private database: DatabaseServer; - private router: DynamicRouterModService; - private json: JsonUtil; - private modLoader: PreAkiModLoader; - private table: IDatabaseTables; - private globalLocale: { [x: string]: { interface: { [x: string]: any; }; }; }; - private translations: { [x: string]: any; }; - private items: { [x: string]: any; }; - private path: { resolve: (arg0: string) => any; }; - private cfg: { BulletBackgroundColours: boolean; }; - - public preAkiLoad(container: DependencyContainer) - { - this.router = container.resolve("DynamicRouterModService"); - this.json = container.resolve("JsonUtil"); - this.translations = require("../res/translations.json"); - this.path = require("path"); - this.cfg = require("./config.json"); - this.hookRoutes(); - } + private items: Record; + private cfg: { BulletBackgroundColours: boolean; } = require("./config.json"); public postAkiLoad(container: DependencyContainer) { - this.modLoader = container.resolve("PreAkiModLoader"); this.database = container.resolve("DatabaseServer"); - this.table = this.database.getTables(); - this.globalLocale = this.table.locales.global; - this.items = this.table.templates.items; - this.updateLocalization(); + this.items = this.database.getTables().templates.items; this.changeBulletColour(); } - private updateLocalization() + private changeBulletColour() { - for (const language in this.translations) - { - if (!(language in this.globalLocale)) - { - continue; - } - - const attrKvPair = this.translations[language]; - for (const attrKey in attrKvPair) - { - const attrValue = attrKvPair[attrKey]; - - this.globalLocale[language][attrKey] = attrValue; - } - } - } - - private hookRoutes() - { - this.router.registerDynamicRouter( - "MunitionsExpert", - [ - { - url: "/MunitionsExpert/GetInfo", - action: (url, info, sessionId, output) => - { - return this.json.serialize(this.path.resolve(this.modLoader.getModPath("Faupi-MunitionsExpert 1.6.9"))); - } - } - ], - "MunitionsExpert" - ) - } - - changeBulletColour() - { - if (this.cfg.BulletBackgroundColours === true) + if (this.cfg.BulletBackgroundColours) { for (const i in this.items) { - const item = this.items[i] - - //set baground colour of ammo depending on pen - if (item._parent === "5485a8684bdc2da71d8b4567") + //set background colour of ammo depending on pen + if (this.items[i]._parent === "5485a8684bdc2da71d8b4567") { - const pen = item._props.PenetrationPower - let colour = "" - - pen > 60 ? colour = "red" : //SuperHighPen - pen > 50 ? colour = "yellow" : //HighPen - pen > 40 ? colour = "violet" : //MedHighPen - pen > 30 ? colour = "blue" : //MedPen - pen > 20 ? colour = "green" : //LowMedPen - colour = "grey" //LowPen - item._props.BackgroundColor = colour + const pen = this.items[i]._props.PenetrationPower; + + switch (true) + { + case (pen > 60): + this.items[i]._props.BackgroundColor = "red"; + break; + case (pen > 50): + this.items[i]._props.BackgroundColor = "yellow"; + break; + case (pen > 40): + this.items[i]._props.BackgroundColor = "violet"; + break; + case (pen > 30): + this.items[i]._props.BackgroundColor = "blue"; + break; + case (pen > 20): + this.items[i]._props.BackgroundColor = "green"; + break; + default: + this.items[i]._props.BackgroundColor = "grey"; + break; + } } } }