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 OdinRegalia v1.0.0
OdinRegalia.dll
Decompiled 2 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using Gungnir; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("OdinRegalia")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("OdinRegalia")] [assembly: AssemblyTitle("OdinRegalia")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace OdinArmour { [BepInPlugin("com.crasssam.odinarmour", "Odin's Regalia", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class OdinArmourPlugin : BaseUnityPlugin { public const string Guid = "com.crasssam.odinarmour"; public const string Version = "1.0.0"; private Harmony _harmony; private float _nextAuraCheck; private bool? _lastSyncedWearing; private ZNetView _lastView; private bool _checkedCape; private OdinEyeGlow _eye; private void Awake() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown _harmony = new Harmony("com.crasssam.odinarmour"); PrefabManager.OnVanillaPrefabsAvailable += Register; TryPatch(typeof(OdinEitrPatch)); TryPatch(typeof(OdinChestVisualPatch)); TryPatch(typeof(OdinCrownJewelPatch)); TryPatch(typeof(GungnirImpactPatch)); TryPatch(typeof(GungnirSummonInput)); _eye = ((Component)this).gameObject.AddComponent<OdinEyeGlow>(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Odin Armour 1.0.0 loaded; awaiting vanilla prefabs"); } private void TryPatch(Type patch) { try { _harmony.CreateClassProcessor(patch).Patch(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Odin Armour patch " + patch.Name + " failed: " + ex)); } } private void OnDestroy() { PrefabManager.OnVanillaPrefabsAvailable -= Register; if (_harmony != null) { _harmony.UnpatchSelf(); } } private void Register() { PrefabManager.OnVanillaPrefabsAvailable -= Register; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Odin Armour registering equipment"); try { OdinEquipment.Register(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Odin Armour item registration failed: " + ex)); } try { OdinPresence.Register(); } catch (Exception ex2) { ((BaseUnityPlugin)this).Logger.LogError((object)("Odin's Presence registration failed: " + ex2)); } GungnirPlugin.Register(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Odin Armour registration pass completed"); } private void Update() { //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) if (!_checkedCape && (Object)(object)ObjectDB.instance != (Object)null && (Object)(object)ZNetScene.instance != (Object)null && (Object)(object)Player.m_localPlayer != (Object)null) { _checkedCape = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)("OdinArmourCape lookup: ObjectDB=" + ((Object)(object)ObjectDB.instance.GetItemPrefab("OdinArmourCape") != (Object)null) + ", ZNetScene=" + ((Object)(object)ZNetScene.instance.GetPrefab("OdinArmourCape") != (Object)null))); } if (Time.time < _nextAuraCheck) { return; } _nextAuraCheck = Time.time + 1f; Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } bool flag = OdinEquipment.HasFullSet(localPlayer); OdinEitrPatch.Sync(localPlayer, flag); ZNetView component = ((Component)localPlayer).GetComponent<ZNetView>(); if ((Object)(object)component != (Object)(object)_lastView) { _lastView = component; _lastSyncedWearing = null; } if ((Object)(object)component != (Object)null && component.IsValid() && component.IsOwner() && (!_lastSyncedWearing.HasValue || flag != _lastSyncedWearing.Value)) { component.GetZDO().Set("com.crasssam.odinarmour.fullset", flag); _lastSyncedWearing = flag; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Odin Armour four-piece set " + (flag ? "active" : "inactive"))); } _eye.Tick(localPlayer, OdinEquipment.IsWearingHood(localPlayer)); if ((Object)(object)OdinPresence.Effect == (Object)null) { return; } if (flag) { OdinPresence.Refresh(localPlayer); return; } bool flag2 = false; foreach (Player allPlayer in Player.GetAllPlayers()) { if (!((Object)(object)allPlayer == (Object)null) && !((Object)(object)allPlayer == (Object)(object)localPlayer) && !(Vector3.Distance(((Component)allPlayer).transform.position, ((Component)localPlayer).transform.position) > 12f) && !BaseAI.IsEnemy((Character)(object)allPlayer, (Character)(object)localPlayer)) { ZNetView component2 = ((Component)allPlayer).GetComponent<ZNetView>(); if ((Object)(object)component2 != (Object)null && component2.IsValid() && component2.GetZDO().GetBool("com.crasssam.odinarmour.fullset", false)) { flag2 = true; break; } } } if (flag2) { OdinPresence.Refresh(localPlayer); } else { OdinPresence.Remove(localPlayer); } } } internal static class OdinEquipment { private static readonly BindingFlags Fields = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private static readonly FieldInfo HelmetSlot = typeof(Humanoid).GetField("m_helmetItem", Fields); private static readonly FieldInfo ChestSlot = typeof(Humanoid).GetField("m_chestItem", Fields); private static readonly FieldInfo LegsSlot = typeof(Humanoid).GetField("m_legItem", Fields); private static readonly FieldInfo CapeSlot = typeof(Humanoid).GetField("m_shoulderItem", Fields); private static readonly HashSet<Requirement> CrownJewelRequirements = new HashSet<Requirement>(); internal static Sprite HoodIcon { get; private set; } internal static void Register() { TryAdd("OdinHood", delegate { Add("OdinHood", "HelmetMage_Ashlands", "HelmetDNHeavy", "Hood of Odin", "A black hood with one glowing red eye. Part of Odin's four-piece regalia.", "HelmetMage_Ashlands", 20, 5, "NornThread", 5, 2, invisibleChest: false); }); TryAdd("OdinChest", delegate { Add("OdinChest", "ArmorFlametalChest", "ArmorDeepNorthHeavyChest", "Odin's Hidden Mail", "Invisible armour that leaves your normal torso visible.", "ArmorFlametalChest", 20, 10, "MooseHide", 8, 3, invisibleChest: true); }); TryAdd("OdinLegs", delegate { Add("OdinLegs", "ArmorAshlandsMediumlegs", "ArmorDeepNorthHeavylegs", "Trousers of Odin", "The shadowed trousers of the Allfather.", "ArmorAshlandsMediumlegs", 20, 10, "MooseHide", 8, 3, invisibleChest: false); }); TryAdd("OdinArmourCape", delegate { Add("OdinArmourCape", "CapeLox", null, "Mantle of Odin", "A dark lox cape with frost resistance and slow fall.", "CapeLox", 10, 3, "MooseHide", 6, 2, invisibleChest: false); }); } private static void TryAdd(string name, Action register) { try { register(); } catch (Exception ex) { Debug.LogError((object)("[OdinArmour] Could not register " + name + ": " + ex)); } } private static void Add(string prefabName, string basePrefab, string armorReference, string displayName, string description, string ingredient, int bloodgold, int bloodgoldUpgrade, string extraIngredient, int extraAmount, int extraUpgrade, bool invisibleChest) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown ItemConfig val = new ItemConfig { Name = displayName, Description = description, CraftingStation = "blackforge", MinStationLevel = 2 }; val.AddRequirement(new RequirementConfig(ingredient, 1, 0, true)); val.AddRequirement(new RequirementConfig("Gold", bloodgold, bloodgoldUpgrade, true)); val.AddRequirement(new RequirementConfig(extraIngredient, extraAmount, extraUpgrade, true)); val.AddRequirement(new RequirementConfig("CrownJewel", 1, 1, true)); CustomItem val2 = new CustomItem(prefabName, basePrefab, val); if ((Object)(object)val2.ItemPrefab == (Object)null || (Object)(object)val2.ItemDrop == (Object)null) { throw new InvalidOperationException("Could not clone " + basePrefab + " as " + prefabName + ". Check the log for a prefab name collision or missing source item."); } Recipe val3 = ((val2.Recipe == null) ? null : val2.Recipe.Recipe); if ((Object)(object)val3 == (Object)null || val3.m_resources == null || val3.m_resources.Length != 4 || val3.m_resources[3] == null) { throw new InvalidOperationException("Could not create the Crown Jewel recipe for " + prefabName); } ItemData itemData = val2.ItemDrop.m_itemData; itemData.m_shared = ShallowCopy<SharedData>(itemData.m_shared); SharedData shared = itemData.m_shared; shared.m_name = "$item_odinarmour_" + prefabName; shared.m_description = "$item_odinarmour_desc_" + prefabName; shared.m_movementModifier = 0f; SetIfExists(shared, "m_setName", "OdinArmourFourPieces"); SetIfExists(shared, "m_setSize", 4); SetIfExists(shared, "m_setStatusEffect", null); if (armorReference != null) { GameObject prefab = PrefabManager.Instance.GetPrefab(armorReference); if ((Object)(object)prefab == (Object)null) { throw new InvalidOperationException("Missing armour reference: " + armorReference); } SharedData shared2 = prefab.GetComponent<ItemDrop>().m_itemData.m_shared; CopyField(shared2, shared, "m_armor"); CopyField(shared2, shared, "m_armorPerLevel"); SetIfExists(shared, "m_equipStatusEffect", null); } Darken(val2.ItemPrefab, invisibleChest); Sprite val4 = DarkIcon(shared.m_icons); if ((Object)(object)val4 != (Object)null) { shared.m_icons = (Sprite[])(object)new Sprite[1] { val4 }; } if (prefabName == "OdinHood" && shared.m_icons != null && shared.m_icons.Length != 0) { HoodIcon = shared.m_icons[0]; } if (!ItemManager.Instance.AddItem(val2)) { throw new InvalidOperationException("Jötunn rejected " + prefabName + "; see the Jötunn warnings in the BepInEx log."); } CrownJewelRequirements.Add(val3.m_resources[3]); if (prefabName == "OdinArmourCape") { try { OdinPresence.ConfigureCape(shared); } catch (Exception ex) { Debug.LogError((object)("[OdinArmour] OdinArmourCape registered, but slow fall failed: " + ex)); } } Debug.Log((object)("[OdinArmour] Jötunn accepted " + prefabName)); CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); string text = "English"; localization.AddTranslation(ref text, new Dictionary<string, string> { ["item_odinarmour_" + prefabName] = displayName, ["item_odinarmour_desc_" + prefabName] = description }); } private static T ShallowCopy<T>(T value) where T : class { return (T)typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(value, null); } internal static bool IsCrownJewelRequirement(Requirement requirement) { return CrownJewelRequirements.Contains(requirement); } private static void CopyField(object source, object target, string name) { FieldInfo field = source.GetType().GetField(name, Fields); if (field == null) { throw new MissingFieldException(source.GetType().FullName, name); } field.SetValue(target, field.GetValue(source)); } internal static bool SetIfExists(object target, string name, object value) { FieldInfo field = target.GetType().GetField(name, Fields); if (field == null) { return false; } field.SetValue(target, value); return true; } internal static bool HasFullSet(Player player) { if ((Object)(object)player != (Object)null && Is(HelmetSlot, player, "OdinHood") && Is(ChestSlot, player, "OdinChest") && Is(LegsSlot, player, "OdinLegs")) { return Is(CapeSlot, player, "OdinArmourCape"); } return false; } internal static bool IsWearingHood(Player player) { if ((Object)(object)player != (Object)null) { return Is(HelmetSlot, player, "OdinHood"); } return false; } private static bool Is(FieldInfo slot, Player player, string name) { ItemData val = (ItemData)((slot == null) ? null : /*isinst with value type is only supported in some contexts*/); if (val != null && val.m_shared != null) { return val.m_shared.m_name == "$item_odinarmour_" + name; } return false; } private static void Darken(GameObject root, bool invisibleChest) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //IL_008d: 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_00c5: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true); Color val3 = default(Color); foreach (Renderer val in componentsInChildren) { if (invisibleChest && val is SkinnedMeshRenderer) { val.enabled = false; continue; } Material[] sharedMaterials = val.sharedMaterials; Material[] array = (Material[])(object)new Material[sharedMaterials.Length]; for (int j = 0; j < sharedMaterials.Length; j++) { if (!((Object)(object)sharedMaterials[j] == (Object)null)) { Material val2 = new Material(sharedMaterials[j]); ((Color)(ref val3))..ctor(0.018f, 0.019f, 0.024f, 1f); if (val2.HasProperty("_Color")) { val2.SetColor("_Color", val3); } if (val2.HasProperty("_BaseColor")) { val2.SetColor("_BaseColor", val3); } if (val2.HasProperty("_EmissionColor")) { val2.SetColor("_EmissionColor", Color.black); } array[j] = val2; } } val.sharedMaterials = array; } } private static Sprite DarkIcon(Sprite[] source) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_0089: 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_010c: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) if (source == null || source.Length == 0 || (Object)(object)source[0] == (Object)null) { return null; } try { Sprite obj = source[0]; Texture2D texture = obj.texture; Rect textureRect = obj.textureRect; int num = Mathf.RoundToInt(((Rect)(ref textureRect)).width); int num2 = Mathf.RoundToInt(((Rect)(ref textureRect)).height); RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)0); RenderTexture active = RenderTexture.active; Texture2D val; try { Graphics.Blit((Texture)(object)texture, temporary); RenderTexture.active = temporary; val = new Texture2D(num, num2, (TextureFormat)4, false); val.ReadPixels(new Rect(((Rect)(ref textureRect)).x, ((Rect)(ref textureRect)).y, (float)num, (float)num2), 0, 0); val.Apply(); } finally { RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); } Color[] pixels = val.GetPixels(); for (int i = 0; i < pixels.Length; i++) { float grayscale = ((Color)(ref pixels[i])).grayscale; pixels[i] = new Color(0.012f + grayscale * 0.12f, 0.012f + grayscale * 0.11f, 0.018f + grayscale * 0.13f, pixels[i].a); } val.SetPixels(pixels); val.Apply(); return Sprite.Create(val, new Rect(0f, 0f, (float)num, (float)num2), new Vector2(0.5f, 0.5f)); } catch { return null; } } } [HarmonyPatch(typeof(VisEquipment), "SetChestItem")] internal static class OdinChestVisualPatch { private static void Prefix(ref int itemHash) { if (itemHash != 0 && !((Object)(object)ObjectDB.instance == (Object)null)) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(itemHash); if ((Object)(object)itemPrefab != (Object)null && ((Object)itemPrefab).name == "OdinChest") { itemHash = 0; } } } } [HarmonyPatch(typeof(Requirement), "GetAmount")] internal static class OdinCrownJewelPatch { private static void Postfix(Requirement __instance, int qualityLevel, ref int __result) { if (qualityLevel > 1 && OdinEquipment.IsCrownJewelRequirement(__instance)) { __result = 1; } } } [HarmonyPatch] internal static class OdinEitrPatch { private const float Bonus = 50f; private static readonly BindingFlags Methods = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private static readonly MethodInfo SetMaximum = typeof(Player).GetMethod("SetMaxEitr", Methods, null, new Type[2] { typeof(float), typeof(bool) }, null); private static readonly MethodInfo GetFoodValues = typeof(Player).GetMethod("GetTotalFoodValue", Methods, null, new Type[3] { typeof(float).MakeByRefType(), typeof(float).MakeByRefType(), typeof(float).MakeByRefType() }, null); private static Player _lastPlayer; private static bool? _lastWearing; private static MethodBase TargetMethod() { if (SetMaximum == null) { throw new MissingMethodException("Player.SetMaxEitr(float, bool)"); } return SetMaximum; } private static void Prefix(Player __instance, ref float __0) { if (OdinEquipment.HasFullSet(__instance)) { __0 += 50f; } } internal static void Sync(Player player, bool wearing) { if ((Object)(object)_lastPlayer != (Object)(object)player) { _lastPlayer = player; _lastWearing = null; } if (_lastWearing == wearing) { return; } if (!_lastWearing.HasValue && !wearing) { _lastWearing = false; return; } if (SetMaximum == null || GetFoodValues == null) { Debug.LogError((object)"[OdinArmour] Could not recalculate Eitr: Player food or Eitr setter method is missing"); return; } try { object[] array = new object[3] { 0f, 0f, 0f }; GetFoodValues.Invoke(player, array); SetMaximum.Invoke(player, new object[2] { (float)array[2], false }); _lastWearing = wearing; } catch (Exception ex) { Debug.LogError((object)("[OdinArmour] Could not recalculate Eitr after set change: " + ex)); } } } internal sealed class OdinEyeGlow : MonoBehaviour { private static readonly Vector3 EyeOffset = new Vector3(0.075f, 0.065f, 0.225f); private GameObject _eye; private Player _owner; internal void Tick(Player player, bool hoodEquipped) { //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Expected O, but got Unknown //IL_00fa: 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) if (!hoodEquipped) { if ((Object)(object)_eye != (Object)null) { _eye.SetActive(false); } return; } if ((Object)(object)_owner != (Object)(object)player || (Object)(object)_eye == (Object)null) { if ((Object)(object)_eye != (Object)null) { Object.Destroy((Object)(object)_eye); } _owner = player; Transform val = null; Animator componentInChildren = ((Component)player).GetComponentInChildren<Animator>(true); if ((Object)(object)componentInChildren != (Object)null && componentInChildren.isHuman) { try { val = componentInChildren.GetBoneTransform((HumanBodyBones)10); } catch (Exception) { } } if ((Object)(object)val == (Object)null) { Transform[] componentsInChildren = ((Component)player).GetComponentsInChildren<Transform>(true); foreach (Transform val2 in componentsInChildren) { if (string.Equals(((Object)val2).name, "Head", StringComparison.OrdinalIgnoreCase)) { val = val2; break; } } } if ((Object)(object)val == (Object)null) { return; } _eye = new GameObject("OdinArmour_RightEyeLight"); _eye.transform.SetParent(val, false); _eye.transform.localPosition = EyeOffset; Light obj = _eye.AddComponent<Light>(); obj.color = new Color(1f, 0.025f, 0.025f); obj.intensity = 1.2f; obj.range = 0.16f; } _eye.SetActive(true); } private void OnDestroy() { if ((Object)(object)_eye != (Object)null) { Object.Destroy((Object)(object)_eye); } } } internal static class OdinPresence { private static readonly BindingFlags Fields = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; internal static StatusEffect Effect { get; private set; } internal static void ConfigureCape(SharedData shared) { GameObject prefab = PrefabManager.Instance.GetPrefab("CapeFeather"); ItemDrop val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<ItemDrop>() : null); StatusEffect val2 = (((Object)(object)val != (Object)null) ? val.m_itemData.m_shared.m_equipStatusEffect : null); if ((Object)(object)val2 == (Object)null) { throw new InvalidOperationException("CapeFeather's slow-fall equip effect was not found"); } AddFrostResistance(shared); shared.m_equipStatusEffect = val2; } private static void AddFrostResistance(SharedData shared) { FieldInfo fieldInfo = FindField(((object)shared).GetType(), "m_damageModifiers"); if (fieldInfo == null || !fieldInfo.FieldType.IsGenericType) { throw new MissingFieldException("SharedData", "m_damageModifiers"); } Type type = fieldInfo.FieldType.GetGenericArguments()[0]; FieldInfo fieldInfo2 = FindField(type, "m_type"); FieldInfo fieldInfo3 = FindField(type, "m_modifier"); if (fieldInfo2 == null || fieldInfo3 == null || !fieldInfo2.FieldType.IsEnum || !fieldInfo3.FieldType.IsEnum) { throw new MissingFieldException("DamageModPair", "m_type/m_modifier"); } if (!(Activator.CreateInstance(fieldInfo.FieldType) is IList list)) { throw new InvalidOperationException("Cannot copy cape damage modifiers"); } if (fieldInfo.GetValue(shared) is IList list2) { foreach (object item in list2) { list.Add(item); if (fieldInfo2.GetValue(item).ToString() == "Frost") { fieldInfo3.SetValue(item, Enum.Parse(fieldInfo3.FieldType, "Resistant")); list[list.Count - 1] = item; fieldInfo.SetValue(shared, list); return; } } } object obj = Activator.CreateInstance(type); fieldInfo2.SetValue(obj, Enum.Parse(fieldInfo2.FieldType, "Frost")); fieldInfo3.SetValue(obj, Enum.Parse(fieldInfo3.FieldType, "Resistant")); list.Add(obj); fieldInfo.SetValue(shared, list); } internal static void Register() { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown SE_Stats val = ScriptableObject.CreateInstance<SE_Stats>(); ((Object)val).name = "OdinArmour_Presence"; ((StatusEffect)val).m_name = "Odin's Presence"; ((StatusEffect)val).m_tooltip = "Odin's Presence: +20 armour. Odin's Wisdom: +15% Eitr regeneration. Shared with nearby allies."; ((StatusEffect)val).m_ttl = 0f; ((StatusEffect)val).m_icon = OdinEquipment.HoodIcon; if (!OdinEquipment.SetIfExists(val, "m_addArmor", 20f) && !OdinEquipment.SetIfExists(val, "m_armorAdd", 20f)) { throw new MissingFieldException("SE_Stats", "m_addArmor"); } if (!OdinEquipment.SetIfExists(val, "m_eitrRegenMultiplier", 1.15f)) { throw new MissingFieldException("SE_Stats", "m_eitrRegenMultiplier"); } if (!ItemManager.Instance.AddStatusEffect(new CustomStatusEffect((StatusEffect)(object)val, false))) { throw new InvalidOperationException("Jötunn rejected Odin's Presence status effect"); } Effect = (StatusEffect)(object)val; } internal static void Refresh(Player player) { if ((Object)(object)player == (Object)null || (Object)(object)Effect == (Object)null) { return; } object sEMan = ((Character)player).GetSEMan(); if (sEMan == null) { return; } MethodInfo[] methods = sEMan.GetType().GetMethods(Fields); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name != "AddStatusEffect") { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 0 || parameters[0].ParameterType != typeof(StatusEffect)) { continue; } object[] parameters2; if (parameters.Length == 5) { parameters2 = new object[5] { Effect, true, 0, 0f, (short)(-1) }; } else if (parameters.Length == 4) { parameters2 = new object[4] { Effect, true, 0, 0f }; } else if (parameters.Length == 2) { parameters2 = new object[2] { Effect, true }; } else { if (parameters.Length != 1) { continue; } parameters2 = new object[1] { Effect }; } try { methodInfo.Invoke(sEMan, parameters2); break; } catch { } } } internal static void Remove(Player player) { if (!((Object)(object)player == (Object)null) && !((Object)(object)Effect == (Object)null)) { SEMan sEMan = ((Character)player).GetSEMan(); if (sEMan != null) { sEMan.RemoveStatusEffect(StringExtensionMethods.GetStableHashCode(((Object)Effect).name), false); } } } private static FieldInfo FindField(Type type, string name) { Type type2 = type; while (type2 != null) { FieldInfo field = type2.GetField(name, Fields | BindingFlags.DeclaredOnly); if (field != null) { return field; } type2 = type2.BaseType; } return null; } } } namespace Gungnir { public sealed class GungnirHoming : MonoBehaviour { private const float LockRange = 60f; private const float MinimumAimDot = 0.9063f; private const float StraightFlightSeconds = 0.35f; private const float TurnRampSeconds = 0.4f; private const float TurnRadiansPerSecond = 9f; private static readonly BindingFlags Fields = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private static readonly FieldInfo OwnerField = typeof(Projectile).GetField("m_owner", Fields); private static readonly FieldInfo VelocityField = typeof(Projectile).GetField("m_vel", Fields); private static readonly FieldInfo GravityField = typeof(Projectile).GetField("m_gravity", Fields); private static readonly FieldInfo DidHitField = typeof(Projectile).GetField("m_didHit", Fields); private readonly List<Character> _candidates = new List<Character>(); private Projectile _projectile; private ZNetView _network; private Character _target; private float _speed; private float _spawnTime; private bool _searched; private bool _homingStarted; private void Awake() { _projectile = ((Component)this).GetComponent<Projectile>(); _network = ((Component)this).GetComponent<ZNetView>(); _spawnTime = Time.time; } private void FixedUpdate() { //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_010c: 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_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_projectile == (Object)null || VelocityField == null || OwnerField == null) { ((Behaviour)this).enabled = false; } else { if ((Object)(object)_network != (Object)null && !_network.IsOwner()) { return; } if (!_searched) { object? value = OwnerField.GetValue(_projectile); Character val = (Character)((value is Character) ? value : null); if ((Object)(object)val == (Object)null) { if (Time.time - _spawnTime > 0.5f) { ((Behaviour)this).enabled = false; } return; } _searched = true; Vector3 val2 = (Vector3)VelocityField.GetValue(_projectile); if (((Vector3)(ref val2)).sqrMagnitude < 1f) { ((Behaviour)this).enabled = false; return; } _target = SelectTarget(val); if ((Object)(object)_target == (Object)null) { ((Behaviour)this).enabled = false; return; } } if ((Object)(object)_target == (Object)null || _target.IsDead() || Vector3.Distance(((Component)this).transform.position, ((Component)_target).transform.position) > 75f) { ((Behaviour)this).enabled = false; return; } if (DidHitField != null && DidHitField.FieldType == typeof(bool) && (bool)DidHitField.GetValue(_projectile)) { ((Behaviour)this).enabled = false; return; } Vector3 val3 = (Vector3)VelocityField.GetValue(_projectile); if (((Vector3)(ref val3)).sqrMagnitude < 1f) { ((Behaviour)this).enabled = false; return; } float num = Time.time - _spawnTime; if (num < 0.35f) { return; } if (!_homingStarted) { _homingStarted = true; _speed = ((Vector3)(ref val3)).magnitude; if (GravityField != null && GravityField.FieldType == typeof(float)) { GravityField.SetValue(_projectile, 0f); } } Vector3 val4 = _target.GetCenterPoint() - ((Component)this).transform.position; if (!(((Vector3)(ref val4)).sqrMagnitude < 0.01f)) { float num2 = Mathf.Clamp01((num - 0.35f) / 0.4f); float num3 = Mathf.Lerp(1.5f, 9f, num2); Vector3 val5 = Vector3.RotateTowards(((Vector3)(ref val3)).normalized, ((Vector3)(ref val4)).normalized, num3 * Time.fixedDeltaTime, 0f); VelocityField.SetValue(_projectile, val5 * _speed); } } } private Character SelectTarget(Character owner) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_0084: 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_00a6: 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_00ab: Unknown result type (might be due to invalid IL or missing references) Vector3 eyePoint = owner.GetEyePoint(); Vector3 lookDir = owner.GetLookDir(); Vector3 normalized = ((Vector3)(ref lookDir)).normalized; Character result = null; float num = 0.9063f; float num2 = float.MaxValue; Character.GetCharactersInRange(eyePoint, 60f, _candidates); foreach (Character candidate in _candidates) { if ((Object)(object)candidate == (Object)null || (Object)(object)candidate == (Object)(object)owner || candidate.IsDead() || !BaseAI.IsEnemy(owner, candidate)) { continue; } Vector3 val = candidate.GetCenterPoint() - eyePoint; float magnitude = ((Vector3)(ref val)).magnitude; if (!(magnitude < 1f) && !(magnitude > 60f)) { float num3 = Vector3.Dot(normalized, val / magnitude); if (!(num3 < 0.9063f) && (num3 > num + 0.002f || (num3 >= num - 0.002f && magnitude < num2))) { result = candidate; num = num3; num2 = magnitude; } } } _candidates.Clear(); return result; } } [HarmonyPatch] internal static class GungnirImpactPatch { private static readonly FieldInfo OwnerField = typeof(Projectile).GetField("m_owner", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static MethodBase TargetMethod() { MethodInfo[] methods = typeof(Projectile).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (methodInfo.Name == "OnHit" && parameters.Length >= 3 && parameters[0].ParameterType == typeof(Collider)) { return methodInfo; } } throw new MissingMethodException("Projectile.OnHit(Collider, ...) was not found."); } private static void Prefix(Projectile __instance, Collider collider, out bool __state) { __state = false; if (!((Object)(object)__instance == (Object)null) && !((Object)(object)collider == (Object)null) && !(OwnerField == null) && !((Object)(object)((Component)__instance).GetComponent<GungnirHoming>() == (Object)null)) { Character componentInParent = ((Component)collider).GetComponentInParent<Character>(); object? value = OwnerField.GetValue(__instance); Character val = (Character)((value is Character) ? value : null); __state = (Object)(object)componentInParent != (Object)null && (Object)(object)val != (Object)null && (Object)(object)componentInParent != (Object)(object)val && BaseAI.IsEnemy(val, componentInParent); } } private static void Postfix(Projectile __instance, bool __state) { if (__state && !((Object)(object)__instance == (Object)null) && !((Object)(object)ZNetScene.instance == (Object)null)) { ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.IsValid() && component.IsOwner()) { ZNetScene.instance.Destroy(((Component)__instance).gameObject); } } } } internal static class GungnirPlugin { internal static void Register() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown try { ItemConfig val = new ItemConfig { Name = "Gungnir, Odin's Spear", Description = "Odin's unerring spear. With no shield equipped, block to summon six Einherjar for 50 Eitr. Throw with the usual secondary attack.", CraftingStation = "forge", MinStationLevel = 1 }; val.AddRequirement(new RequirementConfig("SpearGold", 1, 0, true)); val.AddRequirement(new RequirementConfig("BlackMetal", 20, 0, true)); val.AddRequirement(new RequirementConfig("YggdrasilWood", 10, 0, true)); CustomItem val2 = new CustomItem("Gungnir", "SpearGold", val); ItemData itemData = val2.ItemDrop.m_itemData; itemData.m_shared = Copy<SharedData>(itemData.m_shared); SharedData shared = itemData.m_shared; shared.m_name = "$item_gungnir"; shared.m_description = "$item_gungnir_description"; if (shared.m_secondaryAttack == null) { throw new InvalidOperationException("The Nord Spear has no secondary throw attack."); } shared.m_secondaryAttack = Copy<Attack>(shared.m_secondaryAttack); Attack secondaryAttack = shared.m_secondaryAttack; if ((Object)(object)secondaryAttack.m_attackProjectile == (Object)null) { throw new InvalidOperationException("The Nord Spear has no throw projectile."); } secondaryAttack.m_consumeItem = false; GameObject val3 = PrefabManager.Instance.CreateClonedPrefab("Gungnir_Projectile", secondaryAttack.m_attackProjectile); if ((Object)(object)val3 == (Object)null) { throw new InvalidOperationException("Could not clone the Nord Spear projectile."); } Projectile component = val3.GetComponent<Projectile>(); if ((Object)(object)component == (Object)null) { throw new InvalidOperationException("Nord Spear projectile has no Projectile component."); } SetRequired(component, "m_respawnItemOnHit", false); SetRequired(component, "m_stayAfterHitStatic", true); SetRequired(component, "m_stayAfterHitDynamic", true); SetRequired(component, "m_stayTTL", 5f); SetOptional(component, "m_spawnOnTtl", false); val3.AddComponent<GungnirHoming>(); Blacken(val2.ItemPrefab); Blacken(val3); Sprite val4 = MakeBlackIcon(shared.m_icons); if ((Object)(object)val4 != (Object)null) { shared.m_icons = (Sprite[])(object)new Sprite[1] { val4 }; } PrefabManager.Instance.AddPrefab(val3); secondaryAttack.m_attackProjectile = val3; ItemManager.Instance.AddItem(val2); try { GungnirSummon.Register(val2); } catch (Exception ex) { Debug.LogError((object)("[OdinRegalia] Gungnir spear registered, but summon registration failed: " + ex)); } CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); string text = "English"; localization.AddTranslation(ref text, new Dictionary<string, string> { ["item_gungnir"] = "Gungnir, Odin's Spear", ["item_gungnir_description"] = "Odin's unerring spear. Without a shield, press block to summon six Einherjar for 50 Eitr. Use the usual secondary attack to throw it." }); Debug.Log((object)"[OdinRegalia] Gungnir registered. Spawn for testing: spawn Gungnir 1"); } catch (Exception ex2) { Debug.LogError((object)("[OdinRegalia] Could not register Gungnir: " + ex2)); } } private static T Copy<T>(T value) where T : class { return (T)typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(value, null); } private static void SetRequired(object target, string name, object value) { FieldInfo field = target.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null || field.FieldType != value.GetType()) { throw new MissingFieldException(target.GetType().FullName, name); } field.SetValue(target, value); } private static void SetOptional(object target, string name, object value) { FieldInfo field = target.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == value.GetType()) { field.SetValue(target, value); } } private static void Blacken(GameObject root) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_006f: 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) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { Material[] sharedMaterials = val.sharedMaterials; Material[] array = (Material[])(object)new Material[sharedMaterials.Length]; for (int j = 0; j < sharedMaterials.Length; j++) { if (!((Object)(object)sharedMaterials[j] == (Object)null)) { Material val2 = new Material(sharedMaterials[j]); if (val2.HasProperty("_Color")) { val2.SetColor("_Color", new Color(0.035f, 0.037f, 0.045f, 1f)); } if (val2.HasProperty("_BaseColor")) { val2.SetColor("_BaseColor", new Color(0.035f, 0.037f, 0.045f, 1f)); } if (val2.HasProperty("_EmissionColor")) { val2.SetColor("_EmissionColor", Color.black); } array[j] = val2; } } val.sharedMaterials = array; } } private static Sprite MakeBlackIcon(Sprite[] source) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_0089: 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_010c: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) if (source == null || source.Length == 0 || (Object)(object)source[0] == (Object)null) { return null; } try { Sprite obj = source[0]; Texture2D texture = obj.texture; Rect textureRect = obj.textureRect; int num = Mathf.RoundToInt(((Rect)(ref textureRect)).width); int num2 = Mathf.RoundToInt(((Rect)(ref textureRect)).height); RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)0); RenderTexture active = RenderTexture.active; Texture2D val; try { Graphics.Blit((Texture)(object)texture, temporary); RenderTexture.active = temporary; val = new Texture2D(num, num2, (TextureFormat)4, false); val.ReadPixels(new Rect(((Rect)(ref textureRect)).x, ((Rect)(ref textureRect)).y, (float)num, (float)num2), 0, 0); val.Apply(); } finally { RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); } Color[] pixels = val.GetPixels(); for (int i = 0; i < pixels.Length; i++) { float grayscale = ((Color)(ref pixels[i])).grayscale; pixels[i] = new Color(0.018f + grayscale * 0.13f, 0.019f + grayscale * 0.14f, 0.026f + grayscale * 0.16f, pixels[i].a); } val.SetPixels(pixels); val.Apply(); ((Object)val).name = "Gungnir_Icon"; return Sprite.Create(val, new Rect(0f, 0f, (float)num, (float)num2), new Vector2(0.5f, 0.5f)); } catch (Exception ex) { Debug.LogWarning((object)("[OdinRegalia] Could not tint Gungnir icon: " + ex.Message)); return null; } } } internal static class GungnirSummon { private const int EinherjarPerCast = 6; internal static Attack CastAttack { get; private set; } internal static void Register(CustomItem spear) { GameObject prefab = PrefabManager.Instance.GetPrefab("StaffSkeleton"); GameObject prefab2 = PrefabManager.Instance.GetPrefab("StaffShield"); if ((Object)(object)prefab == (Object)null || (Object)(object)prefab2 == (Object)null) { throw new InvalidOperationException("StaffSkeleton or StaffShield is unavailable"); } Attack attack = prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_attack; Attack attack2 = prefab2.GetComponent<ItemDrop>().m_itemData.m_shared.m_attack; if (attack == null || attack2 == null || (Object)(object)attack.m_attackProjectile == (Object)null) { throw new InvalidOperationException("Vanilla summon or shield casting attack is unavailable"); } GameObject val = MakeSoldier(); PrefabManager.Instance.AddPrefab(val); GameObject val2 = PrefabManager.Instance.CreateClonedPrefab("OdinSoldier_Spawn", attack.m_attackProjectile); SpawnAbility val3 = (((Object)(object)val2 != (Object)null) ? val2.GetComponent<SpawnAbility>() : null); if ((Object)(object)val3 == (Object)null) { throw new InvalidOperationException("Dead Raiser projectile lacks SpawnAbility"); } val3.m_spawnPrefab = (GameObject[])(object)new GameObject[1] { val }; val3.m_minToSpawn = 6; FieldInfo fieldInfo = FindField(((object)val3).GetType(), "m_maxToSpawn"); if (fieldInfo != null && fieldInfo.FieldType == typeof(int)) { fieldInfo.SetValue(val3, 6); } SetRequiredField(val3, "m_setMaxInstancesFromWeaponLevel", false); SetSummonLimit(val3, 6); PrefabManager.Instance.AddPrefab(val2); CastAttack = ShallowCopy<Attack>(attack); CastAttack.m_attackProjectile = val2; CastAttack.m_attackAnimation = attack2.m_attackAnimation; CastAttack.m_attackEitr = 50f; CastAttack.m_attackStamina = 0f; CastAttack.m_attackHealth = 0f; CastAttack.m_attackHealthPercentage = 0f; CastAttack.m_consumeItem = false; Debug.Log((object)"[OdinRegalia] Summon registered: 6 Einherjar, 50 Eitr, StaffShield animation"); } private static GameObject MakeSoldier() { GameObject prefab = PrefabManager.Instance.GetPrefab("Player"); GameObject val = (((Object)(object)prefab != (Object)null) ? PrefabManager.Instance.CreateClonedPrefab("OdinSoldier", prefab) : null); GameObject prefab2 = PrefabManager.Instance.GetPrefab("Skeleton_Friendly"); if ((Object)(object)val == (Object)null || (Object)(object)prefab2 == (Object)null) { throw new InvalidOperationException("Player or Skeleton_Friendly prefab is unavailable"); } Player component = val.GetComponent<Player>(); if ((Object)(object)component == (Object)null) { throw new InvalidOperationException("Player prefab lacks Player component"); } Dictionary<FieldInfo, object> values = Snapshot(component, typeof(Humanoid)); Component component2 = val.GetComponent("PlayerController"); if ((Object)(object)component2 != (Object)null) { Object.DestroyImmediate((Object)(object)component2); } Component component3 = val.GetComponent("Talker"); if ((Object)(object)component3 != (Object)null) { Object.DestroyImmediate((Object)(object)component3); } Object.DestroyImmediate((Object)(object)component); Humanoid val2 = val.AddComponent<Humanoid>(); Restore(val2, values); FieldInfo fieldInfo = FindField(((object)val2).GetType(), "m_tamed"); if (fieldInfo != null && fieldInfo.FieldType == typeof(bool)) { fieldInfo.SetValue(val2, true); } val.tag = "Untagged"; MonsterAI component4 = prefab2.GetComponent<MonsterAI>(); if ((Object)(object)component4 == (Object)null) { throw new InvalidOperationException("Friendly skeleton lacks MonsterAI"); } MonsterAI target = val.AddComponent<MonsterAI>(); CopySettings(component4, target); Tameable component5 = prefab2.GetComponent<Tameable>(); if ((Object)(object)component5 != (Object)null) { Tameable target2 = val.AddComponent<Tameable>(); CopySettings(component5, target2); GameObject prefab3 = PrefabManager.Instance.GetPrefab("OdinChest"); GameObject prefab4 = PrefabManager.Instance.GetPrefab("OdinLegs"); GameObject prefab5 = PrefabManager.Instance.GetPrefab("AxeGold"); if ((Object)(object)prefab3 == (Object)null || (Object)(object)prefab4 == (Object)null || (Object)(object)prefab5 == (Object)null) { throw new InvalidOperationException("Soldier equipment missing: OdinChest, OdinLegs or AxeGold"); } val2.m_defaultItems = (GameObject[])(object)new GameObject[3] { prefab3, prefab4, prefab5 }; ((Character)val2).m_name = "Einherjar"; return val; } throw new InvalidOperationException("Friendly skeleton lacks Tameable"); } private static Dictionary<FieldInfo, object> Snapshot(object source, Type from) { Dictionary<FieldInfo, object> dictionary = new Dictionary<FieldInfo, object>(); Type type = from; while (type != null && type != typeof(MonoBehaviour)) { FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (!fieldInfo.IsStatic && !fieldInfo.IsInitOnly) { dictionary[fieldInfo] = fieldInfo.GetValue(source); } } type = type.BaseType; } return dictionary; } private static void Restore(object target, Dictionary<FieldInfo, object> values) { foreach (KeyValuePair<FieldInfo, object> value in values) { value.Key.SetValue(target, value.Value); } } private static void CopySettings(object source, object target) { Type type = source.GetType(); while (type != null && type != typeof(MonoBehaviour)) { FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (!fieldInfo.IsStatic && !fieldInfo.IsInitOnly) { Type fieldType = fieldInfo.FieldType; if (fieldType.IsPrimitive || fieldType.IsEnum || fieldType == typeof(string) || fieldType == typeof(Vector3)) { fieldInfo.SetValue(target, fieldInfo.GetValue(source)); } } } type = type.BaseType; } } private static T ShallowCopy<T>(T value) where T : class { return (T)typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(value, null); } private static void SetSummonLimit(SpawnAbility spawn, int limit) { FieldInfo fieldInfo = FindField(((object)spawn).GetType(), "m_levelUpSettings"); IList list = ((fieldInfo != null) ? (fieldInfo.GetValue(spawn) as IList) : null); if (list == null || list.Count == 0) { throw new InvalidOperationException("Dead Raiser has no summon level settings"); } if (!(Activator.CreateInstance(fieldInfo.FieldType) is IList list2)) { throw new InvalidOperationException("Cannot clone summon level settings"); } foreach (object item in list) { object obj = CloneEntry(item); SetRequiredNumber(obj, "m_maxSpawns", limit); list2.Add(obj); } object obj2 = CloneEntry(list[0]); SetRequiredNumber(obj2, "m_skillLevel", 0); SetRequiredNumber(obj2, "m_maxSpawns", limit); list2.Insert(0, obj2); fieldInfo.SetValue(spawn, list2); } private static object CloneEntry(object source) { if (source == null) { throw new InvalidOperationException("Summon level setting was null"); } if (source.GetType().IsValueType) { return source; } return typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(source, null); } private static void SetRequiredField(object target, string name, object value) { FieldInfo fieldInfo = FindField(target.GetType(), name); if (fieldInfo == null || fieldInfo.FieldType != value.GetType()) { throw new MissingFieldException(target.GetType().FullName, name); } fieldInfo.SetValue(target, value); } private static void SetRequiredNumber(object target, string name, int value) { FieldInfo fieldInfo = FindField(target.GetType(), name); if (fieldInfo == null || !typeof(IConvertible).IsAssignableFrom(fieldInfo.FieldType)) { throw new MissingFieldException(target.GetType().FullName, name); } fieldInfo.SetValue(target, Convert.ChangeType(value, fieldInfo.FieldType)); } private static FieldInfo FindField(Type targetType, string name) { Type type = targetType; while (type != null) { FieldInfo field = type.GetField(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return field; } type = type.BaseType; } return null; } } [HarmonyPatch] internal static class GungnirSummonInput { private static readonly FieldInfo LeftHand = typeof(Humanoid).GetField("m_leftItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static MethodBase TargetMethod() { MethodInfo[] methods = typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name != "SetControls") { continue; } bool flag = false; bool flag2 = false; ParameterInfo[] parameters = methodInfo.GetParameters(); foreach (ParameterInfo parameterInfo in parameters) { if (parameterInfo.Name == "block" && parameterInfo.ParameterType == typeof(bool)) { flag = true; } if (parameterInfo.Name == "blockHold" && parameterInfo.ParameterType == typeof(bool)) { flag2 = true; } } if (flag && flag2) { return methodInfo; } } throw new MissingMethodException("Player.SetControls(... block, blockHold ...)"); } private static void Prefix(Player __instance, ref bool block, ref bool blockHold, ref bool secondaryAttack, ref bool secondaryAttackHold) { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Invalid comparison between Unknown and I4 if ((Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || GungnirSummon.CastAttack == null) { return; } ItemData currentWeapon = ((Humanoid)__instance).GetCurrentWeapon(); if (currentWeapon == null || currentWeapon.m_shared == null || currentWeapon.m_shared.m_name != "$item_gungnir") { return; } ItemData val = (ItemData)((LeftHand != null) ? /*isinst with value type is only supported in some contexts*/: null); if (val != null && val.m_shared != null && (int)val.m_shared.m_itemType == 5) { return; } bool flag = block; if (flag) { Attack secondaryAttack2 = currentWeapon.m_shared.m_secondaryAttack; try { currentWeapon.m_shared.m_secondaryAttack = GungnirSummon.CastAttack; ((Character)__instance).StartAttack((Character)null, true); } catch (Exception ex) { Debug.LogError((object)("[OdinRegalia] Summon cast failed: " + ex)); } finally { currentWeapon.m_shared.m_secondaryAttack = secondaryAttack2; } } block = false; blockHold = false; if (flag & secondaryAttack) { secondaryAttack = false; secondaryAttackHold = false; } } } }