using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("WeaponDamageDisplay")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("WeaponDamageDisplay")] [assembly: AssemblyTitle("WeaponDamageDisplay")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace WeaponDamageDisplay { [BepInPlugin("com.nadre.weapondamagedisplay", "WeaponDamageDisplay", "1.3.0")] public class Plugin : BaseUnityPlugin { [HarmonyPatch(typeof(PlayerControllerB))] internal class PlayerControllerBPatch { private static int lastTooltipIndex = -1; private static HUDManager? lastHudInstance = null; private static readonly HashSet _ignoredTypeNames = new HashSet(StringComparer.OrdinalIgnoreCase) { "FlashlightItem", "PatcherTool", "WalkieTalkie", "BoomboxItem", "KeyItem", "ShoppingCart", "RadarBoosterItem", "NoisemakerProp", "SprayPaintItem", "ExtensionLadderItem", "TetraChemicalItem", "JetpackItem", "LungProp" }; private static readonly string[] _damageKeywords = new string[11] { "hitforce", "shovelhitforce", "hitdamage", "damagevalue", "damage", "force", "power", "attack", "hit", "strike", "weapon" }; private static MethodInfo? _lguShovelForceMethod = null; private static MethodInfo? _lguKnifeForceMethod = null; private static bool _checkedLgu = false; private static readonly Dictionary _damageMemberCache = new Dictionary(); public static void ResetTooltipTracker() { lastTooltipIndex = -1; lastHudInstance = null; } private static void ClearLastTooltip() { if (lastTooltipIndex != -1 && (Object)(object)lastHudInstance != (Object)null && lastHudInstance.controlTipLines != null && lastTooltipIndex >= 0 && lastTooltipIndex < lastHudInstance.controlTipLines.Length && (Object)(object)lastHudInstance.controlTipLines[lastTooltipIndex] != (Object)null && ((TMP_Text)lastHudInstance.controlTipLines[lastTooltipIndex]).text != "") { ((TMP_Text)lastHudInstance.controlTipLines[lastTooltipIndex]).text = ""; } lastTooltipIndex = -1; lastHudInstance = null; } [HarmonyPatch("Update")] [HarmonyPostfix] private static void Postfix_Update(PlayerControllerB __instance) { if ((Object)(object)StartOfRound.Instance == (Object)null || (Object)(object)__instance != (Object)(object)StartOfRound.Instance.localPlayerController) { return; } GrabbableObject val = null; if (__instance.ItemSlots != null && __instance.currentItemSlot >= 0 && __instance.currentItemSlot < __instance.ItemSlots.Length) { val = __instance.ItemSlots[__instance.currentItemSlot]; } if ((Object)(object)val != (Object)null) { string weaponDamage = GetWeaponDamage(val); if (!string.IsNullOrEmpty(weaponDamage) && (Object)(object)HUDManager.Instance != (Object)null && HUDManager.Instance.controlTipLines != null) { int num = 0; if (val.itemProperties?.toolTips != null) { num = val.itemProperties.toolTips.Length; } if (num < HUDManager.Instance.controlTipLines.Length) { if (lastTooltipIndex != -1 && lastTooltipIndex != num) { ClearLastTooltip(); } if ((Object)(object)HUDManager.Instance.controlTipLines[num] != (Object)null) { string text = "Dégat : " + weaponDamage; if (((TMP_Text)HUDManager.Instance.controlTipLines[num]).text != text) { ((TMP_Text)HUDManager.Instance.controlTipLines[num]).text = text; } lastTooltipIndex = num; lastHudInstance = HUDManager.Instance; } } else { ClearLastTooltip(); } } else { ClearLastTooltip(); } } else { ClearLastTooltip(); } } private static void TryLoadLgu() { if (_checkedLgu) { return; } _checkedLgu = true; try { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (assembly.GetName().Name != "MoreShipUpgrades") { continue; } Type type = assembly.GetType("MoreShipUpgrades.UpgradeComponents.TierUpgrades.ProteinPowder"); if (type != null) { _lguShovelForceMethod = type.GetMethod("GetShovelHitForce", BindingFlags.Static | BindingFlags.Public); if (_lguShovelForceMethod != null) { LoggerInstance.LogInfo((object)"[LGU] Support Protein Powder (pelle) activé."); } } string[] array = new string[3] { "MoreShipUpgrades.UpgradeComponents.TierUpgrades.ProteinPowder", "MoreShipUpgrades.UpgradeComponents.TierUpgrades.BigBolt", "MoreShipUpgrades.UpgradeComponents.TierUpgrades.MedKit" }; foreach (string text in array) { Type type2 = assembly.GetType(text); if (!(type2 == null)) { MethodInfo methodInfo = type2.GetMethod("GetKnifeHitForce", BindingFlags.Static | BindingFlags.Public) ?? type2.GetMethod("GetMeleeHitForce", BindingFlags.Static | BindingFlags.Public) ?? type2.GetMethod("GetWeaponHitForce", BindingFlags.Static | BindingFlags.Public); if (methodInfo != null) { _lguKnifeForceMethod = methodInfo; LoggerInstance.LogInfo((object)("[LGU] Support bonus couteau/mêlée trouvé dans " + text + ".")); break; } } } break; } } catch (Exception ex) { LoggerInstance.LogError((object)("[LGU] Erreur détection MoreShipUpgrades : " + ex.Message)); } } private static int GetLguShovelForce(int originalForce) { TryLoadLgu(); if (_lguShovelForceMethod != null) { try { object obj = _lguShovelForceMethod.Invoke(null, new object[1] { originalForce }); if (obj is int) { return (int)obj; } } catch { } } return originalForce; } private static int GetLguKnifeForce(int originalForce) { TryLoadLgu(); if (_lguKnifeForceMethod != null) { try { object obj = _lguKnifeForceMethod.Invoke(null, new object[1] { originalForce }); if (obj is int) { return (int)obj; } } catch { } } return originalForce; } private static MemberInfo? FindDamageMember(Type? type) { if (type == null || type == typeof(MonoBehaviour) || type == typeof(Object)) { return null; } if (_damageMemberCache.TryGetValue(type, out MemberInfo value)) { return value; } MemberInfo memberInfo = null; Type type2 = type; while (type2 != null && type2 != typeof(MonoBehaviour) && type2 != typeof(Object)) { FieldInfo[] fields = type2.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); string[] damageKeywords = _damageKeywords; foreach (string value2 in damageKeywords) { FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { if (fieldInfo.Name.ToLower().Contains(value2)) { Type fieldType = fieldInfo.FieldType; if (fieldType == typeof(int) || fieldType == typeof(float) || fieldType == typeof(double)) { memberInfo = fieldInfo; break; } } } if (memberInfo != null) { break; } } if (memberInfo != null) { break; } PropertyInfo[] properties = type2.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); damageKeywords = _damageKeywords; foreach (string value3 in damageKeywords) { PropertyInfo[] array2 = properties; foreach (PropertyInfo propertyInfo in array2) { if (propertyInfo.GetIndexParameters().Length == 0 && propertyInfo.Name.ToLower().Contains(value3)) { Type propertyType = propertyInfo.PropertyType; if (propertyType == typeof(int) || propertyType == typeof(float) || propertyType == typeof(double)) { memberInfo = propertyInfo; break; } } } if (memberInfo != null) { break; } } if (memberInfo != null) { break; } type2 = type2.BaseType; } _damageMemberCache[type] = memberInfo; return memberInfo; } private static string GetWeaponDamage(GrabbableObject item) { if ((Object)(object)item == (Object)null) { return ""; } string name = ((object)item).GetType().Name; if (_ignoredTypeNames.Contains(name)) { return ""; } Shovel val = (Shovel)(object)((item is Shovel) ? item : null); if (val != null) { int lguShovelForce = GetLguShovelForce(val.shovelHitForce); return $"{lguShovelForce} HP"; } if (name == "ShotgunItem") { return "1-5 par plomb (max 50)"; } if (name == "KnifeItem") { int num = 1; int lguKnifeForce = GetLguKnifeForce(num); if (lguKnifeForce <= num) { return "1 HP (Rapide)"; } return $"{lguKnifeForce} HP (LGU)"; } try { MemberInfo memberInfo = FindDamageMember(((object)item).GetType()); if (memberInfo != null) { object obj = null; if (memberInfo is FieldInfo fieldInfo) { obj = fieldInfo.GetValue(item); } else if (memberInfo is PropertyInfo propertyInfo) { obj = propertyInfo.GetValue(item); } if (obj != null) { if (obj is int num2) { return $"{num2} HP"; } if (obj is float num3) { return $"{num3:0.#} HP"; } if (obj is double) { double num4 = (double)obj; return $"{num4:0.#} HP"; } } } } catch (Exception ex) { LoggerInstance.LogError((object)("[WDD] Réflexion échouée sur " + name + " : " + ex.Message)); } if ((Object)(object)item.itemProperties != (Object)null && item.itemProperties.isDefensiveWeapon) { return "Arme (valeur inconnue)"; } return ""; } } [HarmonyPatch(typeof(StartOfRound))] internal class StartOfRoundPatch { [HarmonyPatch("Start")] [HarmonyPostfix] private static void Postfix_Start() { LoggerInstance.LogInfo((object)"[WDD] StartOfRound.Start : Initialisation terminée."); PlayerControllerBPatch.ResetTooltipTracker(); } } public const string ModGUID = "com.nadre.weapondamagedisplay"; public const string ModName = "WeaponDamageDisplay"; public const string ModVersion = "1.3.0"; private readonly Harmony harmony = new Harmony("com.nadre.weapondamagedisplay"); internal static Plugin? Instance; internal static ManualLogSource LoggerInstance; private void Awake() { Instance = this; LoggerInstance = ((BaseUnityPlugin)this).Logger; LoggerInstance.LogInfo((object)"WeaponDamageDisplay v1.3.0 chargé avec succès."); harmony.PatchAll(); } } }