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 OdinHatesLitter v1.0.6
plugins/OdinHatesLitter.dll
Decompiled a week agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("OdinHatesLitter")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("OdinHatesLitter")] [assembly: AssemblyTitle("OdinHatesLitter")] [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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace OdinHatesLitter { [HarmonyPatch(typeof(InventoryGui), "OnDropOutside")] internal static class InventoryGridDropPatch { private static void Prefix() { if (Plugin.DebugLogging.Value) { Debug.Log((object)"[OdinHatesLitter] Drag-drop outside inventory detected."); } Plugin.OnTrackedItemDropped(null, 1); } } [HarmonyPatch(typeof(ItemDrop), "DropItem")] internal static class ItemDropTrackingPatch { private static void Postfix(ItemDrop __result) { if (!((Object)(object)__result == (Object)null) && WrathTracker.PendingTrackedDrops > 0) { WrathTracker.PendingTrackedDrops--; WrathTracker.TrackedDrops.Add(__result); if (Plugin.DebugLogging.Value) { Debug.Log((object)("[OdinHatesLitter] World item tracked for pickup cleanup: " + (__result.m_itemData?.m_shared?.m_name ?? "unknown"))); } } } } [HarmonyPatch(typeof(ItemDrop), "Pickup")] internal static class ItemPickupPatch { private static void Prefix(ItemDrop __instance, Humanoid character) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)character == (Object)null) && !((Object)(object)character != (Object)(object)Player.m_localPlayer) && WrathTracker.TrackedDrops.Contains(__instance) && __instance.CanPickup(true)) { WrathTracker.TrackedDrops.Remove(__instance); Plugin.OnTrackedItemPickedUp(__instance.m_itemData, __instance.m_itemData.m_stack); if (Plugin.DebugLogging.Value) { Debug.Log((object)("[OdinHatesLitter] Tracked litter item picked back up: " + (__instance.m_itemData?.m_shared?.m_name ?? "unknown"))); } } } } internal static class LitterMessages { private static readonly string[] CalmMessages = new string[6] { "Odin frowns upon your carelessness.", "The forest remembers what you leave behind.", "Another offering to the wilderness.", "The greydwarfs appreciate your donation.", "A raven quietly records your littering.", "The spirits of Valheim are unimpressed." }; private static readonly string[] AnnoyedMessages = new string[5] { "The Allfather grows irritated by your habits.", "Hugin circles overhead in disapproval.", "The ravens have begun keeping count.", "The forest is tired of your excuses.", "Odin expected better from a warrior." }; private static readonly string[] AngryMessages = new string[5] { "Odin's patience wears thin.", "The ravens now watch your every move.", "The wilderness rejects your carelessness.", "You test the Allfather's patience.", "Valhalla whispers of your misconduct." }; private static readonly string[] FuriousMessages = new string[5] { "ODIN IS LOSING PATIENCE WITH YOU.", "The Allfather's wrath gathers strength.", "The ravens demand restitution.", "Your littering has become an insult to Valhalla.", "Soon, Odin may decide to intervene personally." }; private static readonly string[] ForgivenessMessages = new string[8] { "The Allfather's anger softens slightly.", "The ravens note your correction.", "The forest accepts your apology.", "Odin approves of your effort.", "Your honor is partially restored.", "The wilderness forgives this offense.", "A wise warrior cleans up after himself.", "The spirits seem less displeased." }; private static readonly string[] FullForgivenessMessages = new string[5] { "Odin's favor has been restored.", "The Allfather is satisfied... for now.", "The ravens close their ledger.", "Your honor is restored.", "The forest is clean once more." }; private static readonly string[] RareMessages = new string[5] { "Odin has witnessed your crime.", "The gods will remember this.", "Hugin files an official complaint.", "The ravens have seen enough.", "Your littering has been noted in the halls of Valhalla." }; internal static string GetRandomMessage(int wrath) { if (Random.Range(0, 100) < 2) { return RareMessages[Random.Range(0, RareMessages.Length)]; } string[] array = ((wrath >= 15) ? FuriousMessages : ((wrath >= 10) ? AngryMessages : ((wrath < 5) ? CalmMessages : AnnoyedMessages))); return array[Random.Range(0, array.Length)]; } internal static string GetForgivenessMessage(int wrath) { if (wrath <= 0) { return FullForgivenessMessages[Random.Range(0, FullForgivenessMessages.Length)]; } return ForgivenessMessages[Random.Range(0, ForgivenessMessages.Length)]; } } [HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")] internal static class InventoryGuiSelectedItemPatch { private static void Prefix(InventoryGui __instance, ItemData item, Modifier mod) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Invalid comparison between Unknown and I4 //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Invalid comparison between Unknown and I4 //IL_005c: Unknown result type (might be due to invalid IL or missing references) if (item == null) { return; } Container value = Traverse.Create((object)__instance).Field("m_currentContainer").GetValue<Container>(); bool flag = (int)mod == 3; bool flag2 = (int)mod == 2 && (Object)(object)value == (Object)null; if (flag || flag2) { if (Plugin.DebugLogging.Value) { Debug.Log((object)$"[OdinHatesLitter] Inventory drop detected. Modifier: {mod}"); } Plugin.OnTrackedItemDropped(item, item.m_stack); } } } [BepInPlugin("Dova.OdinHatesLitter", "OdinHatesLitter", "1.0.6")] public sealed class Plugin : BaseUnityPlugin { public const string ModGuid = "Dova.OdinHatesLitter"; public const string ModName = "OdinHatesLitter"; public const string ModVersion = "1.0.6"; internal static ConfigEntry<bool> EnableMod; internal static ConfigEntry<int> TriggerChance; internal static ConfigEntry<bool> CenterMessage; internal static ConfigEntry<bool> IgnoreDropsInsideWard; internal static ConfigEntry<bool> DebugLogging; internal static ConfigEntry<float> WardIgnoreRadius; internal static ConfigEntry<bool> EnableWrathSystem; internal static ConfigEntry<bool> ShowWrathMeter; internal static ConfigEntry<int> MaxWrath; internal static ConfigEntry<int> WrathPerDrop; internal static ConfigEntry<int> WrathRemovedOnPickup; internal static ConfigEntry<int> ForgivenessMessageChance; private Harmony _harmony = null; internal static int CurrentWrath { get; private set; } private void Awake() { //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Expected O, but got Unknown EnableMod = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableMod", true, "Enable or disable OdinHatesLitter."); TriggerChance = ((BaseUnityPlugin)this).Config.Bind<int>("General", "TriggerChance", 8, "Percent chance that a message appears when you intentionally drop an item. 0-100."); CenterMessage = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "CenterMessage", true, "If true, shows center-screen messages. If false, shows top-left messages."); IgnoreDropsInsideWard = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "IgnoreDropsInsideWard", true, "If true, Odin will not comment when you drop items inside an active ward/base area."); WardIgnoreRadius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "WardIgnoreRadius", 30f, "Radius around active wards where Odin ignores dropped items."); DebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugLogging", false, "Enable debug logs for testing item drop detection."); EnableWrathSystem = ((BaseUnityPlugin)this).Config.Bind<bool>("Wrath", "EnableWrathSystem", true, "If true, dropped items increase Odin's wrath."); ShowWrathMeter = ((BaseUnityPlugin)this).Config.Bind<bool>("Wrath", "ShowWrathMeter", true, "If true, shows Odin's wrath meter whenever wrath changes."); MaxWrath = ((BaseUnityPlugin)this).Config.Bind<int>("Wrath", "MaxWrath", 40, "Maximum wrath value."); WrathPerDrop = ((BaseUnityPlugin)this).Config.Bind<int>("Wrath", "WrathPerDrop", 1, "Wrath added when an item is dropped outside a ward/base area."); WrathRemovedOnPickup = ((BaseUnityPlugin)this).Config.Bind<int>("Wrath", "WrathRemovedOnPickup", 1, "Wrath removed when a tracked dropped item is picked back up."); ForgivenessMessageChance = ((BaseUnityPlugin)this).Config.Bind<int>("Wrath", "ForgivenessMessageChance", 25, "Percent chance to show a forgiveness message when picking up tracked litter. 0-100."); _harmony = new Harmony("Dova.OdinHatesLitter"); _harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"OdinHatesLitter 1.0.6 loaded."); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } internal static void OnTrackedItemDropped(ItemData item, int amount) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) if (!EnableMod.Value) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } if (IgnoreDropsInsideWard.Value && IsInsidePlayerBaseArea(((Component)localPlayer).transform.position)) { if (DebugLogging.Value) { Debug.Log((object)"[OdinHatesLitter] Drop ignored because player is inside a ward/base area."); } } else { WrathTracker.PendingTrackedDrops++; AddWrath(item, amount); TryShowLitterMessage(item, amount); } } internal static void OnTrackedItemPickedUp(ItemData item, int amount) { RemoveWrath(item, amount); Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { int num = Mathf.Clamp(ForgivenessMessageChance.Value, 0, 100); int num2 = Random.Range(0, 100); if (DebugLogging.Value) { Debug.Log((object)$"[OdinHatesLitter] Pickup forgiveness roll. Chance={num}, Roll={num2}"); } if (num > 0 && num2 < num) { ((Character)localPlayer).Message((MessageType)2, LitterMessages.GetForgivenessMessage(CurrentWrath), 0, (Sprite)null); } } } private static void AddWrath(ItemData item, int amount) { if (EnableWrathSystem.Value) { CurrentWrath = Mathf.Clamp(CurrentWrath + Mathf.Max(0, WrathPerDrop.Value), 0, Mathf.Max(0, MaxWrath.Value)); if (DebugLogging.Value) { Debug.Log((object)string.Format("[OdinHatesLitter] Wrath increased to {0}/{1}. Item={2}, Amount={3}", CurrentWrath, MaxWrath.Value, item?.m_shared?.m_name ?? "unknown", amount)); } ShowWrathMeterMessage(); } } private static void RemoveWrath(ItemData item, int amount) { if (EnableWrathSystem.Value) { CurrentWrath = Mathf.Clamp(CurrentWrath - Mathf.Max(0, WrathRemovedOnPickup.Value), 0, Mathf.Max(0, MaxWrath.Value)); if (DebugLogging.Value) { Debug.Log((object)string.Format("[OdinHatesLitter] Wrath decreased to {0}/{1}. Item={2}, Amount={3}", CurrentWrath, MaxWrath.Value, item?.m_shared?.m_name ?? "unknown", amount)); } ShowWrathMeterMessage(); } } private static void ShowWrathMeterMessage() { if (ShowWrathMeter.Value) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { ((Character)localPlayer).Message((MessageType)1, $"Odin's Wrath: {CurrentWrath}/{MaxWrath.Value}", 0, (Sprite)null); } } } private static void TryShowLitterMessage(ItemData item, int amount) { //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.Clamp(TriggerChance.Value, 0, 100); int num2 = Random.Range(0, 100); if (DebugLogging.Value) { Debug.Log((object)string.Format("[OdinHatesLitter] Drop detected. Chance={0}, Roll={1}, Wrath={2}, Item={3}, Amount={4}", num, num2, CurrentWrath, item?.m_shared?.m_name ?? "unknown", amount)); } if (num > 0 && num2 < num) { string randomMessage = LitterMessages.GetRandomMessage(CurrentWrath); MessageType val = (MessageType)((!CenterMessage.Value) ? 1 : 2); ((Character)Player.m_localPlayer).Message(val, randomMessage, 0, (Sprite)null); } } private static bool IsInsidePlayerBaseArea(Vector3 position) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return Object.op_Implicit((Object)(object)EffectArea.IsPointInsideArea(position, (Type)4, WardIgnoreRadius.Value)); } } internal static class WrathTracker { internal static int PendingTrackedDrops = 0; internal static readonly HashSet<ItemDrop> TrackedDrops = new HashSet<ItemDrop>(); } }