using System; using System.Collections.Generic; using 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 Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("GunnrCompanion")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("GunnrCompanion")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("9a682378-eb40-46a9-88f7-e0c77670cd0c")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] namespace GunnrCompanion; [BepInPlugin("ulf.valheim.gunnrcompanion", "Gunnr Companion", "0.1.15-rune-preview")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { [HarmonyPatch] private static class GunnrRuneUsePatch { private static IEnumerable TargetMethods() { MethodInfo[] methods = typeof(Humanoid).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo[] array = methods; foreach (MethodInfo method in array) { if (method != null && method.Name == "UseItem") { yield return method; } } } private static bool Prefix(Humanoid __instance, object[] __args) { if ((Object)(object)instance == (Object)null || (Object)(object)__instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null) { return true; } if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return true; } ItemData item = null; if (__args != null) { foreach (object obj in __args) { ItemData val = (ItemData)((obj is ItemData) ? obj : null); if (val != null) { item = val; break; } } } if (!IsGunnrRuneItem(item)) { return true; } instance.HandleGunnrRuneUse(Player.m_localPlayer); return false; } } [HarmonyPatch(typeof(Character), "Damage")] private static class CharacterDamagePatch { private static bool Prefix(Character __instance) { if (invulnerable != null && invulnerable.Value && IsGunnr(__instance)) { return false; } return true; } } private const string ModGuid = "ulf.valheim.gunnrcompanion"; private const string ModName = "Gunnr Companion"; private const string ModVersion = "0.1.15-rune-preview"; private const string WolfPrefabName = "Wolf"; private const string CompanionMarkerKey = "Ulf_Gunnr_Companion"; private const string CompanionNameKey = "Ulf_Gunnr_Name"; private const string RunePrefabName = "GunnrsRune"; private const string RuneDisplayName = "Gunnr's Rune"; private const string RuneDescription = "Bound by oath, carried by blood. Use to call Gunnr to your side or send her beyond sight."; private const string FireAuraChildName = "Ulf_Gunnr_FireAura"; private const string FrostAuraChildName = "Ulf_Gunnr_FrostAura"; private const string SpiritAuraChildName = "Ulf_Gunnr_SpiritAura"; private const string GlowAuraChildName = "Ulf_Gunnr_GlowAura"; private static ConfigEntry enableGunnr; private static ConfigEntry companionName; private static ConfigEntry companionLevel; private static ConfigEntry invulnerable; private static ConfigEntry spawnGunnrNow; private static ConfigEntry summonGunnrNow; private static ConfigEntry spawnIfMissing; private static ConfigEntry manualSpawnOnly; private static ConfigEntry removeDuplicates; private static ConfigEntry spawnDistance; private static ConfigEntry teleportDistance; private static ConfigEntry enableGunnrRune; private static ConfigEntry giveRuneIfMissing; private static ConfigEntry gunnrStored; private static ConfigEntry storedGunnrHealth; private static ConfigEntry runeUseCooldown; private static ConfigEntry wolfPupMode; private static ConfigEntry wolfPupScale; private static ConfigEntry adultWolfScale; private static ConfigEntry avoidWaterSpawn; private static ConfigEntry waterHeightBuffer; private static ConfigEntry enableAuras; private static ConfigEntry fireAura; private static ConfigEntry frostAura; private static ConfigEntry spiritAura; private static ConfigEntry glowAura; private static ConfigEntry fireAuraPrefab; private static ConfigEntry frostAuraPrefab; private static ConfigEntry spiritAuraPrefab; private static ConfigEntry auraYOffset; private static ConfigEntry auraScale; private static ConfigEntry glowRange; private static ConfigEntry glowIntensity; private static ConfigEntry glowColorHex; private static ManualLogSource log; private static readonly string[] FireAuraCandidates = new string[6] { "vfx_burning", "vfx_Burning", "vfx_fire", "vfx_Fire", "vfx_fire_addfuel", "vfx_FireAddFuel" }; private static readonly string[] FrostAuraCandidates = new string[6] { "vfx_freeze", "vfx_Freezing", "vfx_frost", "vfx_Frost", "vfx_ColdBall_Hit", "vfx_frost_staff_shield" }; private static readonly string[] SpiritAuraCandidates = new string[6] { "vfx_StaffShield", "vfx_staff_shield", "vfx_DvergerMage_Mistile_attack", "vfx_eitrgod_explosion", "vfx_GhostDeath", "vfx_WraithDeath" }; private static Plugin instance; private readonly Harmony harmony = new Harmony("ulf.valheim.gunnrcompanion"); private float nextCompanionCheckTime; private float nextRuneUseTime; private void Awake() { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Expected O, but got Unknown //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Expected O, but got Unknown //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Expected O, but got Unknown //IL_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Expected O, but got Unknown //IL_030d: Unknown result type (might be due to invalid IL or missing references) //IL_0317: Expected O, but got Unknown //IL_036a: Unknown result type (might be due to invalid IL or missing references) //IL_0374: Expected O, but got Unknown //IL_04b3: Unknown result type (might be due to invalid IL or missing references) //IL_04bd: Expected O, but got Unknown //IL_04f0: Unknown result type (might be due to invalid IL or missing references) //IL_04fa: Expected O, but got Unknown //IL_052d: Unknown result type (might be due to invalid IL or missing references) //IL_0537: Expected O, but got Unknown //IL_056a: Unknown result type (might be due to invalid IL or missing references) //IL_0574: Expected O, but got Unknown instance = this; log = ((BaseUnityPlugin)this).Logger; enableGunnr = ((BaseUnityPlugin)this).Config.Bind("Gunnr", "Enable Gunnr", true, "Turns the Gunnr companion wolf on or off."); companionName = ((BaseUnityPlugin)this).Config.Bind("Gunnr", "Companion Name", "Gunnr", "The custom name used for the companion wolf."); companionLevel = ((BaseUnityPlugin)this).Config.Bind("Gunnr", "Wolf Level", 3, new ConfigDescription("Wolf level. 1 = no star, 2 = one star, 3 = two star.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 3), Array.Empty())); invulnerable = ((BaseUnityPlugin)this).Config.Bind("Gunnr", "Invulnerable", true, "If true, Gunnr ignores incoming damage."); spawnGunnrNow = ((BaseUnityPlugin)this).Config.Bind("Gunnr", "Spawn Gunnr Now", false, "Toggle this on to manually spawn Gunnr near you. It automatically turns itself back off after use."); summonGunnrNow = ((BaseUnityPlugin)this).Config.Bind("Gunnr", "Summon Gunnr Now", false, "Toggle this on to move the existing loaded Gunnr to you without spawning a duplicate. It automatically turns itself back off after use."); spawnIfMissing = ((BaseUnityPlugin)this).Config.Bind("Gunnr", "Spawn If Missing", false, "If true, Gunnr is spawned again whenever the mod cannot find her. Leave this off to prevent accidental duplicates."); manualSpawnOnly = ((BaseUnityPlugin)this).Config.Bind("Gunnr", "Manual Spawn Only", true, "If true, Gunnr only spawns when Spawn Gunnr Now is toggled. This overrides Spawn If Missing and prevents accidental repeated spawn loops."); removeDuplicates = ((BaseUnityPlugin)this).Config.Bind("Gunnr", "Remove Duplicate Gunnrs", true, "If true, when more than one Gunnr is loaded, the closest one is kept and the extras are removed."); spawnDistance = ((BaseUnityPlugin)this).Config.Bind("Gunnr", "Spawn Distance", 2.5f, new ConfigDescription("How far from the player Gunnr appears when spawned or teleported.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 10f), Array.Empty())); teleportDistance = ((BaseUnityPlugin)this).Config.Bind("Gunnr", "Teleport Back Distance", 45f, new ConfigDescription("If Gunnr is farther than this from the player, she is moved back near the player. Set to 0 to disable.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 200f), Array.Empty())); enableGunnrRune = ((BaseUnityPlugin)this).Config.Bind("Gunnr's Rune", "Enable Gunnr's Rune", true, "Adds Gunnr's Rune as a reusable inventory item. Use it to summon or stow Gunnr without consuming or equipping the item."); giveRuneIfMissing = ((BaseUnityPlugin)this).Config.Bind("Gunnr's Rune", "Give Rune If Missing", true, "If true, the mod gives the player Gunnr's Rune when it is missing from their inventory."); gunnrStored = ((BaseUnityPlugin)this).Config.Bind("Gunnr's Rune", "Gunnr Is Stored", false, "Internal saved state. True means Gunnr is stored inside Gunnr's Rune and should not exist as a live wolf until summoned."); storedGunnrHealth = ((BaseUnityPlugin)this).Config.Bind("Gunnr's Rune", "Stored Gunnr Health", 0f, "Internal saved state. The health Gunnr had when stored. 0 means use default health when released."); runeUseCooldown = ((BaseUnityPlugin)this).Config.Bind("Gunnr's Rune", "Rune Use Cooldown", 1f, new ConfigDescription("Seconds before Gunnr's Rune can be used again.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 30f), Array.Empty())); wolfPupMode = ((BaseUnityPlugin)this).Config.Bind("Appearance", "Wolf Pup Mode", false, "If true, Gunnr keeps her adult wolf companion behavior but is visually scaled down to look like a wolf pup."); wolfPupScale = ((BaseUnityPlugin)this).Config.Bind("Appearance", "Wolf Pup Scale", 0.55f, new ConfigDescription("Visual scale used when Wolf Pup Mode is on. 0.5 to 0.65 usually looks pup-sized.", (AcceptableValueBase)(object)new AcceptableValueRange(0.25f, 1f), Array.Empty())); adultWolfScale = ((BaseUnityPlugin)this).Config.Bind("Appearance", "Adult Wolf Scale", 1f, new ConfigDescription("Visual scale used when Wolf Pup Mode is off. Leave at 1 for normal wolf size.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 2f), Array.Empty())); avoidWaterSpawn = ((BaseUnityPlugin)this).Config.Bind("Safety", "Avoid Water Spawn Points", true, "If true, the mod tries to spawn or teleport Gunnr only on ground above water. This is water safety only; there is no vehicle logic."); waterHeightBuffer = ((BaseUnityPlugin)this).Config.Bind("Safety", "Water Height Buffer", 0.3f, new ConfigDescription("Extra height used when deciding whether a spawn point is too close to water.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 3f), Array.Empty())); enableAuras = ((BaseUnityPlugin)this).Config.Bind("Auras", "Enable Aura System", true, "Master switch for all Gunnr aura visuals. These are visual only and do not add damage."); fireAura = ((BaseUnityPlugin)this).Config.Bind("Auras - Fire", "Enable Fire Aura", false, "Adds a fire visual aura to Gunnr. Visual only."); fireAuraPrefab = ((BaseUnityPlugin)this).Config.Bind("Auras - Fire", "Fire Aura Prefab", "Auto", "Prefab name for the fire aura. Leave as Auto to try known fire VFX names."); frostAura = ((BaseUnityPlugin)this).Config.Bind("Auras - Frost/Snow", "Enable Frost Snow Aura", false, "Adds a frost/snow visual aura to Gunnr. Visual only."); frostAuraPrefab = ((BaseUnityPlugin)this).Config.Bind("Auras - Frost/Snow", "Frost Snow Aura Prefab", "Auto", "Prefab name for the frost/snow aura. Leave as Auto to try known frost VFX names."); spiritAura = ((BaseUnityPlugin)this).Config.Bind("Auras - Spirit", "Enable Spirit Aura", false, "Adds a spirit/eitr-style visual aura to Gunnr. Visual only."); spiritAuraPrefab = ((BaseUnityPlugin)this).Config.Bind("Auras - Spirit", "Spirit Aura Prefab", "Auto", "Prefab name for the spirit aura. Leave as Auto to try known spirit/eitr VFX names."); glowAura = ((BaseUnityPlugin)this).Config.Bind("Auras - Glow", "Enable Glow Aura", false, "Adds a point light glow to Gunnr. Visual only."); auraYOffset = ((BaseUnityPlugin)this).Config.Bind("Auras - Shared", "Aura Vertical Offset", 0.35f, new ConfigDescription("Moves prefab aura effects up or down on Gunnr.", (AcceptableValueBase)(object)new AcceptableValueRange(-2f, 3f), Array.Empty())); auraScale = ((BaseUnityPlugin)this).Config.Bind("Auras - Shared", "Aura Scale", 1f, new ConfigDescription("Scales prefab aura effects attached to Gunnr.", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 5f), Array.Empty())); glowRange = ((BaseUnityPlugin)this).Config.Bind("Auras - Glow", "Glow Range", 5f, new ConfigDescription("How far Gunnr's glow light reaches.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 20f), Array.Empty())); glowIntensity = ((BaseUnityPlugin)this).Config.Bind("Auras - Glow", "Glow Intensity", 1.25f, new ConfigDescription("Brightness of Gunnr's glow light.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 8f), Array.Empty())); glowColorHex = ((BaseUnityPlugin)this).Config.Bind("Auras - Glow", "Glow Color Hex", "#9ECFFF", "Glow color as a hex value, for example #9ECFFF, #FF8A2A, or #FFFFFF."); if (enableGunnrRune.Value) { PrefabManager.OnVanillaPrefabsAvailable += AddGunnrRuneItem; } harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Gunnr Companion loaded."); } private void OnDestroy() { PrefabManager.OnVanillaPrefabsAvailable -= AddGunnrRuneItem; harmony.UnpatchSelf(); if ((Object)(object)instance == (Object)(object)this) { instance = null; } } private void Update() { if (!enableGunnr.Value) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)ZNetScene.instance == (Object)null) { return; } EnsureGunnrRuneInInventory(localPlayer); if (Time.time < nextCompanionCheckTime) { return; } nextCompanionCheckTime = Time.time + 2f; List list = FindAllGunnrs(); Character primaryGunnr = GetPrimaryGunnr(localPlayer, list); if (removeDuplicates.Value && list.Count > 1) { RemoveExtraGunnrs(list, primaryGunnr); } if (summonGunnrNow.Value) { summonGunnrNow.Value = false; if (gunnrStored.Value) { ReleaseStoredGunnr(localPlayer); return; } if ((Object)(object)primaryGunnr == (Object)null) { SpawnGunnr(localPlayer); return; } SummonExistingGunnr(localPlayer, primaryGunnr); } if (spawnGunnrNow.Value) { spawnGunnrNow.Value = false; if (gunnrStored.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Spawn Gunnr Now was pressed, but " + companionName.Value + " is currently stored inside Gunnr's Rune. Use the rune or Summon Gunnr Now to release her.")); return; } if (!CanSpawnOrTeleportNow(localPlayer)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Spawn Gunnr Now was pressed, but " + companionName.Value + " was not spawned because water safety is active.")); return; } if ((Object)(object)primaryGunnr == (Object)null) { SpawnGunnr(localPlayer); return; } ((BaseUnityPlugin)this).Logger.LogInfo((object)("Spawn Gunnr Now was pressed, but " + companionName.Value + " already exists. No duplicate was spawned.")); } if (gunnrStored.Value) { if ((Object)(object)primaryGunnr != (Object)null) { ((BaseUnityPlugin)this).Logger.LogInfo((object)(companionName.Value + " is marked as stored, but a live Gunnr was found. Removing the live copy to prevent duplicates.")); RemoveGunnr(primaryGunnr); } } else if ((Object)(object)primaryGunnr == (Object)null) { if (!manualSpawnOnly.Value && spawnIfMissing.Value && CanSpawnOrTeleportNow(localPlayer)) { SpawnGunnr(localPlayer); } } else { ConfigureGunnr(((Component)primaryGunnr).gameObject, primaryGunnr); if (CanSpawnOrTeleportNow(localPlayer)) { MaintainGunnr(localPlayer, primaryGunnr); } } } private void AddGunnrRuneItem() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown try { ItemConfig val = new ItemConfig(); val.Name = "Gunnr's Rune"; val.Description = "Bound by oath, carried by blood. Use to call Gunnr to your side or send her beyond sight."; val.Amount = 1; val.CraftingStation = CraftingStations.Workbench; val.AddRequirement("TrophyWolf", 1, 0); val.AddRequirement("BoneFragments", 5, 0); val.AddRequirement("Resin", 5, 0); CustomItem val2 = new CustomItem("GunnrsRune", "Wishbone", val); ItemManager.Instance.AddItem(val2); ConfigureRunePrefab(val2.ItemPrefab); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Gunnr's Rune item registered."); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed to register Gunnr's Rune: " + ex.Message)); } finally { PrefabManager.OnVanillaPrefabsAvailable -= AddGunnrRuneItem; } } private static void ConfigureRunePrefab(GameObject runePrefab) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)runePrefab == (Object)null)) { ItemDrop component = runePrefab.GetComponent(); if (!((Object)(object)component == (Object)null) && component.m_itemData != null && component.m_itemData.m_shared != null) { SharedData shared = component.m_itemData.m_shared; shared.m_name = "Gunnr's Rune"; shared.m_description = "Bound by oath, carried by blood. Use to call Gunnr to your side or send her beyond sight."; shared.m_itemType = (ItemType)2; shared.m_maxStackSize = 1; shared.m_useDurability = false; shared.m_destroyBroken = false; TrySetObjectMember(shared, "m_consumeStatusEffect", null); TrySetObjectMember(shared, "m_equipStatusEffect", null); } } } private void EnsureGunnrRuneInInventory(Player player) { if ((Object)(object)player == (Object)null || !enableGunnrRune.Value || !giveRuneIfMissing.Value) { return; } Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory != null && !InventoryHasGunnrRune(inventory)) { GameObject gunnrRunePrefab = GetGunnrRunePrefab(); if (!((Object)(object)gunnrRunePrefab == (Object)null) && TryAddItemToInventory(inventory, gunnrRunePrefab)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Added Gunnr's Rune to the player inventory."); } } } private static bool TryAddItemToInventory(Inventory inventory, GameObject itemPrefab) { if (inventory == null || (Object)(object)itemPrefab == (Object)null) { return false; } MethodInfo[] methods = typeof(Inventory).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo[] array = methods; foreach (MethodInfo methodInfo in array) { if (methodInfo == null || methodInfo.Name != "AddItem") { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length != 2 || !(parameters[0].ParameterType == typeof(GameObject)) || !(parameters[1].ParameterType == typeof(int))) { continue; } try { object obj = methodInfo.Invoke(inventory, new object[2] { itemPrefab, 1 }); if (obj is bool result) { return result; } return obj != null; } catch { return false; } } return false; } private static GameObject GetGunnrRunePrefab() { if ((Object)(object)ObjectDB.instance != (Object)null) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("GunnrsRune"); if ((Object)(object)itemPrefab != (Object)null) { return itemPrefab; } } if ((Object)(object)ZNetScene.instance != (Object)null) { GameObject prefab = ZNetScene.instance.GetPrefab("GunnrsRune"); if ((Object)(object)prefab != (Object)null) { return prefab; } } return null; } private static bool InventoryHasGunnrRune(Inventory inventory) { if (inventory == null) { return false; } foreach (ItemData allItem in inventory.GetAllItems()) { if (IsGunnrRuneItem(allItem)) { return true; } } return false; } private void HandleGunnrRuneUse(Player player) { if (!((Object)(object)player == (Object)null) && enableGunnrRune.Value && !(Time.time < nextRuneUseTime)) { nextRuneUseTime = Time.time + Mathf.Max(0f, runeUseCooldown.Value); List list = FindAllGunnrs(); Character primaryGunnr = GetPrimaryGunnr(player, list); if (removeDuplicates.Value && list.Count > 1) { RemoveExtraGunnrs(list, primaryGunnr); } if (gunnrStored.Value) { ReleaseStoredGunnr(player); } else if ((Object)(object)primaryGunnr != (Object)null) { StoreGunnrInRune(primaryGunnr); } else { ReleaseStoredGunnr(player); } } } private void StoreGunnrInRune(Character gunnr) { if (!((Object)(object)gunnr == (Object)null)) { storedGunnrHealth.Value = GetCharacterHealth(gunnr); gunnrStored.Value = true; RemoveGunnr(gunnr); ((BaseUnityPlugin)this).Logger.LogInfo((object)(companionName.Value + " was bound into Gunnr's Rune.")); MessageLocalPlayer(companionName.Value + " returns to the rune."); } } private void ReleaseStoredGunnr(Player player) { if ((Object)(object)player == (Object)null) { return; } if (!CanSpawnOrTeleportNow(player)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Gunnr's Rune was used, but " + companionName.Value + " cannot be released here because water safety is active.")); MessageLocalPlayer(companionName.Value + " cannot answer here."); return; } Character val = SpawnGunnr(player); if ((Object)(object)val == (Object)null) { MessageLocalPlayer(companionName.Value + " cannot answer here."); return; } if (storedGunnrHealth.Value > 0f) { TrySetCharacterHealth(val, storedGunnrHealth.Value); } gunnrStored.Value = false; storedGunnrHealth.Value = 0f; ((BaseUnityPlugin)this).Logger.LogInfo((object)(companionName.Value + " was released from Gunnr's Rune.")); MessageLocalPlayer(companionName.Value + " answers the rune."); } private static bool IsGunnrRuneItem(ItemData item) { if (item == null) { return false; } if ((Object)(object)item.m_dropPrefab != (Object)null) { string name = ((Object)item.m_dropPrefab).name; if (!string.IsNullOrEmpty(name) && name.StartsWith("GunnrsRune", StringComparison.Ordinal)) { return true; } } if (item.m_shared != null) { return item.m_shared.m_name == "Gunnr's Rune" || item.m_shared.m_name == "$item_gunnrsrune"; } return false; } private static float GetCharacterHealth(Character character) { if ((Object)(object)character == (Object)null) { return 0f; } object raw = InvokeInstanceMethodWithResult(character, "GetHealth"); if (TryConvertToFloat(raw, out var value)) { return value; } return 0f; } private static void TrySetCharacterHealth(Character character, float health) { if (!((Object)(object)character == (Object)null) && !(health <= 0f)) { InvokeInstanceMethod(character, "SetHealth", health); } } private static void MessageLocalPlayer(string message) { if (!((Object)(object)Player.m_localPlayer == (Object)null) && !string.IsNullOrEmpty(message)) { InvokeInstanceMethod(Player.m_localPlayer, "Message", (object)(MessageType)2, message, 0, null); } } private bool CanSpawnOrTeleportNow(Player player) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return false; } if (avoidWaterSpawn.Value && IsPositionOverWater(((Component)player).transform.position)) { return false; } return true; } private Character SpawnGunnr(Player player) { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || (Object)(object)ZNetScene.instance == (Object)null) { return null; } GameObject prefab = ZNetScene.instance.GetPrefab("Wolf"); if ((Object)(object)prefab == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Could not find Wolf prefab. Gunnr was not spawned."); return null; } if (!TryGetCompanionPositionNearPlayer(player, out var position)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Could not find a safe non-water spawn point for " + companionName.Value + ". Spawn skipped.")); return null; } Quaternion val = Quaternion.LookRotation(((Component)player).transform.forward); GameObject val2 = Object.Instantiate(prefab, position, val); ((Object)val2).name = "Gunnr_Companion"; Character component = val2.GetComponent(); if ((Object)(object)component == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Spawned Wolf prefab had no Character component."); return null; } MarkAsGunnr(component); ConfigureGunnr(val2, component); gunnrStored.Value = false; ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Spawned {companionName.Value} as a level {companionLevel.Value} wolf."); return component; } private void MaintainGunnr(Player player, Character gunnr) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || (Object)(object)gunnr == (Object)null) { return; } ConfigureGunnr(((Component)gunnr).gameObject, gunnr); if (teleportDistance.Value <= 0f) { return; } float num = Vector3.Distance(((Component)player).transform.position, ((Component)gunnr).transform.position); if (num > teleportDistance.Value) { if (!TryGetCompanionPositionNearPlayer(player, out var position)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Skipped moving " + companionName.Value + "; no safe non-water position was found.")); return; } ((Component)gunnr).transform.position = position; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Moved " + companionName.Value + " back near the player.")); } } private void SummonExistingGunnr(Player player, Character gunnr) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)player == (Object)null) && !((Object)(object)gunnr == (Object)null)) { if (!CanSpawnOrTeleportNow(player)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Summon Gunnr Now was pressed, but " + companionName.Value + " was not moved because water safety is active.")); return; } if (!TryGetCompanionPositionNearPlayer(player, out var position)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Summon Gunnr Now was pressed, but no safe land position was found."); return; } ConfigureGunnr(((Component)gunnr).gameObject, gunnr); ((Component)gunnr).transform.position = position; ((Component)gunnr).transform.rotation = Quaternion.LookRotation(((Component)player).transform.forward); StopGunnrMovement(gunnr); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Summoned existing " + companionName.Value + " to the player without spawning a duplicate.")); } } private static void StopGunnrMovement(Character gunnr) { //IL_0080: 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) if ((Object)(object)gunnr == (Object)null) { return; } InvokeInstanceMethod(gunnr, "StopMoving"); InvokeInstanceMethod(gunnr, "Stop"); Component[] componentsInChildren = ((Component)gunnr).GetComponentsInChildren(true); Component[] array = componentsInChildren; foreach (Component val in array) { if (!((Object)(object)val == (Object)null) && !(((object)val).GetType().Name != "Rigidbody")) { TrySetVector3Member(val, "velocity", Vector3.zero); TrySetVector3Member(val, "angularVelocity", Vector3.zero); } } } private static bool TrySetVector3Member(object target, string memberName, Vector3 value) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) if (target == null || string.IsNullOrEmpty(memberName)) { return false; } Type type = target.GetType(); FieldInfo field = type.GetField(memberName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(Vector3)) { field.SetValue(target, value); return true; } PropertyInfo property = type.GetProperty(memberName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.PropertyType == typeof(Vector3) && property.CanWrite) { property.SetValue(target, value, null); return true; } return false; } private bool TryGetCompanionPositionNearPlayer(Player player, out Vector3 position) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: 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_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018d: 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_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) position = Vector3.zero; if ((Object)(object)player == (Object)null) { return false; } float num = Mathf.Max(1f, spawnDistance.Value); Vector3 position2 = ((Component)player).transform.position; Vector3 right = ((Component)player).transform.right; Vector3 forward = ((Component)player).transform.forward; Vector3[] obj = new Vector3[12] { right * num + forward * 1.25f, -right * num + forward * 1.25f, right * num - forward * 1.25f, -right * num - forward * 1.25f, forward * num, -forward * num, right * num, -right * num, default(Vector3), default(Vector3), default(Vector3), default(Vector3) }; Vector3 val = right + forward; obj[8] = ((Vector3)(ref val)).normalized * num; val = -right + forward; obj[9] = ((Vector3)(ref val)).normalized * num; val = right - forward; obj[10] = ((Vector3)(ref val)).normalized * num; val = -right - forward; obj[11] = ((Vector3)(ref val)).normalized * num; Vector3[] array = (Vector3[])(object)obj; Vector3[] array2 = array; foreach (Vector3 val2 in array2) { Vector3 val3 = position2 + val2; if (avoidWaterSpawn.Value && IsPositionOverWater(val3)) { continue; } if (TrySnapToGround(val3, out var groundedPosition)) { if (!avoidWaterSpawn.Value || !IsPositionOverWater(groundedPosition)) { position = groundedPosition; return true; } } else if (!avoidWaterSpawn.Value || !IsPositionOverWater(val3)) { position = val3; return true; } } return false; } private static bool TrySnapToGround(Vector3 position, out Vector3 groundedPosition) { //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) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) groundedPosition = position; if (TryGetGroundHeight(position, out var groundHeight)) { groundedPosition = new Vector3(position.x, groundHeight + 0.15f, position.z); return true; } return false; } private static bool IsPlayerSafelyOnLand(Player player) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return false; } if (IsPositionOverWater(((Component)player).transform.position)) { return false; } if (TryGetGroundHeight(((Component)player).transform.position, out var groundHeight)) { return ((Component)player).transform.position.y >= groundHeight - 1f && ((Component)player).transform.position.y <= groundHeight + 5f; } return true; } private static bool IsPositionOverWater(Vector3 position) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (!TryGetWaterLevel(out var waterLevel)) { return false; } if (TryGetGroundHeight(position, out var groundHeight)) { return groundHeight + waterHeightBuffer.Value < waterLevel; } return position.y < waterLevel + waterHeightBuffer.Value; } private static bool TryGetGroundHeight(Vector3 position, out float groundHeight) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) groundHeight = position.y; object obj = ZoneSystem.instance; if (obj == null) { return false; } MethodInfo[] methods = obj.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo[] array = methods; foreach (MethodInfo methodInfo in array) { if (methodInfo == null || methodInfo.Name != "GetGroundHeight") { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); try { if (parameters.Length == 1 && parameters[0].ParameterType == typeof(Vector3)) { object raw = methodInfo.Invoke(obj, new object[1] { position }); if (TryConvertToFloat(raw, out groundHeight)) { return true; } } if (parameters.Length == 2 && parameters[0].ParameterType == typeof(Vector3) && parameters[1].ParameterType.IsByRef) { object[] array2 = new object[2] { position, 0f }; if ((!(methodInfo.Invoke(obj, array2) is bool flag) || flag) && TryConvertToFloat(array2[1], out groundHeight)) { return true; } } } catch { } } return false; } private static bool TryGetWaterLevel(out float waterLevel) { waterLevel = 30f; object obj = ZoneSystem.instance; if (obj == null) { return false; } string[] array = new string[3] { "m_waterLevel", "WaterLevel", "waterLevel" }; string[] array2 = array; foreach (string memberName in array2) { if (TryGetFloatMember(obj, memberName, out waterLevel)) { return true; } } waterLevel = 30f; return true; } private static bool TryGetFloatMember(object target, string memberName, out float value) { value = 0f; if (target == null || string.IsNullOrEmpty(memberName)) { return false; } Type type = target.GetType(); FieldInfo field = type.GetField(memberName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && TryConvertToFloat(field.GetValue(target), out value)) { return true; } PropertyInfo property = type.GetProperty(memberName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && TryConvertToFloat(property.GetValue(target, null), out value)) { return true; } return false; } private static bool TryConvertToFloat(object raw, out float value) { value = 0f; if (raw is float num) { value = num; return true; } if (raw is double num2) { value = (float)num2; return true; } if (raw is int num3) { value = num3; return true; } return false; } private static List FindAllGunnrs() { List list = new List(); Character[] array = Object.FindObjectsByType((FindObjectsSortMode)0); Character[] array2 = array; foreach (Character val in array2) { if (IsGunnr(val)) { list.Add(val); } } return list; } private static Character GetPrimaryGunnr(Player player, List gunnrs) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) if (gunnrs == null || gunnrs.Count == 0) { return null; } if ((Object)(object)player == (Object)null) { return gunnrs[0]; } Character val = null; float num = float.MaxValue; foreach (Character gunnr in gunnrs) { if (!((Object)(object)gunnr == (Object)null)) { float num2 = Vector3.Distance(((Component)player).transform.position, ((Component)gunnr).transform.position); if (num2 < num) { num = num2; val = gunnr; } } } return ((Object)(object)val != (Object)null) ? val : gunnrs[0]; } private void RemoveExtraGunnrs(List gunnrs, Character keepGunnr) { if (gunnrs == null || gunnrs.Count <= 1) { return; } foreach (Character gunnr in gunnrs) { if (!((Object)(object)gunnr == (Object)null) && !((Object)(object)gunnr == (Object)(object)keepGunnr)) { RemoveGunnr(gunnr); } } } private void RemoveGunnr(Character gunnr) { if (!((Object)(object)gunnr == (Object)null)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Removing duplicate Gunnr: " + ((Object)((Component)gunnr).gameObject).name)); ZNetView component = ((Component)gunnr).GetComponent(); if (!((Object)(object)component != (Object)null) || !InvokeInstanceMethod(component, "Destroy")) { Object.Destroy((Object)(object)((Component)gunnr).gameObject); } } } public static bool IsGunnr(Character character) { if ((Object)(object)character == (Object)null) { return false; } ZNetView component = ((Component)character).GetComponent(); if ((Object)(object)component == (Object)null || component.GetZDO() == null) { return false; } return component.GetZDO().GetBool("Ulf_Gunnr_Companion", false); } private static void MarkAsGunnr(Character character) { if (!((Object)(object)character == (Object)null)) { ZNetView component = ((Component)character).GetComponent(); if (!((Object)(object)component == (Object)null) && component.GetZDO() != null) { component.GetZDO().Set("Ulf_Gunnr_Companion", true); component.GetZDO().Set("Ulf_Gunnr_Name", companionName.Value); } } } private static void ConfigureGunnr(GameObject wolfObject, Character wolfCharacter) { if ((Object)(object)wolfObject == (Object)null || (Object)(object)wolfCharacter == (Object)null) { return; } MarkAsGunnr(wolfCharacter); InvokeInstanceMethod(wolfCharacter, "SetLevel", companionLevel.Value); ApplyAppearance(wolfObject); Component[] componentsInChildren = wolfObject.GetComponentsInChildren(true); Component[] array = componentsInChildren; foreach (Component val in array) { if (!((Object)(object)val == (Object)null)) { string name = ((object)val).GetType().Name; if (name == "Tameable") { InvokeInstanceMethod(val, "Tame"); InvokeInstanceMethod(val, "SetTamed", true); InvokeInstanceMethod(val, "SetName", companionName.Value); } if (name == "MonsterAI" || name == "BaseAI") { InvokeInstanceMethod(val, "SetTamed", true); } } } SetLikelyTameNameZdoValues(wolfCharacter, companionName.Value); ApplyAuras(wolfObject); } private static void ApplyAppearance(GameObject wolfObject) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)wolfObject == (Object)null) && wolfPupMode != null && wolfPupScale != null && adultWolfScale != null) { float num = (wolfPupMode.Value ? wolfPupScale.Value : adultWolfScale.Value); num = Mathf.Clamp(num, 0.25f, 2f); Vector3 val = Vector3.one * num; Vector3 val2 = wolfObject.transform.localScale - val; if (((Vector3)(ref val2)).sqrMagnitude > 0.0001f) { wolfObject.transform.localScale = val; } } } private static void ApplyAuras(GameObject wolfObject) { if (!((Object)(object)wolfObject == (Object)null)) { if (enableAuras == null || !enableAuras.Value) { RemoveAuraChild(wolfObject, "Ulf_Gunnr_FireAura"); RemoveAuraChild(wolfObject, "Ulf_Gunnr_FrostAura"); RemoveAuraChild(wolfObject, "Ulf_Gunnr_SpiritAura"); RemoveAuraChild(wolfObject, "Ulf_Gunnr_GlowAura"); } else { SyncPrefabAura(wolfObject, "Ulf_Gunnr_FireAura", fireAura.Value, fireAuraPrefab.Value, FireAuraCandidates); SyncPrefabAura(wolfObject, "Ulf_Gunnr_FrostAura", frostAura.Value, frostAuraPrefab.Value, FrostAuraCandidates); SyncPrefabAura(wolfObject, "Ulf_Gunnr_SpiritAura", spiritAura.Value, spiritAuraPrefab.Value, SpiritAuraCandidates); SyncGlowAura(wolfObject); } } } private static void SyncPrefabAura(GameObject wolfObject, string childName, bool enabled, string configuredPrefabName, string[] autoCandidates) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) Transform val = FindDirectChild(wolfObject.transform, childName); if (!enabled) { if ((Object)(object)val != (Object)null) { SafeDestroy(((Component)val).gameObject); } return; } if ((Object)(object)val != (Object)null) { val.localPosition = new Vector3(0f, auraYOffset.Value, 0f); val.localRotation = Quaternion.identity; val.localScale = Vector3.one * auraScale.Value; return; } GameObject val2 = ResolveAuraPrefab(configuredPrefabName, autoCandidates); if ((Object)(object)val2 == (Object)null) { ManualLogSource obj = log; if (obj != null) { obj.LogWarning((object)("Could not find aura prefab for " + childName + ". Set its prefab config to a valid Valheim VFX prefab name.")); } return; } GameObject val3 = Object.Instantiate(val2, wolfObject.transform); ((Object)val3).name = childName; val3.transform.localPosition = new Vector3(0f, auraYOffset.Value, 0f); val3.transform.localRotation = Quaternion.identity; val3.transform.localScale = Vector3.one * auraScale.Value; ManualLogSource obj2 = log; if (obj2 != null) { obj2.LogInfo((object)("Attached aura " + childName + " using prefab " + ((Object)val2).name + ".")); } } private static GameObject ResolveAuraPrefab(string configuredPrefabName, string[] autoCandidates) { if ((Object)(object)ZNetScene.instance == (Object)null) { return null; } if (!string.IsNullOrWhiteSpace(configuredPrefabName) && !configuredPrefabName.Equals("Auto", StringComparison.OrdinalIgnoreCase)) { GameObject prefab = ZNetScene.instance.GetPrefab(configuredPrefabName.Trim()); if ((Object)(object)prefab != (Object)null) { return prefab; } } foreach (string text in autoCandidates) { GameObject prefab2 = ZNetScene.instance.GetPrefab(text); if ((Object)(object)prefab2 != (Object)null) { return prefab2; } } return null; } private static void SyncGlowAura(GameObject wolfObject) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) Transform val = FindDirectChild(wolfObject.transform, "Ulf_Gunnr_GlowAura"); if (!glowAura.Value) { if ((Object)(object)val != (Object)null) { SafeDestroy(((Component)val).gameObject); } return; } GameObject val2; if ((Object)(object)val == (Object)null) { val2 = new GameObject("Ulf_Gunnr_GlowAura"); val2.transform.SetParent(wolfObject.transform, false); } else { val2 = ((Component)val).gameObject; } val2.transform.localPosition = new Vector3(0f, auraYOffset.Value + 0.4f, 0f); val2.transform.localRotation = Quaternion.identity; val2.transform.localScale = Vector3.one; Light val3 = val2.GetComponent(); if ((Object)(object)val3 == (Object)null) { val3 = val2.AddComponent(); } val3.type = (LightType)2; val3.range = glowRange.Value; val3.intensity = glowIntensity.Value; val3.color = ParseHexColor(glowColorHex.Value, new Color(0.62f, 0.81f, 1f, 1f)); val3.shadows = (LightShadows)0; } private static Color ParseHexColor(string hex, Color fallback) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(hex)) { return fallback; } string text = hex.Trim(); if (!text.StartsWith("#")) { text = "#" + text; } Color result = default(Color); if (ColorUtility.TryParseHtmlString(text, ref result)) { return result; } return fallback; } private static Transform FindDirectChild(Transform parent, string childName) { if ((Object)(object)parent == (Object)null || string.IsNullOrEmpty(childName)) { return null; } for (int i = 0; i < parent.childCount; i++) { Transform child = parent.GetChild(i); if ((Object)(object)child != (Object)null && ((Object)child).name == childName) { return child; } } return null; } private static void RemoveAuraChild(GameObject wolfObject, string childName) { if (!((Object)(object)wolfObject == (Object)null)) { Transform val = FindDirectChild(wolfObject.transform, childName); if ((Object)(object)val != (Object)null) { SafeDestroy(((Component)val).gameObject); } } } private static void SafeDestroy(GameObject gameObject) { if (!((Object)(object)gameObject == (Object)null)) { Object.Destroy((Object)(object)gameObject); } } private static void SetLikelyTameNameZdoValues(Character wolfCharacter, string name) { if (!((Object)(object)wolfCharacter == (Object)null) && !string.IsNullOrEmpty(name)) { ZNetView component = ((Component)wolfCharacter).GetComponent(); if (!((Object)(object)component == (Object)null) && component.GetZDO() != null) { component.GetZDO().Set("TamedName", name); component.GetZDO().Set("tamedName", name); component.GetZDO().Set("name", name); component.GetZDO().Set("Ulf_Gunnr_Name", name); } } } private static bool TrySetObjectMember(object target, string memberName, object value) { if (target == null || string.IsNullOrEmpty(memberName)) { return false; } Type type = target.GetType(); FieldInfo field = type.GetField(memberName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { field.SetValue(target, value); return true; } PropertyInfo property = type.GetProperty(memberName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.CanWrite) { property.SetValue(target, value, null); return true; } return false; } private static object InvokeInstanceMethodWithResult(object target, string methodName, params object[] args) { if (target == null || string.IsNullOrEmpty(methodName)) { return null; } Type type = target.GetType(); MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo[] array = methods; foreach (MethodInfo methodInfo in array) { if (methodInfo == null || methodInfo.Name != methodName) { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == args.Length) { try { return methodInfo.Invoke(target, args); } catch { return null; } } } return null; } private static bool InvokeInstanceMethod(object target, string methodName, params object[] args) { if (target == null || string.IsNullOrEmpty(methodName)) { return false; } Type type = target.GetType(); MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo[] array = methods; foreach (MethodInfo methodInfo in array) { if (methodInfo == null || methodInfo.Name != methodName) { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == args.Length) { try { methodInfo.Invoke(target, args); return true; } catch { return false; } } } return false; } }