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 FriendlyTrollstav v1.0.0
BepInEx/plugins/FriendlyTrollstav/FriendlyTrollstav.dll
Decompiled a week agousing System; using System.Collections.Generic; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using BepInEx; using HarmonyLib; using UnityEngine; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: AssemblyVersion("0.0.0.0")] namespace Nikki.FriendlyTrollstav; [BepInPlugin("nikki.valheim.friendlytrollstav", "Friendly Trollstav", "1.0.0")] public sealed class Plugin : BaseUnityPlugin { private Harmony harmony; private void Awake() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown harmony = new Harmony("nikki.valheim.friendlytrollstav"); harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Friendly Trollstav loaded: summoned trolls and Trollstav effects cannot target or damage players."); } private void OnDestroy() { if (harmony != null) { harmony.UnpatchSelf(); } } } public sealed class FriendlyEffect : MonoBehaviour { private void Start() { ZNetView component = ((Component)this).GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && component.IsValid() && component.IsOwner()) { component.GetZDO().Set("nikki_friendly_trollstav", true); } } } internal static class Rules { [ThreadStatic] internal static bool InTrollEffect; internal static bool IsTroll(Character character) { if ((Object)(object)character == (Object)null) { return false; } string name = ((Object)((Component)character).gameObject).name; return name == "Troll_Summoned" || name.StartsWith("Troll_Summoned(", StringComparison.Ordinal) || name.StartsWith("Troll_Summoned ", StringComparison.Ordinal); } internal static bool IsStaff(ItemData item) { return item != null && (Object)(object)item.m_dropPrefab != (Object)null && ((Object)item.m_dropPrefab).name == "StaffRedTroll"; } internal static bool Protected(Component component) { if ((Object)(object)component == (Object)null) { return false; } if ((Object)(object)component.GetComponentInParent<FriendlyEffect>() != (Object)null) { return true; } Character character = (Character)(object)((component is Character) ? component : null); if (IsTroll(character)) { return true; } ZNetView component2 = component.GetComponent<ZNetView>(); if ((Object)(object)component2 != (Object)null && component2.IsValid() && component2.GetZDO().GetBool("nikki_friendly_trollstav", false)) { return true; } FieldInfo fieldInfo = AccessTools.Field(((object)component).GetType(), "m_owner"); return fieldInfo != null && IsTroll((Character)/*isinst with value type is only supported in some contexts*/); } internal static void Mark(GameObject obj) { if ((Object)(object)obj != (Object)null && (Object)(object)obj.GetComponent<FriendlyEffect>() == (Object)null) { obj.AddComponent<FriendlyEffect>(); } } public static GameObject Spawn(GameObject prefab, Vector3 position, Quaternion rotation) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate<GameObject>(prefab, position, rotation); if (InTrollEffect) { Mark(val); } return val; } } [HarmonyPatch(typeof(BaseAI), "IsEnemy", new Type[] { typeof(Character), typeof(Character) })] internal static class NoPlayerTarget { private static bool Prefix(Character __0, Character __1, ref bool __result) { if (Rules.IsTroll(__0) && (Object)(object)__1 != (Object)null && __1.IsPlayer()) { __result = false; return false; } return true; } } [HarmonyPatch(typeof(MonsterAI), "UpdateTarget")] internal static class ClearExistingTarget { private static void Postfix(MonsterAI __instance) { if (Rules.IsTroll(((Component)__instance).GetComponent<Character>())) { object? value = AccessTools.Field(typeof(MonsterAI), "m_targetCreature").GetValue(__instance); Character val = (Character)((value is Character) ? value : null); if ((Object)(object)val != (Object)null && val.IsPlayer()) { MethodInfo methodInfo = AccessTools.Method(typeof(MonsterAI), "SetTarget", (Type[])null, (Type[])null); object[] parameters = new object[1]; methodInfo.Invoke(__instance, parameters); } } } } [HarmonyPatch(typeof(Character), "Damage")] internal static class NoPlayerDamage { private static bool Prefix(Character __instance, HitData __0) { return !__instance.IsPlayer() || (!Rules.InTrollEffect && (__0 == null || !Rules.IsTroll(__0.GetAttacker()))); } } [HarmonyPatch(typeof(Character), "RPC_Damage")] internal static class NoPlayerRPCDamage { private static bool Prefix(Character __instance, HitData __1) { return !__instance.IsPlayer() || (!Rules.InTrollEffect && (__1 == null || !Rules.IsTroll(__1.GetAttacker()))); } } [HarmonyPatch(typeof(Projectile), "Setup")] internal static class MarkProjectile { private static void Postfix(Projectile __instance, Character __0, ItemData __4, ItemData __5) { if (Rules.InTrollEffect || Rules.IsTroll(__0) || Rules.IsStaff(__4) || Rules.IsStaff(__5)) { Rules.Mark(((Component)__instance).gameObject); __instance.m_hitOwner = false; } } } [HarmonyPatch(typeof(Aoe), "Setup")] internal static class MarkArea { private static void Postfix(Aoe __instance, Character __0, ItemData __4, ItemData __5) { if (Rules.InTrollEffect || Rules.IsTroll(__0) || Rules.IsStaff(__4) || Rules.IsStaff(__5)) { Rules.Mark(((Component)__instance).gameObject); __instance.m_hitOwner = false; } } } [HarmonyPatch(typeof(Aoe), "OnHit")] internal static class NoAreaPlayerHit { private static bool Prefix(Aoe __instance, Collider __0, ref bool __result) { if ((Object)(object)__0 == (Object)null || (!Rules.InTrollEffect && !Rules.Protected((Component)(object)__instance))) { return true; } Character componentInParent = ((Component)__0).GetComponentInParent<Character>(); if ((Object)(object)componentInParent != (Object)null && componentInParent.IsPlayer()) { __result = false; return false; } return true; } } [HarmonyPatch] internal static class CaptureAttackContext { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(Projectile), "OnHit", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Projectile), "SpawnOnHit", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Aoe), "OnHit", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Aoe), "CustomFixedUpdate", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(EffectList), "Create", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Character), "OnDeath", (Type[])null, (Type[])null); } [HarmonyPriority(800)] private static void Prefix(object __instance, out bool __state) { __state = Rules.InTrollEffect; if (Rules.Protected((Component)((__instance is Component) ? __instance : null))) { Rules.InTrollEffect = true; } } private static void Finalizer(bool __state) { Rules.InTrollEffect = __state; } private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { foreach (CodeInstruction code in instructions) { MethodInfo method = code.operand as MethodInfo; if (method != null && method.DeclaringType == typeof(Object) && method.Name == "Instantiate" && method.IsGenericMethod && method.ReturnType == typeof(GameObject)) { ParameterInfo[] parameters = method.GetParameters(); if (parameters.Length == 3 && parameters[1].ParameterType == typeof(Vector3) && parameters[2].ParameterType == typeof(Quaternion)) { code.opcode = OpCodes.Call; code.operand = AccessTools.Method(typeof(Rules), "Spawn", (Type[])null, (Type[])null); } } yield return code; } } } [HarmonyPatch] internal static class MarkEarlyEffects { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(Aoe), "Awake", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Projectile), "Awake", (Type[])null, (Type[])null); } private static void Postfix(Component __instance) { if (Rules.InTrollEffect) { Rules.Mark(__instance.gameObject); } } }