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 StopBitingMyBoat v1.0.0
StopBitingMyBoat.dll
Decompiled a month agousing System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("StopBitingMyBoat")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("StopBitingMyBoat")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("72f52b69-822e-4c14-902a-cdb9805a310d")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace StopBitingMyBoat { [BepInPlugin("petri.valheim.stopbitingmyboat", "Stop Biting My Boat", "1.0.0")] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Log; public const string ModGuid = "petri.valheim.stopbitingmyboat"; public const string ModName = "Stop Biting My Boat"; public const string ModVersion = "1.0.0"; internal static ConfigEntry<bool> ModEnabled; internal static ConfigEntry<bool> DebugLogging; internal static ConfigEntry<bool> OnlyIgnoreEmptyBoats; internal static ConfigEntry<bool> PreventBoatDamage; private Harmony _harmony; private void Awake() { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable or disable Stop Biting My Boat."); DebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugLogging", false, "Enable debug logging."); OnlyIgnoreEmptyBoats = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "OnlyIgnoreEmptyBoats", false, "If enabled, Necks and Boars only ignore boats when no player is onboard."); PreventBoatDamage = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "PreventBoatDamage", true, "Prevent Necks and Boars from damaging boats if they still manage to attack."); Log = ((BaseUnityPlugin)this).Logger; _harmony = new Harmony("petri.valheim.stopbitingmyboat"); _harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Stop Biting My Boat loaded."); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } internal static void LogDebug(string message) { if (DebugLogging.Value) { Log.LogInfo((object)message); } } } } namespace StopBitingMyBoat.Patches { public static class StaticTargetFilter { public static void FilterBoatTarget(BaseAI ai, ref StaticTarget target, string source) { if (!Plugin.ModEnabled.Value || (Object)(object)ai == (Object)null || (Object)(object)target == (Object)null) { return; } string text = ((Object)((Component)ai).gameObject).name.Replace("(Clone)", ""); if (!(text != "Neck") || !(text != "Boar")) { Plugin.LogDebug("Static target found from " + source + ": AI=" + text + ", Target=" + ((Object)target).name + ", Root=" + ((Object)((Component)target).transform.root).name); Ship val = ((Component)target).GetComponentInParent<Ship>(); if ((Object)(object)val == (Object)null) { val = ((Component)((Component)target).transform.root).GetComponent<Ship>(); } if ((Object)(object)val == (Object)null) { Plugin.LogDebug(text + " static target was not detected as ship: Target=" + ((Object)target).name + ", Root=" + ((Object)((Component)target).transform.root).name); } else if (Plugin.OnlyIgnoreEmptyBoats.Value && val.HasPlayerOnboard()) { Plugin.LogDebug(text + " allowed boat target because player is onboard: " + ((Object)val).name); } else { Plugin.LogDebug(text + " ignored boat static target from " + source + ": " + ((Object)val).name); target = null; } } } } [HarmonyPatch(typeof(BaseAI), "FindClosestStaticPriorityTarget")] public static class BaseAI_FindClosestStaticPriorityTargetPatch { [HarmonyPostfix] private static void Postfix(BaseAI __instance, ref StaticTarget __result) { StaticTargetFilter.FilterBoatTarget(__instance, ref __result, "closest priority"); } } [HarmonyPatch(typeof(BaseAI), "FindRandomStaticTarget")] public static class BaseAI_FindRandomStaticTargetPatch { [HarmonyPostfix] private static void Postfix(BaseAI __instance, ref StaticTarget __result) { StaticTargetFilter.FilterBoatTarget(__instance, ref __result, "random"); } } [HarmonyPatch(typeof(WearNTear), "Damage")] public static class WearNTearDamagePatch { [HarmonyPrefix] private static bool Prefix(WearNTear __instance, HitData hit) { if (!Plugin.ModEnabled.Value) { return true; } if (!Plugin.PreventBoatDamage.Value) { return true; } if ((Object)(object)__instance == (Object)null || hit == null) { return true; } if ((Object)(object)((Component)__instance).GetComponent<Ship>() == (Object)null) { return true; } Character attacker = hit.GetAttacker(); string text = (((Object)(object)attacker != (Object)null) ? ((Object)((Component)attacker).gameObject).name.Replace("(Clone)", "") : "UNKNOWN"); if (text == "Neck" || text == "Boar") { Plugin.LogDebug("Blocked " + text + " damage to boat: " + ((Object)__instance).name); return false; } return true; } } }