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 GunnrCompanion v1.0.1
BepInEx/plugins/GunnrCompanion/GunnrCompanion.dll
Decompiled 3 days agousing 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<MethodBase> 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<bool> enableGunnr; private static ConfigEntry<string> companionName; private static ConfigEntry<int> companionLevel; private static ConfigEntry<bool> invulnerable; private static ConfigEntry<bool> spawnGunnrNow; private static ConfigEntry<bool> summonGunnrNow; private static ConfigEntry<bool> spawnIfMissing; private static ConfigEntry<bool> manualSpawnOnly; private static ConfigEntry<bool> removeDuplicates; private static ConfigEntry<float> spawnDistance; private static ConfigEntry<float> teleportDistance; private static ConfigEntry<bool> enableGunnrRune; private static ConfigEntry<bool> giveRuneIfMissing; private static ConfigEntry<bool> gunnrStored; private static ConfigEntry<float> storedGunnrHealth; private static ConfigEntry<float> runeUseCooldown; private static ConfigEntry<bool> wolfPupMode; private static ConfigEntry<float> wolfPupScale; private static ConfigEntry<float> adultWolfScale; private static ConfigEntry<bool> avoidWaterSpawn; private static ConfigEntry<float> waterHeightBuffer; private static ConfigEntry<bool> enableAuras; private static ConfigEntry<bool> fireAura; private static ConfigEntry<bool> frostAura; private static ConfigEntry<bool> spiritAura; private static ConfigEntry<bool> glowAura; private static ConfigEntry<string> fireAuraPrefab; private static ConfigEntry<string> frostAuraPrefab; private static ConfigEntry<string> spiritAuraPrefab; private static ConfigEntry<float> auraYOffset; private static ConfigEntry<float> auraScale; private static ConfigEntry<float> glowRange; private static ConfigEntry<float> glowIntensity; private static ConfigEntry<string> 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<bool>("Gunnr", "Enable Gunnr", true, "Turns the Gunnr companion wolf on or off."); companionName = ((BaseUnityPlugin)this).Config.Bind<string>("Gunnr", "Companion Name", "Gunnr", "The custom name used for the companion wolf."); companionLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Gunnr", "Wolf Level", 3, new ConfigDescription("Wolf level. 1 = no star, 2 = one star, 3 = two star.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 3), Array.Empty<object>())); invulnerable = ((BaseUnityPlugin)this).Config.Bind<bool>("Gunnr", "Invulnerable", true, "If true, Gunnr ignores incoming damage."); spawnGunnrNow = ((BaseUnityPlugin)this).Config.Bind<bool>("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<bool>("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<bool>("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<bool>("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<bool>("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<float>("Gunnr", "Spawn Distance", 2.5f, new ConfigDescription("How far from the player Gunnr appears when spawned or teleported.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>())); teleportDistance = ((BaseUnityPlugin)this).Config.Bind<float>("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<float>(0f, 200f), Array.Empty<object>())); enableGunnrRune = ((BaseUnityPlugin)this).Config.Bind<bool>("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<bool>("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<bool>("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<float>("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<float>("Gunnr's Rune", "Rune Use Cooldown", 1f, new ConfigDescription("Seconds before Gunnr's Rune can be used again.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f), Array.Empty<object>())); wolfPupMode = ((BaseUnityPlugin)this).Config.Bind<bool>("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<float>("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<float>(0.25f, 1f), Array.Empty<object>())); adultWolfScale = ((BaseUnityPlugin)this).Config.Bind<float>("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<float>(0.5f, 2f), Array.Empty<object>())); avoidWaterSpawn = ((BaseUnityPlugin)this).Config.Bind<bool>("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<float>("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<float>(0f, 3f), Array.Empty<object>())); enableAuras = ((BaseUnityPlugin)this).Config.Bind<bool>("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<bool>("Auras - Fire", "Enable Fire Aura", false, "Adds a fire visual aura to Gunnr. Visual only."); fireAuraPrefab = ((BaseUnityPlugin)this).Config.Bind<string>("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<bool>("Auras - Frost/Snow", "Enable Frost Snow Aura", false, "Adds a frost/snow visual aura to Gunnr. Visual only."); frostAuraPrefab = ((BaseUnityPlugin)this).Config.Bind<string>("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<bool>("Auras - Spirit", "Enable Spirit Aura", false, "Adds a spirit/eitr-style visual aura to Gunnr. Visual only."); spiritAuraPrefab = ((BaseUnityPlugin)this).Config.Bind<string>("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<bool>("Auras - Glow", "Enable Glow Aura", false, "Adds a point light glow to Gunnr. Visual only."); auraYOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Auras - Shared", "Aura Vertical Offset", 0.35f, new ConfigDescription("Moves prefab aura effects up or down on Gunnr.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-2f, 3f), Array.Empty<object>())); auraScale = ((BaseUnityPlugin)this).Config.Bind<float>("Auras - Shared", "Aura Scale", 1f, new ConfigDescription("Scales prefab aura effects attached to Gunnr.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>())); glowRange = ((BaseUnityPlugin)this).Config.Bind<float>("Auras - Glow", "Glow Range", 5f, new ConfigDescription("How far Gunnr's glow light reaches.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 20f), Array.Empty<object>())); glowIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Auras - Glow", "Glow Intensity", 1.25f, new ConfigDescription("Brightness of Gunnr's glow light.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 8f), Array.Empty<object>())); glowColorHex = ((BaseUnityPlugin)this).Config.Bind<string>("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<Character> 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<ItemDrop>(); 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<Character> 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<GameObject>(prefab, position, val); ((Object)val2).name = "Gunnr_Companion"; Character component = val2.GetComponent<Character>(); 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<Component>(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<Character> FindAllGunnrs() { List<Character> list = new List<Character>(); Character[] array = Object.FindObjectsByType<Character>((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<Character> 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<Character> 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<ZNetView>(); 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<ZNetView>(); 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<ZNetView>(); 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<Component>(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<GameObject>(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<Light>(); if ((Object)(object)val3 == (Object)null) { val3 = val2.AddComponent<Light>(); } 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<ZNetView>(); 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; } }