Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Valgrind v1.0.1
BepInEx\plugins\Valgrind\Valgrind.dll
Decompiled 11 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Utils; using Microsoft.CodeAnalysis; using UnityEngine; using Valgrind.Configuration; using Valgrind.Logic; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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] [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 Valgrind { [BepInPlugin("com.bigai.valgrind", "Valgrind", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class ValgrindPlugin : BaseUnityPlugin { public const string PluginGUID = "com.bigai.valgrind"; public const string PluginName = "Valgrind"; public const string PluginVersion = "1.0.1"; private Harmony? _harmony; public static ValgrindPlugin Instance { get; private set; } public static ManualLogSource Log { get; private set; } private void Awake() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; try { Log.LogInfo((object)"══════════════════════════════════════════"); Log.LogInfo((object)" Valgrind v1.0.1 loading..."); Log.LogInfo((object)"══════════════════════════════════════════"); ModConfig.Initialize(((BaseUnityPlugin)this).Config); _harmony = new Harmony("com.bigai.valgrind"); _harmony.PatchAll(Assembly.GetExecutingAssembly()); Log.LogInfo((object)"[Valgrind] All Harmony patches applied successfully."); Log.LogInfo((object)"[Valgrind] Ready. Dynamic death penalty active with Jötunn ServerSync."); } catch (Exception arg) { Log.LogError((object)string.Format("[{0}] Failed to initialize: {1}", "Valgrind", arg)); } } private void OnDestroy() { Harmony? harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } Log.LogInfo((object)"[Valgrind] Unloaded."); } } } namespace Valgrind.Patches { [HarmonyPatch(typeof(Skills), "OnDeath")] public static class SkillsDeathPatch { [HarmonyPrefix] public static bool Prefix(Skills __instance) { if ((Object)(object)__instance == (Object)null) { return true; } try { SkillLossCalculator.ApplyDeathPenalty(__instance); return false; } catch (Exception arg) { ValgrindPlugin.Log.LogError((object)$"[Valgrind] Error applying dynamic death penalty: {arg}"); return true; } } } } namespace Valgrind.Logic { public static class SkillLossCalculator { public static void ApplyDeathPenalty(Skills skills) { if ((Object)(object)skills == (Object)null) { return; } List<Skill> skillList = skills.GetSkillList(); if (skillList != null && skillList.Count != 0) { CalculationMode value = ModConfig.CalculationModeEntry.Value; bool value2 = ModConfig.ResetAccumulatorOnDeath.Value; bool value3 = ModConfig.EnableDebugLogging.Value; if (value == CalculationMode.PerSkill) { ApplyPerSkillDeathPenalty(skillList, value2, value3); } else { ApplyPlayerWideDeathPenalty(skillList, value, value2, value3); } } } private static void ApplyPlayerWideDeathPenalty(List<Skill> skillList, CalculationMode mode, bool resetAccumulator, bool debug) { float num = CalculateAverageSkillLevel(skillList); float num2 = ((mode != CalculationMode.ContinuousCurve) ? GetTierLossPercent(num) : GetCurveLossPercent(num)); float num3 = Mathf.Clamp01(1f - num2 / 100f); if (debug) { ValgrindPlugin.Log.LogInfo((object)$"[SkillLossCalculator] Mode={mode}, AvgLevel={num:F2}, LossPercent={num2:F2}%, Multiplier={num3:F4}, ResetAccumulator={resetAccumulator}"); } foreach (Skill skill in skillList) { if (skill != null && skill.m_level > 0f) { float level = skill.m_level; skill.m_level = Mathf.Max(0f, skill.m_level * num3); if (resetAccumulator) { skill.m_accumulator = 0f; } if (debug) { ValgrindPlugin.Log.LogInfo((object)string.Format("[SkillLossCalculator] Skill {0}: {1:F2} -> {2:F2}", ((object)Unsafe.As<SkillType, SkillType>(ref skill.m_info?.m_skill)/*cast due to .constrained prefix*/).ToString() ?? "Unknown", level, skill.m_level)); } } } } private static void ApplyPerSkillDeathPenalty(List<Skill> skillList, bool resetAccumulator, bool debug) { if (debug) { ValgrindPlugin.Log.LogInfo((object)$"[SkillLossCalculator] Applying Per-Skill death penalty. ResetAccumulator={resetAccumulator}"); } foreach (Skill skill in skillList) { if (skill != null && skill.m_level > 0f) { float tierLossPercent = GetTierLossPercent(skill.m_level); float num = Mathf.Clamp01(1f - tierLossPercent / 100f); float level = skill.m_level; skill.m_level = Mathf.Max(0f, skill.m_level * num); if (resetAccumulator) { skill.m_accumulator = 0f; } if (debug) { ValgrindPlugin.Log.LogInfo((object)string.Format("[SkillLossCalculator] Skill {0} (Level {1:F2}): Loss {2:F2}% -> New Level {3:F2}", ((object)Unsafe.As<SkillType, SkillType>(ref skill.m_info?.m_skill)/*cast due to .constrained prefix*/).ToString() ?? "Unknown", level, tierLossPercent, skill.m_level)); } } } } public static float CalculateAverageSkillLevel(List<Skill> skillList) { if (skillList == null || skillList.Count == 0) { return 0f; } List<float> list = new List<float>(); foreach (Skill skill in skillList) { if (skill != null && skill.m_level > 0f) { list.Add(skill.m_level); } } if (list.Count == 0) { return 0f; } if (ModConfig.UseTopNSkillsOnly.Value) { int count = Mathf.Clamp(ModConfig.TopNSkillsCount.Value, 1, list.Count); return list.OrderByDescending((float l) => l).Take(count).Average(); } return list.Average(); } public static float GetTierLossPercent(float level) { if (level < 25f) { return Mathf.Clamp(ModConfig.EarlyGameLossPercent.Value, 0f, 100f); } if (level < 50f) { return Mathf.Clamp(ModConfig.MidGameLossPercent.Value, 0f, 100f); } if (level <= 75f) { return Mathf.Clamp(ModConfig.LateGameLossPercent.Value, 0f, 100f); } return Mathf.Clamp(ModConfig.EndgameLossPercent.Value, 0f, 100f); } public static float GetCurveLossPercent(float level) { float num = Mathf.Clamp(ModConfig.CurveMaxLossPercent.Value, 0f, 100f); float num2 = Mathf.Clamp(ModConfig.CurveMinLossPercent.Value, 0f, 100f); float num3 = Mathf.Clamp01(level / 100f); return Mathf.Lerp(num, num2, num3); } } } namespace Valgrind.Configuration { public enum CalculationMode { TieredBrackets, ContinuousCurve, PerSkill } public static class ModConfig { public static ConfigEntry<CalculationMode> CalculationModeEntry { get; private set; } public static ConfigEntry<bool> UseTopNSkillsOnly { get; private set; } public static ConfigEntry<int> TopNSkillsCount { get; private set; } public static ConfigEntry<bool> ResetAccumulatorOnDeath { get; private set; } public static ConfigEntry<bool> EnableDebugLogging { get; private set; } public static ConfigEntry<float> EarlyGameLossPercent { get; private set; } public static ConfigEntry<float> MidGameLossPercent { get; private set; } public static ConfigEntry<float> LateGameLossPercent { get; private set; } public static ConfigEntry<float> EndgameLossPercent { get; private set; } public static ConfigEntry<float> CurveMaxLossPercent { get; private set; } public static ConfigEntry<float> CurveMinLossPercent { get; private set; } public static void Initialize(ConfigFile config) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Expected O, but got Unknown //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Expected O, but got Unknown //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Expected O, but got Unknown //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Expected O, but got Unknown //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Expected O, but got Unknown //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Expected O, but got Unknown //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Expected O, but got Unknown //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Expected O, but got Unknown //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Expected O, but got Unknown //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Expected O, but got Unknown //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Expected O, but got Unknown //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Expected O, but got Unknown //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Expected O, but got Unknown //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Expected O, but got Unknown //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Expected O, but got Unknown CalculationModeEntry = config.Bind<CalculationMode>("1 - General", "CalculationMode", CalculationMode.TieredBrackets, new ConfigDescription("Method used to calculate dynamic skill loss on death:\n- TieredBrackets: Discrete loss % based on overall average skill level.\n- ContinuousCurve: Smooth linear/curved scaling between Max and Min loss % based on average skill.\n- PerSkill: Evaluates each skill independently against the Tiered Brackets based on its own level (instead of character average).", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); UseTopNSkillsOnly = config.Bind<bool>("1 - General", "UseTopNSkillsOnly", false, new ConfigDescription("If true, average skill level is computed using only the player's top N highest skills (reflecting primary build). If false, averages all discovered skills (level > 0).", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); TopNSkillsCount = config.Bind<int>("1 - General", "TopNSkillsCount", 5, new ConfigDescription("Number of top skills to factor into the average when UseTopNSkillsOnly is enabled.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); ResetAccumulatorOnDeath = config.Bind<bool>("1 - General", "ResetAccumulatorOnDeath", true, new ConfigDescription("If true, partial XP progress toward the next skill level is wiped to 0 on death (vanilla behavior). If false, progress toward the next level is preserved.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); EnableDebugLogging = config.Bind<bool>("1 - General", "EnableDebugLogging", false, new ConfigDescription("Enable verbose logging of skill loss calculations to the BepInEx console.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = false } })); EarlyGameLossPercent = config.Bind<float>("2 - Tiered Brackets", "EarlyGameLossPercent", 8f, new ConfigDescription("Skill loss % for skill/average levels < 25. (Vanilla baseline is 5.0%)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); MidGameLossPercent = config.Bind<float>("2 - Tiered Brackets", "MidGameLossPercent", 5f, new ConfigDescription("Skill loss % for skill/average levels between 25 and 50. (Vanilla baseline is 5.0%)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); LateGameLossPercent = config.Bind<float>("2 - Tiered Brackets", "LateGameLossPercent", 2.5f, new ConfigDescription("Skill loss % for skill/average levels between 50 and 75.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); EndgameLossPercent = config.Bind<float>("2 - Tiered Brackets", "EndgameLossPercent", 1f, new ConfigDescription("Skill loss % for skill/average levels > 75.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); CurveMaxLossPercent = config.Bind<float>("3 - Continuous Curve", "CurveMaxLossPercent", 8f, new ConfigDescription("Maximum skill loss percentage (applied at skill level 0).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); CurveMinLossPercent = config.Bind<float>("3 - Continuous Curve", "CurveMinLossPercent", 1f, new ConfigDescription("Minimum skill loss percentage (applied at skill level 100).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); } } }