Patching correct armor values

This commit is contained in:
bepis69 2022-06-22 21:20:17 -04:00
parent 79384d4f92
commit 39d494b196
12 changed files with 164 additions and 218 deletions

13
.gitignore vendored
View File

@ -10,6 +10,7 @@ obj/
.idea .idea
slnx.sqlite slnx.sqlite
slnx-journal.sqlite slnx-journal.sqlite
Built/
## nodejs ## nodejs
node_modules node_modules
@ -20,14 +21,8 @@ package-lock.json
desktop.ini desktop.ini
## ALT-Mods ## ALT-Mods
Faupi-HideoutMod/Project/bin
Faupi-HideoutMod/Project/obj
Faupi-MunitionsExpert/MunitionsExpert/bin bepis69-ExpandedArmorDetails/ExpandedArmorDetails/bin
Faupi-MunitionsExpert/MunitionsExpert/obj bepis69-ExpandedArmorDetails/ExpandedArmorDetails/obj
KcY-SeeItemValue/itemValue/bin Folder.DotSettings.user
KcY-SeeItemValue/itemValue/obj
Built/

View File

@ -30,14 +30,8 @@
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<!-- <PropertyGroup>-->
<!-- <SignAssembly>true</SignAssembly>-->
<!-- </PropertyGroup>-->
<!-- <PropertyGroup>-->
<!-- <AssemblyOriginatorKeyFile>-->
<!-- </AssemblyOriginatorKeyFile>-->
<!-- </PropertyGroup>-->
<ItemGroup> <ItemGroup>
<Compile Include="src\client\ArmorTemplate.cs" />
<Compile Include="src\client\StaticIconsPatch.cs" /> <Compile Include="src\client\StaticIconsPatch.cs" />
<Compile Include="src\client\CachedAttributesPatch.cs" /> <Compile Include="src\client\CachedAttributesPatch.cs" />
<Compile Include="src\client\ModInformation.cs" /> <Compile Include="src\client\ModInformation.cs" />

View File

@ -6,12 +6,12 @@ using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following // General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information // set of attributes. Change these attribute values to modify the information
// associated with an assembly. // associated with an assembly.
[assembly: AssemblyTitle("MunitionsExpert - Ammo stats in inspect view")] [assembly: AssemblyTitle("ExpandedArmorDetails - Ammo stats in inspect view")]
[assembly: AssemblyDescription("Adds ammo stats to inspect view as well as improving the format a little")] [assembly: AssemblyDescription("Adds armor stats to inspect view as well as improving the format a little")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")] [assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SPT-AKI - MunitionsExpert")] [assembly: AssemblyProduct("SPT-AKI - ExpandedArmorDetails")]
[assembly: AssemblyCopyright("Faupi © 2021")] [assembly: AssemblyCopyright("bepis69 © 2022")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]

View File

@ -0,0 +1,7 @@
namespace ExpandedArmorDetails
{
public class ArmorTemplate : GClass1898
{
}
}

View File

@ -1,30 +1,21 @@
namespace MunitionsExpert namespace ExpandedArmorDetails
{ {
public static class Attributes public static class Attributes
{ {
public enum ENewItemAttributeId public enum ENewItemAttributeId
{ {
Damage, DurabilityFactor,
ArmorDamage, EffectiveDurability
Penetration,
FragmentationChance,
RicochetChance
} }
public static string GetName(this ENewItemAttributeId id) public static string GetName(this ENewItemAttributeId id)
{ {
switch (id) switch (id)
{ {
case ENewItemAttributeId.Damage: case ENewItemAttributeId.DurabilityFactor:
return "DAMAGE"; return "DESTRUCTIBILITY";
case ENewItemAttributeId.ArmorDamage: case ENewItemAttributeId.EffectiveDurability:
return "ARMOR DAMAGE"; return "EFFECTIVE DURABILITY";
case ENewItemAttributeId.Penetration:
return "PENETRATION";
case ENewItemAttributeId.FragmentationChance:
return "FRAGMENTATION CHANCE";
case ENewItemAttributeId.RicochetChance:
return "RICOCHET CHANCE";
default: default:
return id.ToString(); return id.ToString();
} }

View File

@ -5,23 +5,19 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using ItemAttributes = GClass2100; using ItemAttributes = GClass2100;
namespace MunitionsExpert namespace ExpandedArmorDetails
{ {
internal class CachedAttributesPatch : ModulePatch internal class CachedAttributesPatch : ModulePatch
{ {
protected override MethodBase GetTargetMethod() protected override MethodBase GetTargetMethod()
{ {
return typeof(AmmoTemplate).GetMethod("GetCachedReadonlyQualities", BindingFlags.Instance | BindingFlags.Public); return typeof(ArmorTemplate).GetMethod("GetCachedReadonlyQualities", BindingFlags.Instance | BindingFlags.Public);
} }
[PatchPostfix] [PatchPostfix]
private static void PatchPostfix(ref AmmoTemplate __instance, ref List<ItemAttributes> __result) private static void PatchPostfix(ref ArmorTemplate __instance, ref List<ItemAttributes> __result)
{ {
if (!__result.Any((ItemAttributes a) => (Attributes.ENewItemAttributeId)a.Id == Attributes.ENewItemAttributeId.Damage)) ExpandedArmorDetails.AddNewAttributes(ref __result, __instance);
{
//ExpandedArmorDetails.FormatExistingAttributes(ref __result, __instance);
MunitionsExpert.AddNewAttributes(ref __result, __instance);
}
} }
} }
} }

View File

@ -0,0 +1,131 @@
using System;
using System.IO;
using System.Collections.Generic;
using UnityEngine;
using EFT.InventoryLogic;
using UnityEngine.Networking;
using System.Threading.Tasks;
using BepInEx;
using Comfort.Common;
using ItemAttribute = GClass2100;
using static ExpandedArmorDetails.Attributes;
using ServerSettings = GClass1087;
namespace ExpandedArmorDetails
{
[BepInPlugin("com.bepis69.ExpandedArmorDetails", "bepis69-ExpandedArmorDetails", "0.0.1")]
public class ExpandedArmorDetails : BaseUnityPlugin
{
private void Awake()
{
new CachedAttributesPatch().Enable();
new StaticIconsPatch().Enable();
CacheIcons();
}
private static ModInformation _modInfo;
public static ModInformation ModInfo
{
private set
{
_modInfo = value;
}
get
{
if (_modInfo == null)
_modInfo = ModInformation.Load();
return _modInfo;
}
}
public static Dictionary<Enum, Sprite> iconCache = new Dictionary<Enum, Sprite>();
public static List<ItemAttribute> penAttributes = new List<ItemAttribute>(); // For refreshing armor class rating
public static string modName = ModInfo.name;
public static void CacheIcons()
{
_ = LoadTexture(ENewItemAttributeId.DurabilityFactor, Path.Combine(ModInfo.path, "res/ricochet.png"));
_ = LoadTexture(ENewItemAttributeId.EffectiveDurability, Path.Combine(ModInfo.path, "res/ricochet.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)));
}
}
}
private static float CalculateDurabilityFactor(EArmorMaterial material)
{
switch (material)
{
case EArmorMaterial.Aluminium:
return 0.6f;
case EArmorMaterial.Aramid:
return 0.25f;
case EArmorMaterial.Ceramic:
return 0.8f;
case EArmorMaterial.Combined:
return 0.5f;
case EArmorMaterial.Glass:
return 0.8f;
case EArmorMaterial.Titan:
return 0.55f;
case EArmorMaterial.ArmoredSteel:
return 0.7f;
case EArmorMaterial.UHMWPE:
return 0.45f;
default:
return 1f;
}
}
public static void AddNewAttributes(ref List<ItemAttribute> attributes, ArmorTemplate template)
{
if (template.ArmorMaterial > 0)
{
float durabilityFactor = CalculateDurabilityFactor(template.ArmorMaterial);
ItemAttribute atDurabilityFact = new ItemAttribute(ENewItemAttributeId.DurabilityFactor)
{
Name = ENewItemAttributeId.DurabilityFactor.GetName(),
Base = () => durabilityFactor,
StringValue = () => $"{(( 1-durabilityFactor+1) * 100).ToString()}%",
DisplayType = () => EItemAttributeDisplayType.Compact
};
attributes.Add(atDurabilityFact);
if (template.MaxDurability > 0)
{
int effectiveDurability = (int)(template.MaxDurability / durabilityFactor);
ItemAttribute atDurabilityEff = new ItemAttribute(ENewItemAttributeId.EffectiveDurability)
{
Name = ENewItemAttributeId.EffectiveDurability.GetName(),
Base = () => effectiveDurability,
StringValue = () => effectiveDurability.ToString(),
DisplayType = () => EItemAttributeDisplayType.Compact
};
attributes.Add(atDurabilityEff);
}
}
}
}
}

View File

@ -4,7 +4,7 @@ using System;
using UnityEngine; using UnityEngine;
using UnityEngine.Assertions; using UnityEngine.Assertions;
namespace MunitionsExpert namespace ExpandedArmorDetails
{ {
public class ModInformation public class ModInformation
{ {
@ -27,7 +27,7 @@ namespace MunitionsExpert
} }
catch (Exception getModInfoException) catch (Exception getModInfoException)
{ {
string errMsg = $"[{typeof(MunitionsExpert)}] Package.json couldn't be found! Make sure you've installed the mod on the server as well!"; string errMsg = $"[{typeof(ExpandedArmorDetails)}] Package.json couldn't be found! Make sure you've installed the mod on the server as well!";
Debug.LogError(errMsg); Debug.LogError(errMsg);
throw getModInfoException; throw getModInfoException;
} }

View File

@ -1,165 +0,0 @@
using System;
using System.IO;
using System.Collections.Generic;
using UnityEngine;
using EFT.InventoryLogic;
using UnityEngine.Networking;
using System.Threading.Tasks;
using BepInEx;
using Comfort.Common;
using ItemAttribute = GClass2100;
using static MunitionsExpert.Attributes;
using ServerSettings = GClass1087;
namespace MunitionsExpert
{
[BepInPlugin("com.FAUPI.ExpandedArmorDetails", "FAUPI-ExpandedArmorDetails", "1.4.0")]
public class MunitionsExpert : BaseUnityPlugin
{
private void Awake()
{
new CachedAttributesPatch().Enable();
new StaticIconsPatch().Enable();
CacheIcons();
}
private static ModInformation _modInfo;
public static ModInformation ModInfo
{
private set
{
_modInfo = value;
}
get
{
if (_modInfo == null)
_modInfo = ModInformation.Load();
return _modInfo;
}
}
public static Dictionary<Enum, Sprite> iconCache = new Dictionary<Enum, Sprite>();
public static List<ItemAttribute> penAttributes = new List<ItemAttribute>(); // For refreshing armor class rating
public static string modName = ModInfo.name;
public static void CacheIcons()
{
iconCache.Add(ENewItemAttributeId.Damage, Resources.Load<Sprite>("characteristics/icons/icon_info_damage"));
iconCache.Add(ENewItemAttributeId.FragmentationChance, Resources.Load<Sprite>("characteristics/icons/icon_info_shrapnelcount"));
iconCache.Add(EItemAttributeId.LightBleedingDelta, Resources.Load<Sprite>("characteristics/icons/icon_info_bloodloss"));
iconCache.Add(EItemAttributeId.HeavyBleedingDelta, Resources.Load<Sprite>("characteristics/icon_info_hydration"));
iconCache.Add(ENewItemAttributeId.Penetration, Resources.Load<Sprite>("characteristics/icon_info_penetration"));
_ = LoadTexture(ENewItemAttributeId.ArmorDamage, Path.Combine(ModInfo.path, "res/armorDamage.png"));
_ = LoadTexture(ENewItemAttributeId.RicochetChance, Path.Combine(ModInfo.path, "res/ricochet.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<ItemAttribute> 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)
}
ItemAttribute at_damage = new ItemAttribute(ENewItemAttributeId.Damage)
{
Name = ENewItemAttributeId.Damage.GetName(),
Base = () => totalDamage,
StringValue = () => damageStr,
DisplayType = () => EItemAttributeDisplayType.Compact
};
attributes.Add(at_damage);
if (template.ArmorDamage > 0)
{
ItemAttribute at_armordmg = new ItemAttribute(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<ServerSettings>.Instantiated) { return $"CLASS_DATA_MISSING {template.PenetrationPower.ToString()}"; }
ServerSettings.GClass1134.GClass1135[] classes = Singleton<ServerSettings>.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()})";
}
ItemAttribute at_pen = new ItemAttribute(ENewItemAttributeId.Penetration)
{
Name = ENewItemAttributeId.Penetration.GetName(),
Base = () => template.PenetrationPower,
StringValue = getStringValue,
DisplayType = () => EItemAttributeDisplayType.Compact
};
attributes.Add(at_pen);
}
if (template.FragmentationChance > 0)
{
ItemAttribute at_frag = new ItemAttribute(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)
{
ItemAttribute at_ricochet = new ItemAttribute(ENewItemAttributeId.RicochetChance)
{
Name = ENewItemAttributeId.RicochetChance.GetName(),
Base = () => template.RicochetChance,
StringValue = () => $"{(template.RicochetChance * 100).ToString()}%",
DisplayType = () => EItemAttributeDisplayType.Compact
};
attributes.Add(at_ricochet);
}
}
}
}

View File

@ -4,7 +4,7 @@ using Aki.Reflection.Patching;
using EFT.UI; using EFT.UI;
using UnityEngine; using UnityEngine;
namespace MunitionsExpert namespace ExpandedArmorDetails
{ {
internal class StaticIconsPatch : ModulePatch internal class StaticIconsPatch : ModulePatch
{ {
@ -16,12 +16,12 @@ namespace MunitionsExpert
[PatchPrefix] [PatchPrefix]
private static bool PatchPrefix(ref Sprite __result, Enum id) private static bool PatchPrefix(ref Sprite __result, Enum id)
{ {
if (id == null || !MunitionsExpert.iconCache.ContainsKey(id)) if (id == null || !ExpandedArmorDetails.iconCache.ContainsKey(id))
{ {
return true; return true;
} }
Sprite sprite = MunitionsExpert.iconCache[id]; Sprite sprite = ExpandedArmorDetails.iconCache[id];
if (sprite != null) if (sprite != null)
{ {

View File

@ -3,7 +3,7 @@
"author": "bepis69", "author": "bepis69",
"version": "0.0.1", "version": "0.0.1",
"license": "NCSA Open Source", "license": "NCSA Open Source",
"main": "./src/MunitionsExpert.js", "main": "./src/ExpandedArmorDetails.js",
"akiVersion": "2.3.1", "akiVersion": "2.3.1",
"updatedBy": "CWX", "updatedBy": "CWX",
"scripts": { "scripts": {

View File

@ -1,3 +0,0 @@
{
"BulletBackgroundColours": true
}