using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("assembly_guiutils")] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("GungnirStaff")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("A Valheim mod adding the Gungnir staff.")] [assembly: AssemblyFileVersion("1.0.3.0")] [assembly: AssemblyInformationalVersion("1.0.3+c18dabb3f7b8e7e9e872b65c165901ce1df9c815")] [assembly: AssemblyProduct("Gungnir Staff")] [assembly: AssemblyTitle("GungnirStaff")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.3.0")] [module: UnverifiableCode] [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 GungnirStaff { internal static class Alive { internal static bool InGame { get { if (!((Object)(object)Console.m_instance != (Object)null)) { return (Object)(object)Player.m_localPlayer != (Object)null; } return true; } } internal static string StatusLine(Harmony harmony) { int num = ((harmony != null) ? harmony.GetPatchedMethods().Count() : 0); return "Gungnir Staff v1.0.3 | Release build 2026-08-30 22:20:13 | loaded from " + LoadedFrom() + " | " + $"{num} patched method(s)"; } private static string LoadedFrom() { try { string location = Assembly.GetExecutingAssembly().Location; if (string.IsNullOrEmpty(location)) { return "scripts (hot reload, in memory)"; } string fileName = Path.GetFileName(Path.GetDirectoryName(location)); return string.IsNullOrEmpty(fileName) ? location : fileName; } catch (Exception) { return "unknown"; } } internal static void Announce(string reason, Harmony harmony) { string text = "[" + reason + "] " + StatusLine(harmony); GungnirStaffPlugin.Log.LogMessage((object)text); ToGameConsole(text); ToHud(text); } internal static void ToGameConsole(string text) { Console instance = Console.m_instance; if (instance != null) { instance.Print(text); } } internal static void ToHud(string text) { MessageHud instance = MessageHud.m_instance; if (instance != null) { instance.ShowMessage((MessageType)2, text, 0, (Sprite)null, false); } } } internal static class BladeGlow { private const string ObjectName = "GungnirBladeGlow"; private static ParticleSystem _system; private static ParticleSystem _smoke; private static Transform _builtFor; private static int _rebuilds; private static Material _material; private static Color _applied = Color.clear; private static bool _sweepPending; private static int _lastRebuildFrame = -10; private static int _consecutiveRebuilds; private static bool _loggedAnchor; private static Material _smokeMaterial; private static bool _smokeSearched; private static GameObject _mounted; internal static void Apply(GameObject weapon, Transform visual, bool staffStance) { //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: 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_0157: 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_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0165: 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) bool flag = ModConfig.WeaponEffect.Value switch { WeaponEffectMode.Always => true, WeaponEffectMode.Never => false, _ => !staffStance, }; if (ModConfig.BladeGlowStyle.Value == BladeGlowStyle.None) { flag = false; } Renderer val = (((Object)(object)visual != (Object)null) ? FindBlade(visual) : null); if (!flag || (Object)(object)val == (Object)null) { Clear(); return; } if ((!((Object)(object)_mounted != (Object)null) && !((Object)(object)_system != (Object)null)) || _builtFor != ((Component)val).transform) { Clear(); Build(val, weapon, visual); _builtFor = ((Component)val).transform; _sweepPending = true; if (Time.frameCount == _lastRebuildFrame + 1) { _consecutiveRebuilds++; if (_consecutiveRebuilds == 20) { GungnirStaffPlugin.Log.LogWarning((object)"Blade glow has rebuilt on 20 consecutive frames - something is tearing it down as fast as it is built."); } } else { _consecutiveRebuilds = 0; } _lastRebuildFrame = Time.frameCount; } NeutraliseScale(((Object)(object)_system != (Object)null) ? ((Component)_system).transform : null); NeutraliseScale(((Object)(object)_smoke != (Object)null) ? ((Component)_smoke).transform : null); if (!((Object)(object)_system == (Object)null)) { Color val2 = ModConfig.ParseColour(ModConfig.BladeGlowColour.Value, new Color(0.5f, 0.78f, 1f)); if (_applied != val2) { _applied = val2; Tint(val2); } } } internal static void PurgeStrays(Player player) { if ((Object)(object)player == (Object)null || !_sweepPending) { return; } _sweepPending = false; GameObject[] array = (GameObject[])(object)new GameObject[1] { ((Component)player).gameObject }; foreach (GameObject val in array) { ParticleSystem[] componentsInChildren = val.GetComponentsInChildren(true); foreach (ParticleSystem val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && val2 != _system && val2 != _smoke && ((Object)((Component)val2).gameObject).name.StartsWith("GungnirBladeGlow", StringComparison.Ordinal)) { Object.DestroyImmediate((Object)(object)((Component)val2).gameObject); } } } } internal static void Clear() { //IL_006d: 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) if ((Object)(object)_system != (Object)null) { Object.DestroyImmediate((Object)(object)((Component)_system).gameObject); } if ((Object)(object)_smoke != (Object)null) { Object.DestroyImmediate((Object)(object)((Component)_smoke).gameObject); } _smoke = null; if ((Object)(object)_mounted != (Object)null) { Object.DestroyImmediate((Object)(object)_mounted); } _mounted = null; _system = null; _builtFor = null; _material = null; _applied = Color.clear; } private static void Build(Renderer blade, GameObject weapon, Transform visual) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) try { if (!TryMountVanillaEffect(blade)) { _material = BorrowParticleMaterial(weapon); GameObject val = new GameObject("GungnirBladeGlow"); val.transform.SetParent(visual, false); val.transform.localPosition = EmitterAnchor(blade, visual); val.transform.localRotation = Quaternion.Euler(-90f, 0f, 0f); _system = val.AddComponent(); ParticleSystemRenderer component = val.GetComponent(); component.renderMode = (ParticleSystemRenderMode)0; component.alignment = (ParticleSystemRenderSpace)0; ((Renderer)component).material = _material; ((Renderer)component).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)component).receiveShadows = false; if (ModConfig.BladeGlowStyle.Value == BladeGlowStyle.Lightning) { ConfigureLightning(_system, component, visual); BuildOrbit(blade, visual); } else { Configure(_system); } ModConfig.Trace($"Blade glow created ({ModConfig.BladeGlowStyle.Value})."); } } catch (Exception arg) { GungnirStaffPlugin.Log.LogError((object)$"Could not build the blade glow: {arg}"); Clear(); } } private static void Configure(ParticleSystem ps) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_004a: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0091: 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) //IL_00b1: 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_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Expected O, but got Unknown //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0137: 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_0148: 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_0164: 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_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_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_0202: 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_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Expected O, but got Unknown //IL_0211: Unknown result type (might be due to invalid IL or missing references) ps.Stop(); float value = ModConfig.BladeGlowScale.Value; MainModule main = ps.main; ((MainModule)(ref main)).loop = true; ((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)2; ((MainModule)(ref main)).startLifetime = new MinMaxCurve(0.35f, 0.8f); ((MainModule)(ref main)).startSpeed = new MinMaxCurve(0.02f, 0.12f); ((MainModule)(ref main)).startSize = new MinMaxCurve(0.03f * value, 0.07f * value); ((MainModule)(ref main)).maxParticles = 40; ((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(-0.01f); ((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)0; EmissionModule emission = ps.emission; ((EmissionModule)(ref emission)).enabled = true; ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(18f * ModConfig.BladeGlowRate.Value); ShapeModule shape = ps.shape; ((ShapeModule)(ref shape)).enabled = true; ((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)0; ((ShapeModule)(ref shape)).radius = 0.05f * value; ((ShapeModule)(ref shape)).scale = new Vector3(0.5f, 2.4f, 0.5f); ((ShapeModule)(ref shape)).radiusThickness = 0.7f; ColorOverLifetimeModule colorOverLifetime = ps.colorOverLifetime; ((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true; Gradient val = new Gradient(); val.SetKeys((GradientColorKey[])(object)new GradientColorKey[2] { new GradientColorKey(Color.white, 0f), new GradientColorKey(Color.white, 1f) }, (GradientAlphaKey[])(object)new GradientAlphaKey[3] { new GradientAlphaKey(0f, 0f), new GradientAlphaKey(1f, 0.3f), new GradientAlphaKey(0f, 1f) }); ((ColorOverLifetimeModule)(ref colorOverLifetime)).color = new MinMaxGradient(val); SizeOverLifetimeModule sizeOverLifetime = ps.sizeOverLifetime; ((SizeOverLifetimeModule)(ref sizeOverLifetime)).enabled = true; ((SizeOverLifetimeModule)(ref sizeOverLifetime)).size = new MinMaxCurve(1f, new AnimationCurve((Keyframe[])(object)new Keyframe[3] { new Keyframe(0f, 0.3f), new Keyframe(0.4f, 1f), new Keyframe(1f, 0f) })); ps.Play(); } private static void ConfigureLightning(ParticleSystem ps, ParticleSystemRenderer renderer, Transform visual) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_009b: 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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: 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_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0155: 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) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Expected O, but got Unknown //IL_0175: 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_0184: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Expected O, but got Unknown //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0258: 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) ps.Stop(); float value = ModConfig.BladeGlowScale.Value; renderer.renderMode = (ParticleSystemRenderMode)1; renderer.velocityScale = 0.12f; renderer.lengthScale = 3.5f; MainModule main = ps.main; ((MainModule)(ref main)).loop = true; ((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)2; ((MainModule)(ref main)).startLifetime = new MinMaxCurve(0.28f, 0.6f); ((MainModule)(ref main)).startSpeed = new MinMaxCurve(0.45f, 1.2f); ((MainModule)(ref main)).startSize = new MinMaxCurve(0.03f * value, 0.07f * value); ((MainModule)(ref main)).maxParticles = 45; ((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(0f); ((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)0; EmissionModule emission = ps.emission; ((EmissionModule)(ref emission)).enabled = true; ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(4.5f * ModConfig.BladeGlowRate.Value); ((EmissionModule)(ref emission)).SetBursts((Burst[])(object)new Burst[2] { new Burst(0f, (short)2, (short)4, 0, 0.26f), new Burst(0.13f, (short)1, (short)3, 0, 0.42f) }); ShapeModule shape = ps.shape; ((ShapeModule)(ref shape)).enabled = true; ((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)4; ((ShapeModule)(ref shape)).angle = 34f; ((ShapeModule)(ref shape)).radius = 0.05f * value; ((ShapeModule)(ref shape)).radiusThickness = 1f; ColorOverLifetimeModule colorOverLifetime = ps.colorOverLifetime; ((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true; Gradient val = new Gradient(); val.SetKeys((GradientColorKey[])(object)new GradientColorKey[2] { new GradientColorKey(Color.white, 0f), new GradientColorKey(Color.white, 1f) }, (GradientAlphaKey[])(object)new GradientAlphaKey[3] { new GradientAlphaKey(1f, 0f), new GradientAlphaKey(1f, 0.55f), new GradientAlphaKey(0f, 1f) }); ((ColorOverLifetimeModule)(ref colorOverLifetime)).color = new MinMaxGradient(val); SizeOverLifetimeModule sizeOverLifetime = ps.sizeOverLifetime; ((SizeOverLifetimeModule)(ref sizeOverLifetime)).enabled = true; ((SizeOverLifetimeModule)(ref sizeOverLifetime)).size = new MinMaxCurve(1f, new AnimationCurve((Keyframe[])(object)new Keyframe[2] { new Keyframe(0f, 1f), new Keyframe(1f, 0.2f) })); RotationOverLifetimeModule rotationOverLifetime = ps.rotationOverLifetime; ((RotationOverLifetimeModule)(ref rotationOverLifetime)).enabled = true; ((RotationOverLifetimeModule)(ref rotationOverLifetime)).z = new MinMaxCurve(-180f, 180f); ps.Play(); } private static void BuildOrbit(Renderer blade, Transform visual) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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_009f: 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_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: 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_011c: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0130: 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_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: 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) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Expected O, but got Unknown //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Expected O, but got Unknown //IL_02f8: Unknown result type (might be due to invalid IL or missing references) float value = ModConfig.BladeGlowScale.Value; GameObject val = new GameObject("GungnirBladeGlowOrbit"); val.transform.SetParent(visual, false); val.transform.localPosition = EmitterAnchor(blade, visual); _smoke = val.AddComponent(); ParticleSystemRenderer component = val.GetComponent(); component.renderMode = (ParticleSystemRenderMode)0; component.alignment = (ParticleSystemRenderSpace)0; ((Renderer)component).material = _material; ((Renderer)component).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)component).receiveShadows = false; _smoke.Stop(); MainModule main = _smoke.main; ((MainModule)(ref main)).loop = true; ((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)2; ((MainModule)(ref main)).startLifetime = new MinMaxCurve(1.4f, 2.8f); ((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(0f); ((MainModule)(ref main)).startSize = new MinMaxCurve(0.012f * value, 0.026f * value); ((MainModule)(ref main)).maxParticles = 40; ((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(0f); ((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)0; EmissionModule emission = _smoke.emission; ((EmissionModule)(ref emission)).enabled = true; ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(10f * ModConfig.BladeGlowRate.Value); ShapeModule shape = _smoke.shape; ((ShapeModule)(ref shape)).enabled = true; ((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)0; ((ShapeModule)(ref shape)).radius = 0.1f * value; ((ShapeModule)(ref shape)).radiusThickness = 0.4f; VelocityOverLifetimeModule velocityOverLifetime = _smoke.velocityOverLifetime; ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).enabled = true; ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).space = (ParticleSystemSimulationSpace)0; ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).orbitalX = new MinMaxCurve(-0.9f, 0.9f); ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).orbitalY = new MinMaxCurve(-0.9f, 0.9f); ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).orbitalZ = new MinMaxCurve(-0.9f, 0.9f); ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).radial = new MinMaxCurve(-0.01f, 0.01f); ColorOverLifetimeModule colorOverLifetime = _smoke.colorOverLifetime; ((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true; Gradient val2 = new Gradient(); val2.SetKeys((GradientColorKey[])(object)new GradientColorKey[2] { new GradientColorKey(Color.white, 0f), new GradientColorKey(Color.white, 1f) }, (GradientAlphaKey[])(object)new GradientAlphaKey[4] { new GradientAlphaKey(0f, 0f), new GradientAlphaKey(1f, 0.25f), new GradientAlphaKey(0.8f, 0.6f), new GradientAlphaKey(0f, 1f) }); ((ColorOverLifetimeModule)(ref colorOverLifetime)).color = new MinMaxGradient(val2); SizeOverLifetimeModule sizeOverLifetime = _smoke.sizeOverLifetime; ((SizeOverLifetimeModule)(ref sizeOverLifetime)).enabled = true; ((SizeOverLifetimeModule)(ref sizeOverLifetime)).size = new MinMaxCurve(1f, new AnimationCurve((Keyframe[])(object)new Keyframe[3] { new Keyframe(0f, 0.3f), new Keyframe(0.35f, 1f), new Keyframe(1f, 0.2f) })); _smoke.Play(); } private static Vector3 EmitterAnchor(Renderer blade, Transform visual) { //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_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) Bounds bounds = blade.bounds; Vector3 val = visual.InverseTransformPoint(((Bounds)(ref bounds)).center); Vector3 up = Vector3.up; return val + up * ModConfig.BladeGlowOffset.Value; } private static Material BorrowSmokeMaterial() { //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Expected O, but got Unknown if ((Object)(object)_smokeMaterial != (Object)null || _smokeSearched) { return _smokeMaterial; } _smokeSearched = true; string[] array = new string[5] { "SmokeParticleSystem", "RisingSmoke", "SmokeBlob", "SmokeBall", "vfx_Smoke" }; foreach (string text in array) { GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(text) : null); if ((Object)(object)val == (Object)null) { val = PrefabManager.Instance.GetPrefab(text); } Material val2 = (((Object)(object)val == (Object)null) ? null : (from r in val.GetComponentsInChildren(true) select ((Renderer)r).sharedMaterial).FirstOrDefault((Func)((Material m) => (Object)(object)m != (Object)null && (Object)(object)m.shader != (Object)null))); if ((Object)(object)val2 != (Object)null) { _smokeMaterial = new Material(val2); ModConfig.Trace("Smoke using material from '" + text + "'."); return _smokeMaterial; } } ModConfig.Trace("No vanilla smoke material found; falling back to the spark sprite."); return null; } private static void NeutraliseScale(Transform emitter) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_0077: 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_00a2: 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_00b0: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)emitter == (Object)null)) { Vector3 val = (((Object)(object)emitter.parent != (Object)null) ? emitter.parent.lossyScale : Vector3.one); Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(Mathf.Approximately(val.x, 0f) ? 1f : (1f / val.x), Mathf.Approximately(val.y, 0f) ? 1f : (1f / val.y), Mathf.Approximately(val.z, 0f) ? 1f : (1f / val.z)); if (emitter.localScale != val2) { emitter.localScale = val2; } } } private static void Tint(Color colour) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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) Color val = colour * ModConfig.BladeGlowBrightness.Value; val.a = 1f; MainModule main = _system.main; ((MainModule)(ref main)).startColor = new MinMaxGradient(val, colour); if ((Object)(object)_material == (Object)null) { return; } string[] array = new string[4] { "_TintColor", "_Color", "_BaseColor", "_EmissionColor" }; foreach (string text in array) { if (_material.HasProperty(text)) { _material.SetColor(text, val); } } } private static bool TryMountVanillaEffect(Renderer blade) { //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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_0093: 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) string value = ModConfig.BladeGlowPrefab.Value; if (string.IsNullOrEmpty(value)) { return false; } GameObject val = FindEffectPrefab(value); if ((Object)(object)val == (Object)null) { GungnirStaffPlugin.Log.LogWarning((object)("Effect prefab '" + value + "' not found; using the mod's own particles. Try one of the names listed in the setting's description.")); return false; } GameObject val2 = Object.Instantiate(val, ((Component)blade).transform); ((Object)val2).name = "GungnirBladeGlow"; Transform transform = val2.transform; Transform transform2 = ((Component)blade).transform; Bounds bounds = blade.bounds; transform.localPosition = transform2.InverseTransformPoint(((Bounds)(ref bounds)).center); val2.transform.localRotation = Quaternion.identity; val2.transform.localScale = Vector3.one * ModConfig.BladeGlowScale.Value; ZNetView[] componentsInChildren = val2.GetComponentsInChildren(true); foreach (ZNetView val3 in componentsInChildren) { Object.Destroy((Object)(object)val3); } TimedDestruction[] componentsInChildren2 = val2.GetComponentsInChildren(true); foreach (TimedDestruction val4 in componentsInChildren2) { Object.Destroy((Object)(object)val4); } AudioSource[] componentsInChildren3 = val2.GetComponentsInChildren(true); foreach (AudioSource val5 in componentsInChildren3) { ((Behaviour)val5).enabled = false; } _mounted = val2; ModConfig.Trace("Mounted vanilla effect '" + ((Object)val).name + "' on the blade."); return true; } private static GameObject FindEffectPrefab(string name) { ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance != (Object)null) { GameObject prefab = instance.GetPrefab(name); if ((Object)(object)prefab != (Object)null) { return prefab; } } return PrefabManager.Instance.GetPrefab(name); } private static Renderer FindBlade(Transform visual) { return ((IEnumerable)((Component)visual).GetComponentsInChildren(true)).FirstOrDefault((Func)((Renderer r) => ((Object)((Component)r).gameObject).name.StartsWith("Gungnir_Blade", StringComparison.OrdinalIgnoreCase))); } private static Material BorrowParticleMaterial(GameObject weapon) { //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Expected O, but got Unknown //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Expected O, but got Unknown Material val = (((Object)(object)weapon == (Object)null) ? null : (from r in weapon.GetComponentsInChildren(true) select ((Renderer)r).sharedMaterial).FirstOrDefault((Func)((Material m) => (Object)(object)m != (Object)null && (Object)(object)m.shader != (Object)null))); if ((Object)(object)val == (Object)null && (Object)(object)ObjectDB.instance != (Object)null) { val = (from r in ObjectDB.instance.m_items.Where((GameObject p) => (Object)(object)p != (Object)null).SelectMany((GameObject p) => p.GetComponentsInChildren(true)) select ((Renderer)r).sharedMaterial).FirstOrDefault((Func)((Material m) => (Object)(object)m != (Object)null && (Object)(object)m.shader != (Object)null)); } if ((Object)(object)val != (Object)null) { return new Material(val); } Shader val2 = Shader.Find("Particles/Standard Unlit") ?? Shader.Find("Sprites/Default"); if (!((Object)(object)val2 != (Object)null)) { return null; } return new Material(val2); } } internal sealed class GungnirCommand : ConsoleCommand { public override string Name => "gungnir"; public override string Help => "gungnir status | empty | recover | staffs | holster | find | give [level]"; public override bool IsCheat => false; public override List CommandOptionList() { return new List { "status", "empty", "recover", "staffs", "holster", "find", "give" }; } public override void Run(string[] args) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { Print("You need to be in a world first."); return; } switch ((args != null && args.Length != 0) ? args[0].ToLowerInvariant() : "status") { case "give": Give(localPlayer, (args.Length > 1) ? args[1] : null); break; case "staffs": ListStaffs(); break; case "holster": Holster(localPlayer); break; case "find": Find((args.Length > 1) ? args[1] : string.Empty); break; case "empty": Empty(localPlayer); break; case "recover": Recover(localPlayer); break; default: Status(localPlayer); break; } } private static bool SpawningAllowed() { if (Environment.GetCommandLineArgs().Any((string a) => string.Equals(a, "-console", StringComparison.OrdinalIgnoreCase))) { return Terminal.m_cheat; } return false; } private static void Give(Player player, string levelArg) { if (!SpawningAllowed()) { Print("Spawning Gungnir needs a dev session: launch with -console and enable devcommands. Craft it at the Galdr Table instead."); return; } int result = 1; if (!string.IsNullOrEmpty(levelArg) && (!int.TryParse(levelArg, out result) || result < 1 || result > 3)) { Print($"Usage: gungnir give [1-{3}] " + "(got '" + levelArg + "')"); return; } if (!GungnirItem.Create()) { Print("Could not create the Gungnir prefab - see the BepInEx log."); return; } ItemData val = ((Humanoid)player).m_inventory.AddItem("GungnirStaff", 1, result, 0, 0L, string.Empty, false); if (val == null) { Print("No room in your inventory."); return; } StaffContainer staffContainer = StaffContainer.For(val); if (staffContainer != null) { staffContainer.OwnQuality = result; } Print($"Added a Gungnir to your inventory (level {result}, " + $"{GungnirRecipe.SlotsForQuality(result)} rack slots)."); } private static void ListStaffs() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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) List list = StaffRegistry.AllStaffPrefabs(); Print($"Detected {list.Count} staff(s):"); foreach (GameObject item in list) { SharedData shared = item.GetComponent().m_itemData.m_shared; Print($" {((Object)item).name} ({shared.m_skillType}, {shared.m_itemType}, " + $"held as {shared.m_animationState})"); } } private static void Find(string text) { if (string.IsNullOrEmpty(text)) { Print("Usage: gungnir find "); return; } List list = (from p in ObjectDB.instance.m_items where (Object)(object)p != (Object)null && ((Object)p).name.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0 select ((Object)p).name into n orderby n select n).ToList(); Print($"{list.Count} item prefab(s) matching '{text}':"); foreach (string item in list) { Print(" " + item); } } private static void Holster(Player player) { ItemData val = GungnirItem.Active(player); if (val == null) { Print("No Gungnir active."); return; } StaffSwitcher.Holster(player, val); Print("Holstered."); } private static void Empty(Player player) { ItemData val = GungnirItem.Active(player); if (val == null) { Print($"No Gungnir active (Activation = {ModConfig.Activation.Value})."); return; } StaffSwitcher.Holster(player, val); StaffContainer staffContainer = StaffContainer.For(val); int num = 0; int num2 = 0; for (int i = 0; i < staffContainer.Inventory.m_width; i++) { ItemData val2 = staffContainer.ItemAt(i); if (val2 == null) { continue; } if (!((Humanoid)player).m_inventory.HaveEmptySlot()) { num2++; continue; } staffContainer.Inventory.RemoveItem(val2); if (((Humanoid)player).m_inventory.AddItem(val2)) { num++; continue; } staffContainer.Inventory.AddItem(val2); num2++; } staffContainer.SaveToItem(); Print($"Moved {num} staff(s) out of the rack into your inventory."); if (num2 > 0) { Print($"{num2} could not be moved - no room. Free some slots and run it again."); } } private static void Recover(Player player) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) int num = 0; int num2 = 0; ItemDrop[] array = Resources.FindObjectsOfTypeAll(); foreach (ItemDrop val in array) { if ((Object)(object)val == (Object)null || val.m_itemData == null) { continue; } GameObject gameObject = ((Component)val).gameObject; if (gameObject.activeInHierarchy || (Object)(object)gameObject.transform.parent != (Object)null) { continue; } Scene scene = gameObject.scene; if (!((Scene)(ref scene)).IsValid() || gameObject == GungnirItem.Prefab || !GungnirItem.IsGungnir(val.m_itemData)) { continue; } num++; if (((Humanoid)player).m_inventory.HaveEmptySlot()) { ItemData itemData = val.m_itemData; GungnirItem.RepairDropPrefab(itemData); if (((Humanoid)player).m_inventory.AddItem(itemData)) { num2++; Object.Destroy((Object)(object)gameObject); } } } if (num == 0) { Print("No stranded Gungnirs in this world. Anything dropped before a relog is gone for good - it was never written to the save."); return; } Print($"Found {num} stranded Gungnir(s); returned {num2} to your inventory."); if (num2 < num) { Print("The rest need free inventory slots. Make room and run it again."); } } private static void Status(Player player) { Print(Alive.StatusLine(GungnirStaffPlugin.Instance?.Harmony)); ItemData val = GungnirItem.Active(player); if (val == null) { Print("No Gungnir active " + $"(Activation = {ModConfig.Activation.Value}). Try 'gungnir give'."); return; } StaffContainer staffContainer = StaffContainer.For(val); int ownQuality = staffContainer.OwnQuality; Print($"Level {ownQuality}/{3} " + $"-> {GungnirRecipe.SlotsForQuality(ownQuality)} rack slots"); PrintDamage(val); Print("Selected slot: " + ((staffContainer.SelectedSlot < 0) ? "none" : (staffContainer.SelectedSlot + 1).ToString())); Print($"Bar contents ({staffContainer.Inventory.m_width} slots):"); for (int i = 0; i < staffContainer.Inventory.m_width; i++) { ItemData val2 = staffContainer.ItemAt(i); Print(string.Format(" {0}: {1}", i + 1, (val2 == null) ? "-" : (val2.m_shared.m_name + " (lvl " + val2.m_quality + ")"))); } } private static void PrintDamage(ItemData gungnir) { //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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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_0060: 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_0084: 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) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) DamageTypes damage = gungnir.GetDamage(); List parts = new List(); Add("generic", damage.m_damage); Add("pierce", damage.m_pierce); Add("slash", damage.m_slash); Add("blunt", damage.m_blunt); Add("lightning", damage.m_lightning); Add("fire", damage.m_fire); Add("frost", damage.m_frost); Add("poison", damage.m_poison); Add("spirit", damage.m_spirit); Print($"Base damage every hit: {((DamageTypes)(ref damage)).GetTotalDamage():0.#} " + "(" + ((parts.Count > 0) ? string.Join(", ", parts.ToArray()) : "none") + ")"); Attack val = gungnir.m_shared?.m_secondaryAttack; if (val != null) { Print($" secondary x{val.m_damageMultiplier:0.##} " + $"-> {((DamageTypes)(ref damage)).GetTotalDamage() * val.m_damageMultiplier:0.#}"); } Print($"Storm touch: {ModConfig.LightningChance.Value:P0} chance to ADD " + $"{ModConfig.LightningDamage.Value:0.#} lightning on top, with its " + "effect and sound. A failed roll changes nothing about the hit."); SharedData shared = gungnir.m_shared; int num = Count(shared?.m_hitEffect) + Count(shared?.m_attack?.m_hitEffect); Print($"Hit feedback: {num} effect(s) on impact, " + $"{Count(shared?.m_startEffect) + Count(shared?.m_attack?.m_startEffect)} on swing" + ((num == 0) ? " <- SILENT: no impact sound or spark" : string.Empty)); void Add(string label, float value) { if (value > 0f) { parts.Add($"{label} {value:0.#}"); } } } private static int Count(EffectList list) { return (list?.m_effectPrefabs?.Length).GetValueOrDefault(); } private static void Print(string text) { Alive.ToGameConsole(text); GungnirStaffPlugin.Log.LogInfo((object)text); } internal static void Register() { if (!CommandManager.Instance.CustomCommands.Any((ConsoleCommand c) => c.Name == "gungnir")) { CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new GungnirCommand()); } } } internal static class CrystalColors { private const string Section = "Crystal colours"; private static readonly Dictionary Defaults = new Dictionary { { "StaffShield", "#FF0A2E" }, { "StaffRedTroll", "#FF2ECC" }, { "StaffSkeleton", "#6A0DAD" }, { "StaffLightning", "#6A5BFF" }, { "StaffIceShards", "#00D4FF" }, { "StaffGreenRoots", "#35FF00" }, { "StaffClusterbomb", "#FFE100" }, { "StaffFireball", "#FF6600" } }; private static readonly Dictionary> Bound = new Dictionary>(); private static ConfigFile _config; internal static ConfigEntry Idle; internal static ConfigEntry Fallback; internal static ConfigEntry GlowIntensity; internal static ConfigEntry GlowRange; internal static void Bind(ConfigFile config) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Expected O, but got Unknown _config = config; Bound.Clear(); Idle = config.Bind("Crystal colours", "NoStaffSelected", "#FFC24A", "Crystal colour when no staff is selected - Gungnir's own idle glow."); Fallback = config.Bind("Crystal colours", "UnknownStaff", "#FFFFFF", "Crystal colour for a staff with no entry of its own, e.g. one added by another mod. Its own entry appears here once the game has seen it."); GlowIntensity = config.Bind("Crystal colours", "GlowIntensity", 1.6f, new ConfigDescription("Brightness of the light the crystal casts. 0 turns the light off and leaves only the material tint.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 8f), Array.Empty())); GlowRange = config.Bind("Crystal colours", "GlowRange", 3.5f, new ConfigDescription("How far the crystal's light reaches, in metres.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 20f), Array.Empty())); } internal static Color For(ItemData staff) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) if (staff == null) { return Parse(Idle.Value, new Color(1f, 0.76f, 0.29f)); } string text = PrefabNameOf(staff); if (string.IsNullOrEmpty(text)) { return Parse(Fallback.Value, new Color(0.79f, 0.64f, 0.15f)); } if (!Bound.TryGetValue(text, out var value)) { Defaults.TryGetValue(text, out var value2); value = _config.Bind("Crystal colours", text, value2 ?? Fallback.Value, "Crystal colour while " + text + " is selected. Hex, e.g. #FF6A18."); Bound[text] = value; } return Parse(value.Value, Parse(Fallback.Value, Color.white)); } private static string PrefabNameOf(ItemData item) { if ((Object)(object)item.m_dropPrefab != (Object)null) { return ((Object)item.m_dropPrefab).name; } return item.m_shared?.m_name; } private static Color Parse(string hex, Color fallback) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) Color result = default(Color); if (!string.IsNullOrEmpty(hex) && ColorUtility.TryParseHtmlString(hex.Trim(), ref result)) { return result; } return fallback; } } internal static class CrystalGlow { internal const string CrystalObjectName = "Gungnir_Crystal"; private const string GlowObjectName = "GungnirCrystalGlow"; private static Light _light; private static Material _tinted; private static Color _applied = Color.clear; internal static void Apply(Player player, ItemData gungnir) { //IL_0038: 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_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: 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_00ab: 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) GameObject val = FindHeldObject(player); if ((Object)(object)val == (Object)null) { Clear(); return; } StaffContainer staffContainer = StaffContainer.For(gungnir); int num = staffContainer?.SelectedSlot ?? (-1); Color val2 = CrystalColors.For((num >= 0) ? staffContainer.ItemAt(num) : null); EnsureLight(val); if ((Object)(object)_light != (Object)null) { _light.color = val2; _light.intensity = (ModConfig.Enabled.Value ? CrystalColors.GlowIntensity.Value : 0f); _light.range = CrystalColors.GlowRange.Value; } if (_applied != val2) { TintCrystal(val, val2); _applied = val2; } Renderer crystal = FindCrystal(val); CrystalParticles.Apply(crystal, val, player, val2, num >= 0); } internal static void Clear() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_light != (Object)null) { Object.Destroy((Object)(object)((Component)_light).gameObject); } CrystalParticles.Clear(); _light = null; _tinted = null; _applied = Color.clear; } private static GameObject FindHeldObject(Player player) { VisEquipment val = ((Humanoid)(player?)).m_visEquipment; if ((Object)(object)val == (Object)null) { return null; } GameObject rightItemInstance = val.m_rightItemInstance; if ((Object)(object)rightItemInstance != (Object)null && (Object)(object)FindCrystal(rightItemInstance) != (Object)null) { return rightItemInstance; } GameObject leftItemInstance = val.m_leftItemInstance; if ((Object)(object)leftItemInstance != (Object)null && (Object)(object)FindCrystal(leftItemInstance) != (Object)null) { return leftItemInstance; } return rightItemInstance ?? leftItemInstance; } private static void EnsureLight(GameObject attach) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_light != (Object)null) || !((Component)_light).transform.IsChildOf(attach.transform)) { if ((Object)(object)_light != (Object)null) { Object.Destroy((Object)(object)((Component)_light).gameObject); } GameObject val = new GameObject("GungnirCrystalGlow"); val.transform.SetParent(attach.transform, false); Renderer val2 = FindCrystal(attach); Transform transform = val.transform; Vector3 position; if (!((Object)(object)val2 != (Object)null)) { position = attach.transform.position; } else { Bounds bounds = val2.bounds; position = ((Bounds)(ref bounds)).center; } transform.position = position; _light = val.AddComponent(); _light.type = (LightType)2; _light.shadows = (LightShadows)0; _light.renderMode = (LightRenderMode)2; } } private static Renderer FindCrystal(GameObject attach) { Renderer[] componentsInChildren = attach.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if (((Object)((Component)val).gameObject).name.StartsWith("Gungnir_Crystal", StringComparison.Ordinal)) { return val; } } return null; } private static void TintCrystal(GameObject attach, Color colour) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) Renderer val = FindCrystal(attach); if (!((Object)(object)val == (Object)null)) { if ((Object)(object)_tinted == (Object)null || (Object)(object)val.material != (Object)(object)_tinted) { _tinted = val.material; } if (_tinted.HasProperty("_Color")) { _tinted.SetColor("_Color", colour); } if (_tinted.HasProperty("_EmissionColor")) { _tinted.EnableKeyword("_EMISSION"); _tinted.SetColor("_EmissionColor", colour * CrystalColors.GlowIntensity.Value); } } } } internal static class CrystalParticles { private const string OrbitName = "GungnirCrystalOrbit"; private const string SparkName = "GungnirCrystalSparks"; private static ParticleSystem _orbit; private static ParticleSystem _sparks; private static Material _material; private static Color _applied = Color.clear; internal static void Apply(Renderer crystal, GameObject weapon, Player player, Color colour, bool staffStance) { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: 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_00ad: 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) if (ModConfig.CrystalParticles.Value switch { CrystalParticleMode.Always => 1, CrystalParticleMode.Never => 0, _ => staffStance ? 1 : 0, } == 0 || (Object)(object)crystal == (Object)null) { Clear(); return; } if ((Object)(object)_orbit == (Object)null || !((Component)_orbit).transform.IsChildOf(((Component)crystal).transform)) { Clear(); Build(crystal, weapon, player); } if (!((Object)(object)_orbit == (Object)null)) { HoldSize(((Component)_orbit).transform); HoldSize(((Object)(object)_sparks != (Object)null) ? ((Component)_sparks).transform : null); if (_applied != colour) { _applied = colour; Tint(colour); } } } internal static void Clear() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_orbit != (Object)null) { Object.DestroyImmediate((Object)(object)((Component)_orbit).gameObject); } if ((Object)(object)_sparks != (Object)null) { Object.DestroyImmediate((Object)(object)((Component)_sparks).gameObject); } _orbit = null; _sparks = null; _material = null; _applied = Color.clear; } private static void Build(Renderer crystal, GameObject weapon, Player player) { //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_005d: 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) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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) try { VisEquipment val = (((Object)(object)player != (Object)null) ? ((Humanoid)player).m_visEquipment : null); PurgeStrays(weapon); if ((Object)(object)val != (Object)null) { PurgeStrays(val.m_rightItemInstance); PurgeStrays(val.m_leftItemInstance); } _material = BorrowParticleMaterial(weapon); float value = ModConfig.CrystalParticleScale.Value; Transform transform = ((Component)crystal).transform; Bounds bounds = crystal.bounds; Vector3 anchor = transform.InverseTransformPoint(((Bounds)(ref bounds)).center); _orbit = MakeSystem(((Component)crystal).transform, "GungnirCrystalOrbit", anchor); ConfigureOrbit(_orbit, value); _sparks = MakeSystem(((Component)crystal).transform, "GungnirCrystalSparks", anchor); ConfigureSparks(_sparks, value); ModConfig.Trace("Crystal particle systems created."); } catch (Exception arg) { GungnirStaffPlugin.Log.LogError((object)$"Could not build crystal particles: {arg}"); Clear(); } } private static ParticleSystem MakeSystem(Transform parent, string name, Vector3 anchor) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_001a: 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) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); val.transform.localPosition = anchor; val.transform.localRotation = Quaternion.identity; HoldSize(val.transform); ParticleSystem result = val.AddComponent(); ParticleSystemRenderer component = val.GetComponent(); component.renderMode = (ParticleSystemRenderMode)0; component.alignment = (ParticleSystemRenderSpace)0; ((Renderer)component).material = _material; ((Renderer)component).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)component).receiveShadows = false; return result; } private static void ConfigureOrbit(ParticleSystem ps, float scale) { //IL_0007: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: 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_00ac: 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) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: 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_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) ps.Stop(); MainModule main = ps.main; ((MainModule)(ref main)).loop = true; ((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)2; ((MainModule)(ref main)).startLifetime = new MinMaxCurve(1.6f, 3.2f); ((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(0f); ((MainModule)(ref main)).startSize = new MinMaxCurve(0.012f * scale, 0.024f * scale); ((MainModule)(ref main)).maxParticles = 60; ((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(0f); ((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)0; EmissionModule emission = ps.emission; ((EmissionModule)(ref emission)).enabled = true; ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(14f * ModConfig.CrystalParticleRate.Value); ShapeModule shape = ps.shape; ((ShapeModule)(ref shape)).enabled = true; ((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)0; ((ShapeModule)(ref shape)).radius = 0.115f * scale; ((ShapeModule)(ref shape)).radiusThickness = 0.45f; VelocityOverLifetimeModule velocityOverLifetime = ps.velocityOverLifetime; ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).enabled = true; ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).space = (ParticleSystemSimulationSpace)0; ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).orbitalX = new MinMaxCurve(-1.1f, 1.1f); ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).orbitalY = new MinMaxCurve(-1.1f, 1.1f); ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).orbitalZ = new MinMaxCurve(-1.1f, 1.1f); ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).radial = new MinMaxCurve(-0.012f, 0.012f); FadeInOut(ps); ShrinkOverLife(ps, 1f, 0.25f); ps.Play(); } private static void ConfigureSparks(ParticleSystem ps, float scale) { //IL_0007: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: 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) ps.Stop(); MainModule main = ps.main; ((MainModule)(ref main)).loop = true; ((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)2; ((MainModule)(ref main)).startLifetime = new MinMaxCurve(0.45f, 0.9f); ((MainModule)(ref main)).startSpeed = new MinMaxCurve(0.35f, 0.9f); ((MainModule)(ref main)).startSize = new MinMaxCurve(0.008f * scale, 0.018f * scale); ((MainModule)(ref main)).maxParticles = 40; ((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(0.02f); ((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1; EmissionModule emission = ps.emission; ((EmissionModule)(ref emission)).enabled = true; ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(3f * ModConfig.CrystalParticleRate.Value); ((EmissionModule)(ref emission)).SetBursts((Burst[])(object)new Burst[1] { new Burst(0f, (short)3, (short)6, 0, 0.85f) }); ShapeModule shape = ps.shape; ((ShapeModule)(ref shape)).enabled = true; ((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)0; ((ShapeModule)(ref shape)).radius = 0.035f * scale; ((ShapeModule)(ref shape)).radiusThickness = 1f; VelocityOverLifetimeModule velocityOverLifetime = ps.velocityOverLifetime; ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).enabled = true; ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).space = (ParticleSystemSimulationSpace)0; ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).radial = new MinMaxCurve(0.05f, 0.25f); FadeInOut(ps); ShrinkOverLife(ps, 1f, 0f); ps.Play(); } private static void HoldSize(Transform t) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_003a: 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_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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: 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) if ((Object)(object)t == (Object)null) { return; } Transform parent = t.parent; Vector3 val = (((Object)(object)parent != (Object)null) ? parent.lossyScale : Vector3.one); if (!Mathf.Approximately(val.x, 0f) && !Mathf.Approximately(val.y, 0f) && !Mathf.Approximately(val.z, 0f)) { Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(1f / val.x, 1f / val.y, 1f / val.z); if (t.localScale != val2) { t.localScale = val2; } } } private static void PurgeStrays(GameObject root) { if ((Object)(object)root == (Object)null) { return; } ParticleSystem[] componentsInChildren = root.GetComponentsInChildren(true); foreach (ParticleSystem val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && val != _orbit && val != _sparks) { string name = ((Object)((Component)val).gameObject).name; if (name.StartsWith("GungnirCrystalOrbit", StringComparison.Ordinal) || name.StartsWith("GungnirCrystalSparks", StringComparison.Ordinal)) { Object.DestroyImmediate((Object)(object)((Component)val).gameObject); } } } } private static void FadeInOut(ParticleSystem ps) { //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_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_005f: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_009c: 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_00ae: Unknown result type (might be due to invalid IL or missing references) ColorOverLifetimeModule colorOverLifetime = ps.colorOverLifetime; ((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true; Gradient val = new Gradient(); val.SetKeys((GradientColorKey[])(object)new GradientColorKey[2] { new GradientColorKey(Color.white, 0f), new GradientColorKey(Color.white, 1f) }, (GradientAlphaKey[])(object)new GradientAlphaKey[4] { new GradientAlphaKey(0f, 0f), new GradientAlphaKey(1f, 0.25f), new GradientAlphaKey(0.85f, 0.6f), new GradientAlphaKey(0f, 1f) }); ((ColorOverLifetimeModule)(ref colorOverLifetime)).color = new MinMaxGradient(val); } private static void ShrinkOverLife(ParticleSystem ps, float from, float to) { //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_0030: 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) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) SizeOverLifetimeModule sizeOverLifetime = ps.sizeOverLifetime; ((SizeOverLifetimeModule)(ref sizeOverLifetime)).enabled = true; AnimationCurve val = new AnimationCurve((Keyframe[])(object)new Keyframe[3] { new Keyframe(0f, (to > 0f) ? 0.4f : 0.2f), new Keyframe(0.3f, from), new Keyframe(1f, to) }); ((SizeOverLifetimeModule)(ref sizeOverLifetime)).size = new MinMaxCurve(1f, val); } private static void Tint(Color colour) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_0051: 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) Color val = colour * ModConfig.CrystalParticleBrightness.Value; val.a = 1f; ParticleSystem[] array = (ParticleSystem[])(object)new ParticleSystem[2] { _orbit, _sparks }; foreach (ParticleSystem val2 in array) { if (!((Object)(object)val2 == (Object)null)) { MainModule main = val2.main; ((MainModule)(ref main)).startColor = new MinMaxGradient(val, colour); } } if ((Object)(object)_material == (Object)null) { return; } string[] array2 = new string[4] { "_TintColor", "_Color", "_BaseColor", "_EmissionColor" }; foreach (string text in array2) { if (_material.HasProperty(text)) { _material.SetColor(text, val); } } } private static Material BorrowParticleMaterial(GameObject weapon) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown Material val = (((Object)(object)weapon == (Object)null) ? null : (from r in weapon.GetComponentsInChildren(true) select ((Renderer)r).sharedMaterial).FirstOrDefault((Func)((Material m) => (Object)(object)m != (Object)null && (Object)(object)m.shader != (Object)null))); if ((Object)(object)val != (Object)null) { return new Material(val); } Shader val2 = Shader.Find("Particles/Standard Unlit") ?? Shader.Find("Legacy Shaders/Particles/Additive") ?? Shader.Find("Sprites/Default"); if ((Object)(object)val2 == (Object)null) { GungnirStaffPlugin.Log.LogWarning((object)"No particle shader available; crystal motes may not render."); return null; } return new Material(val2); } } internal static class GungnirBar { private const string SlotKeyLabelName = "GungnirSlotKey"; private static GameObject _root; private static InventoryGrid _grid; private static Inventory _bound; private static readonly List _slotKeyLabels = new List(); private static int _labelledSlots = -1; private static bool _dragging; private static Vector2 _dragGrabPoint; private static Vector2 _dragStartPosition; private static Vector2 _dragPosition; private static bool _writingOwnPosition; internal static InventoryGrid Grid => _grid; internal static StaffContainer Container { get; private set; } internal static void Refresh(Player player) { InventoryGui instance = InventoryGui.m_instance; if ((Object)(object)instance == (Object)null || (Object)(object)player == (Object)null) { Hide(); return; } ItemData val = GungnirItem.Active(player); if (!ShouldShow(val)) { Hide(); } else { if ((Object)(object)_grid == (Object)null && !Build(instance)) { return; } Container = ((val != null) ? StaffContainer.For(val) : null); if (Container == null) { Hide(); return; } if (!_root.activeSelf) { _root.SetActive(true); } UpdateDrag(); ApplyLayout(); _bound = Container.Inventory; _grid.UpdateInventory(_bound, player, instance.m_dragItem); SyncSlotKeyLabels(); HighlightSelected(); } } private static bool ShouldShow(ItemData gungnir) { switch (ModConfig.Visibility.Value) { case BarVisibility.Always: return true; case BarVisibility.InventoryOnly: if (gungnir != null) { return InventoryGui.IsVisible(); } return false; default: return gungnir != null; } } private static void Hide() { EndDrag(commit: false); Container = null; if ((Object)(object)_root != (Object)null && _root.activeSelf) { _root.SetActive(false); } } internal static void Teardown() { if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } _dragging = false; _root = null; _grid = null; _bound = null; Container = null; _slotKeyLabels.Clear(); _labelledSlots = -1; } private static void SyncSlotKeyLabels() { List elements = _grid.m_elements; if (!ModConfig.ShowSlotKeys.Value || elements == null) { if (_slotKeyLabels.Count > 0) { ClearSlotKeyLabels(); } } else { if (LabelsAreCurrent(elements.Count)) { return; } ClearSlotKeyLabels(); for (int i = 0; i < elements.Count; i++) { TMP_Text val = BuildSlotKeyLabel(elements[i], i); if ((Object)(object)val != (Object)null) { _slotKeyLabels.Add(val); } } _labelledSlots = elements.Count; ModConfig.Trace($"Built {_slotKeyLabels.Count} shortcut label(s) for {elements.Count} slot(s)."); } } private static bool LabelsAreCurrent(int slots) { if (_labelledSlots != slots) { return false; } foreach (TMP_Text slotKeyLabel in _slotKeyLabels) { if ((Object)(object)slotKeyLabel == (Object)null) { return false; } } return true; } private static void ClearSlotKeyLabels() { foreach (TMP_Text slotKeyLabel in _slotKeyLabels) { if ((Object)(object)slotKeyLabel != (Object)null) { Object.Destroy((Object)(object)((Component)slotKeyLabel).gameObject); } } _slotKeyLabels.Clear(); _labelledSlots = -1; } private static TMP_Text BuildSlotKeyLabel(Element element, int slot) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: 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_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0123: 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) TMP_Text val = element?.m_amount; if ((Object)(object)val == (Object)null || (Object)(object)element.m_go == (Object)null || slot >= 8) { return null; } string text = Inputs.ShortLabel(ModConfig.SlotKeys[slot].Value); if (string.IsNullOrEmpty(text)) { return null; } GameObject val2 = Object.Instantiate(((Component)val).gameObject, element.m_go.transform); ((Object)val2).name = "GungnirSlotKey"; val2.SetActive(true); TMP_Text component = val2.GetComponent(); if ((Object)(object)component == (Object)null) { Object.Destroy((Object)(object)val2); return null; } float num = SlotHeight(element); Transform transform = val2.transform; RectTransform val3 = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)val3 != (Object)null) { val3.anchorMin = new Vector2(0.5f, 0f); val3.anchorMax = new Vector2(0.5f, 0f); val3.pivot = new Vector2(0.5f, 1f); val3.anchoredPosition = new Vector2(0f, (0f - num) * 0.04f); val3.sizeDelta = new Vector2(num * 1.6f, num * 0.4f); ((Transform)val3).localScale = Vector3.one; ((Transform)val3).localRotation = Quaternion.identity; } ((Behaviour)component).enabled = true; component.text = text; component.fontSize = num * 0.26f * ModConfig.SlotKeyScale.Value; component.enableAutoSizing = false; component.alignment = (TextAlignmentOptions)258; component.textWrappingMode = (TextWrappingModes)0; component.overflowMode = (TextOverflowModes)0; ((Graphic)component).color = new Color(1f, 1f, 1f, 0.7f); ((Graphic)component).raycastTarget = false; return component; } private static float SlotHeight(Element element) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) Transform transform = element.m_go.transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); float num; if (!((Object)(object)val != (Object)null)) { num = 0f; } else { Rect rect = val.rect; num = ((Rect)(ref rect)).height; } float num2 = num; if (!(num2 > 1f)) { return 64f; } return num2; } private static bool Build(InventoryGui gui) { InventoryGrid playerGrid = gui.m_playerGrid; Transform val = FindAlwaysActiveUiRoot(gui); if ((Object)(object)playerGrid == (Object)null || (Object)(object)val == (Object)null) { return false; } try { _root = Object.Instantiate(((Component)playerGrid).gameObject, val); ((Object)_root).name = "GungnirStaffBar"; _root.transform.SetAsLastSibling(); _grid = _root.GetComponent(); if ((Object)(object)_grid == (Object)null) { Teardown(); return false; } MakeSelfSufficient(); ClearClonedSlots(); _grid.m_onSelected = null; _grid.m_onRightClick = null; InventoryGrid grid = _grid; grid.m_onSelected = (Action)Delegate.Combine(grid.m_onSelected, new Action(OnSelected)); InventoryGrid grid2 = _grid; grid2.m_onRightClick = (Action)Delegate.Combine(grid2.m_onRightClick, new Action(OnRightClick)); ModConfig.Trace("Staff bar created under '" + ((Object)val).name + "'."); return true; } catch (Exception arg) { GungnirStaffPlugin.Log.LogError((object)$"Could not build the staff bar: {arg}"); Teardown(); return false; } } private static Transform FindAlwaysActiveUiRoot(InventoryGui gui) { GameObject val = (((Object)(object)Hud.m_instance != (Object)null) ? Hud.m_instance.m_rootObject : null); if ((Object)(object)val != (Object)null) { return val.transform; } Canvas componentInParent = ((Component)gui).GetComponentInParent(); Canvas val2 = (((Object)(object)componentInParent != (Object)null) ? componentInParent.rootCanvas : null); if (!((Object)(object)val2 != (Object)null)) { return ((Component)gui).transform.root; } return ((Component)val2).transform; } private static void MakeSelfSufficient() { Canvas val = _root.GetComponent(); if ((Object)(object)val == (Object)null) { val = _root.AddComponent(); } Canvas val2 = (((Object)(object)InventoryGui.m_instance != (Object)null) ? ((Component)InventoryGui.m_instance).GetComponentInParent() : null); int num = (((Object)(object)val2 != (Object)null) ? val2.sortingOrder : 0); val.overrideSorting = true; val.sortingOrder = num + 5; ModConfig.Trace($"Rack canvas sortingOrder {val.sortingOrder} " + $"(inventory canvas is {num})."); if ((Object)(object)_root.GetComponent() == (Object)null) { _root.AddComponent(); } } private static void ClearClonedSlots() { _grid.m_elements?.Clear(); RectTransform gridRoot = _grid.m_gridRoot; if (!((Object)(object)gridRoot == (Object)null)) { for (int num = ((Transform)gridRoot).childCount - 1; num >= 0; num--) { Object.DestroyImmediate((Object)(object)((Component)((Transform)gridRoot).GetChild(num)).gameObject); } } } internal static void OnLayoutSettingChanged() { if (!_writingOwnPosition) { Teardown(); } } private static void UpdateDrag() { //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_006c: 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_0080: 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_0043: 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) int value = ModConfig.MoveBarMouseButton.Value; if (value < 0 || !InventoryGui.IsVisible()) { EndDrag(commit: false); } else if (!_dragging) { if (ZInput.GetMouseButtonDown(value) && PointerIsOverSlots() && TryPointerInParent(out var point)) { _dragging = true; _dragGrabPoint = point; _dragStartPosition = ConfiguredPosition(); _dragPosition = _dragStartPosition; } } else { if (TryPointerInParent(out var point2)) { _dragPosition = ClampToRange(_dragStartPosition + (point2 - _dragGrabPoint)); } if (!ZInput.GetMouseButton(value)) { EndDrag(commit: true); } } } private static void EndDrag(bool commit) { if (!_dragging) { return; } _dragging = false; if (commit) { _writingOwnPosition = true; try { ModConfig.BarOffsetX.Value = Mathf.Round(_dragPosition.x); ModConfig.BarOffsetY.Value = Mathf.Round(_dragPosition.y); } finally { _writingOwnPosition = false; } ModConfig.Trace($"Staff bar moved to {ModConfig.BarOffsetX.Value}, {ModConfig.BarOffsetY.Value}."); } } private static bool TryPointerInParent(out Vector2 point) { //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_0050: 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) //IL_0067: Unknown result type (might be due to invalid IL or missing references) point = Vector2.zero; RectTransform val = (RectTransform)(((Object)(object)_root != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val == (Object)null) { return false; } Canvas component = _root.GetComponent(); Camera val2 = (((Object)(object)component != (Object)null && (int)component.renderMode != 0) ? component.worldCamera : null); return RectTransformUtility.ScreenPointToLocalPointInRectangle(val, Vector2.op_Implicit(ZInput.mousePosition), val2, ref point); } private static Vector2 ConfiguredPosition() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) return new Vector2(ModConfig.BarOffsetX.Value, ModConfig.BarOffsetY.Value); } private static Vector2 ClampToRange(Vector2 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) return new Vector2(Mathf.Clamp(position.x, -2000f, 2000f), Mathf.Clamp(position.y, -2000f, 2000f)); } private static void ApplyLayout() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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) Transform transform = _root.transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); if (!((Object)(object)val == (Object)null)) { val.anchorMin = new Vector2(0.5f, 0f); val.anchorMax = new Vector2(0.5f, 0f); val.pivot = new Vector2(0.5f, 0f); val.anchoredPosition = (_dragging ? _dragPosition : ConfiguredPosition()); ((Transform)val).localScale = Vector3.one * ModConfig.BarScale.Value; } } private static void HighlightSelected() { int num = Container?.SelectedSlot ?? (-1); if (num >= 0 && _bound != null && _grid.m_elements != null && num < _grid.m_elements.Count) { Element element = _grid.GetElement(num, 0, _bound.m_width); if ((Object)(object)element?.m_equiped != (Object)null) { ((Behaviour)element.m_equiped).enabled = true; } } } private static bool PointerIsOverSlots() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) List list = (((Object)(object)_grid != (Object)null) ? _grid.m_elements : null); if (list == null || list.Count == 0) { return false; } Canvas component = _root.GetComponent(); Camera val = (((Object)(object)component != (Object)null && (int)component.renderMode != 0) ? component.worldCamera : null); foreach (Element item in list) { RectTransform val2 = (RectTransform)(((Object)(object)item?.m_go != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val2 != (Object)null && RectTransformUtility.RectangleContainsScreenPoint(val2, Vector2.op_Implicit(ZInput.mousePosition), val)) { return true; } } return false; } internal static bool PointerIsOverBar() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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)_root == (Object)null || !_root.activeInHierarchy) { return false; } Transform transform = _root.transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)val == (Object)null) { return false; } Canvas component = _root.GetComponent(); Camera val2 = (((Object)(object)component != (Object)null && (int)component.renderMode != 0) ? component.worldCamera : null); return RectTransformUtility.RectangleContainsScreenPoint(val, Vector2.op_Implicit(ZInput.mousePosition), val2); } internal static bool TryPlaceDraggedItem(InventoryGui gui) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) ItemData dragItem = gui.m_dragItem; if (dragItem == null || (Object)(object)_grid == (Object)null || Container == null || _bound == null) { return false; } Player localPlayer = Player.m_localPlayer; if (!StaffRegistry.IsStaff(dragItem)) { if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "$gungnir_msg_only_staffs", 0, (Sprite)null); } return true; } Vector2i val = _grid.GetHoveredElement()?.m_pos ?? FirstFreeSlot(); if (val.x < 0) { if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "$gungnir_msg_rack_full", 0, (Sprite)null); } return true; } if (!_grid.DropItem(gui.m_dragInventory, dragItem, gui.m_dragAmount, val)) { return true; } gui.SetupDragItem((ItemData)null, (Inventory)null, 0); Container.SaveToItem(); ModConfig.Trace($"Placed {dragItem.m_shared.m_name} into rack slot {val.x + 1}."); return true; } private static Vector2i FirstFreeSlot() { //IL_002d: 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) for (int i = 0; i < _bound.m_width; i++) { if (_bound.GetItemAt(i, 0) == null) { return new Vector2i(i, 0); } } return new Vector2i(-1, 0); } private static void OnRightClick(InventoryGrid grid, ItemData item, Vector2i pos) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) ModConfig.Trace(string.Format("Rack right-click at slot {0}, item={1}.", pos.x + 1, item?.m_shared?.m_name ?? "empty")); Player localPlayer = Player.m_localPlayer; ItemData val = GungnirItem.Active(localPlayer); if (val != null && item != null) { StaffSwitcher.Select(localPlayer, val, pos.x); } } private static void OnSelected(InventoryGrid grid, ItemData item, Vector2i pos, Modifier mod) { //IL_0019: 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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Invalid comparison between Unknown and I4 //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) InventoryGui instance = InventoryGui.m_instance; Player localPlayer = Player.m_localPlayer; ModConfig.Trace($"Rack left-click at slot {pos.x + 1}, mod={mod}, " + "slotItem=" + (item?.m_shared?.m_name ?? "empty") + ", dragging=" + (instance?.m_dragItem?.m_shared?.m_name ?? "nothing") + "."); if (!((Object)(object)instance == (Object)null) && !((Object)(object)localPlayer == (Object)null)) { if ((int)mod == 2) { MoveToPlayerInventory(localPlayer, item); } else { instance.OnSelectedItem(grid, item, pos, mod); } } } private static void MoveToPlayerInventory(Player player, ItemData item) { if (item == null || Container == null) { return; } Inventory inventory = ((Humanoid)player).m_inventory; if (inventory == null) { return; } if (!inventory.CanAddItem(item, -1)) { ((Character)player).Message((MessageType)2, "$msg_noroom", 0, (Sprite)null); return; } inventory.MoveItemToThis(Container.Inventory, item); Container.SaveToItem(); ItemData val = GungnirItem.Active(player); if (val != null) { StaffSwitcher.Reapply(player, val); } } } internal static class GungnirItem { internal const string PrefabName = "GungnirStaff"; internal const string NameToken = "$gungnir_item_name"; internal const string DescToken = "$gungnir_item_desc"; internal const float PrimaryPierce = 95f; internal const float SecondaryPierce = 113f; private static readonly string[] BaseWeaponCandidates = new string[5] { "SpearSplitner_Lightning", "SpearSplitner", "SpearCarapace", "SpearElderbark", "SpearBronze" }; internal static GameObject Prefab { get; private set; } internal static SharedData BaseShared { get; private set; } internal static bool HasVanillaItems(ObjectDB db) { if ((Object)(object)db == (Object)null || db.m_items == null || db.m_items.Count == 0) { return false; } string[] baseWeaponCandidates = BaseWeaponCandidates; foreach (string text in baseWeaponCandidates) { if ((Object)(object)db.GetItemPrefab(text) != (Object)null) { return true; } } return false; } internal static bool IsGungnir(ItemData item) { if (item == null) { return false; } if ((Object)(object)item.m_dropPrefab != (Object)null) { if (item.m_dropPrefab != Prefab) { return ((Object)item.m_dropPrefab).name == "GungnirStaff"; } return true; } if (item.m_shared == null || !(item.m_shared.m_name == "$gungnir_item_name")) { if (item.m_customData != null) { return item.m_customData.ContainsKey("gungnir.inv"); } return false; } return true; } internal static bool Create() { //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Expected O, but got Unknown ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null || instance.m_items == null || instance.m_items.Count == 0) { ModConfig.Trace("ObjectDB not ready; deferring Gungnir prefab creation."); return false; } GameObject itemPrefab = instance.GetItemPrefab("GungnirStaff"); if ((Object)(object)itemPrefab != (Object)null) { Prefab = itemPrefab; if (((Object)itemPrefab).name != "GungnirStaff") { ((Object)itemPrefab).name = "GungnirStaff"; } ItemDrop component = itemPrefab.GetComponent(); BaseShared = component?.m_itemData?.m_shared; if (component?.m_itemData != null) { component.m_itemData.m_dropPrefab = itemPrefab; } ApplyIdentity(BaseShared, instance); if (ModConfig.StandalonePrefab.Value) { ApplyGameShader(itemPrefab, instance); } RegisterWithZNetScene(itemPrefab); GungnirVisual.Apply(itemPrefab); GungnirRecipe.Register(); ModConfig.Trace("Gungnir prefab already registered; refreshed its stats."); return true; } if (ModConfig.StandalonePrefab.Value) { if (BuildStandalone(instance)) { return true; } GungnirStaffPlugin.Log.LogWarning((object)"Standalone build did not complete; falling back to the cloned spear so the mod stays usable."); } GameObject val = PickBaseWeapon(instance); if ((Object)(object)val == (Object)null) { GungnirStaffPlugin.Log.LogError((object)"Could not find a spear to clone the Gungnir placeholder from."); return false; } try { CustomItem val2 = new CustomItem("GungnirStaff", ((Object)val).name); SharedData shared = val2.ItemDrop.m_itemData.m_shared; ApplyIdentity(shared, instance); ItemManager.Instance.AddItem(val2); ItemManager.Instance.RegisterItemInObjectDB(val2.ItemPrefab); RegisterWithZNetScene(val2.ItemPrefab); Prefab = val2.ItemPrefab; BaseShared = shared; GungnirVisual.Apply(val2.ItemPrefab); GungnirRecipe.Register(); GungnirStaffPlugin.Log.LogInfo((object)("Created the Gungnir prefab (cloned from " + ((Object)val).name + ").")); return true; } catch (Exception arg) { GungnirStaffPlugin.Log.LogError((object)$"Failed to create the Gungnir prefab: {arg}"); return false; } } private static bool BuildStandalone(ObjectDB db) { GameObject val = GungnirStandalone.Build(db); if ((Object)(object)val == (Object)null) { return false; } ItemDrop component = val.GetComponent(); Prefab = val; BaseShared = component.m_itemData.m_shared; ApplyGameShader(val, db); ItemManager.Instance.RegisterItemInObjectDB(val); RegisterWithZNetScene(val); GameObject itemPrefab = db.GetItemPrefab("GungnirStaff"); if ((Object)(object)itemPrefab != (Object)null && ((Object)itemPrefab).name != "GungnirStaff") { GungnirStaffPlugin.Log.LogWarning((object)("Registered prefab was named '" + ((Object)itemPrefab).name + "'; renaming to 'GungnirStaff' so the game can resolve it.")); ((Object)itemPrefab).name = "GungnirStaff"; } ItemDrop val2 = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent() : null); if (val2?.m_itemData != null) { Prefab = itemPrefab; BaseShared = val2.m_itemData.m_shared; val2.m_itemData.m_dropPrefab = itemPrefab; } GungnirRecipe.Register(); GungnirStaffPlugin.Log.LogInfo((object)"Created the standalone Gungnir prefab - no vanilla weapon behind it."); return true; } private static void ApplyGameShader(GameObject prefab, ObjectDB db) { //IL_0080: 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_0085: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) Shader val = GungnirStandalone.FindGameShader(db); if ((Object)(object)val == (Object)null) { GungnirStaffPlugin.Log.LogWarning((object)"No vanilla shader found; the standalone model may render untextured."); return; } int num = 0; Renderer[] componentsInChildren = prefab.GetComponentsInChildren(true); foreach (Renderer val2 in componentsInChildren) { Material[] materials = val2.materials; foreach (Material val3 in materials) { if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3.shader == (Object)(object)val)) { Color val4 = (val3.HasProperty("_Color") ? val3.GetColor("_Color") : Color.white); val3.shader = val; if (val3.HasProperty("_Color")) { val3.SetColor("_Color", val4); } num++; } } } if (num > 0) { ModConfig.Trace($"Standalone shader set to '{((Object)val).name}' on {num} material(s)."); } } private static void ApplyIdentity(SharedData target, ObjectDB db) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) if (target == null) { return; } if (ModConfig.StandalonePrefab.Value) { ApplyGungnirIdentity(target); GungnirStandalone.BorrowEffects(target, db); return; } GameObject obj = PickBaseWeapon(db); SharedData val = ((obj == null) ? null : obj.GetComponent()?.m_itemData?.m_shared); if (val != null && val != target) { CopyFields(val, target); } target.m_attack = CloneAttack(target.m_attack); target.m_secondaryAttack = CloneAttack(target.m_attack); target.m_secondaryAttack.m_attackType = (AttackType)0; target.m_attack.m_consumeItem = false; target.m_secondaryAttack.m_consumeItem = false; Sprite icon = GungnirVisual.Icon; if ((Object)(object)icon != (Object)null) { target.m_icons = (Sprite[])(object)new Sprite[1] { icon }; } target.m_name = "$gungnir_item_name"; target.m_description = "$gungnir_item_desc"; target.m_maxStackSize = 1; target.m_maxQuality = 3; target.m_useDurability = false; target.m_dlc = string.Empty; target.m_damages.m_pierce = 95f; if (target.m_secondaryAttack != null) { target.m_secondaryAttack.m_damageMultiplier = 1.1894736f; } ApplyGungnirIdentity(target); target.m_damagesPerLevel = default(DamageTypes); } private static void ApplyGungnirIdentity(SharedData target) { Sprite icon = GungnirVisual.Icon; if ((Object)(object)icon != (Object)null) { target.m_icons = (Sprite[])(object)new Sprite[1] { icon }; } target.m_name = "$gungnir_item_name"; target.m_description = "$gungnir_item_desc"; target.m_maxStackSize = 1; target.m_maxQuality = 3; target.m_useDurability = false; target.m_dlc = string.Empty; target.m_damages.m_pierce = 95f; if (target.m_secondaryAttack != null) { target.m_secondaryAttack.m_damageMultiplier = 1.1894736f; } } internal static void RepairDropPrefab(ItemData item) { if (item != null && !((Object)(object)item.m_dropPrefab != (Object)null) && !((Object)(object)Prefab == (Object)null) && item.m_customData != null && item.m_customData.ContainsKey("gungnir.inv")) { item.m_dropPrefab = Prefab; ModConfig.Trace("Restored a missing m_dropPrefab on a Gungnir."); } } internal static void CopyFields(T from, T to) where T : class { FieldInfo[] fields = typeof(T).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (!fieldInfo.IsInitOnly && !fieldInfo.IsLiteral) { fieldInfo.SetValue(to, fieldInfo.GetValue(from)); } } } private static Attack CloneAttack(Attack source) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown if (source == null) { return null; } Attack val = new Attack(); CopyFields(source, val); return val; } internal static GameObject PickBaseWeapon(ObjectDB db) { string text = ModConfig.BaseWeapon?.Value; if (!string.IsNullOrEmpty(text)) { GameObject itemPrefab = db.GetItemPrefab(text); if ((Object)(object)itemPrefab != (Object)null) { return itemPrefab; } GungnirStaffPlugin.Log.LogWarning((object)("BaseWeaponPrefab '" + text + "' is not in ObjectDB; falling back. Use 'gungnir find spear' to see the exact names.")); } string[] baseWeaponCandidates = BaseWeaponCandidates; foreach (string text2 in baseWeaponCandidates) { GameObject itemPrefab2 = db.GetItemPrefab(text2); if ((Object)(object)itemPrefab2 != (Object)null) { return itemPrefab2; } } return ((IEnumerable)db.m_items).FirstOrDefault((Func)((GameObject p) => (Object)(object)p != (Object)null && ((Object)p).name != "GungnirStaff" && ((Object)p).name.StartsWith("Spear", StringComparison.OrdinalIgnoreCase))); } private static void RegisterWithZNetScene(GameObject prefab) { ZNetScene instance = ZNetScene.instance; if (!((Object)(object)instance == (Object)null) && !((Object)(object)prefab == (Object)null)) { int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)prefab).name); if (!instance.m_namedPrefabs.ContainsKey(stableHashCode)) { instance.m_prefabs.Add(prefab); instance.m_namedPrefabs[stableHashCode] = prefab; } } } internal static void RepairInventory(Player player) { Inventory val = ((Humanoid)(player?)).m_inventory; if (val == null || (Object)(object)Prefab == (Object)null) { return; } int num = 0; foreach (ItemData allItem in val.GetAllItems()) { if (!((Object)(object)allItem.m_dropPrefab != (Object)null) && ((allItem.m_shared != null && allItem.m_shared.m_name == "$gungnir_item_name") || (allItem.m_customData != null && allItem.m_customData.ContainsKey("gungnir.inv")))) { allItem.m_dropPrefab = Prefab; num++; } } if (num > 0) { GungnirStaffPlugin.Log.LogInfo((object)($"Repaired {num} Gungnir(s) that had no drop prefab - they would " + "not have survived a relog.")); } } internal static ItemData EquippedOn(Player player) { if ((Object)(object)player == (Object)null) { return null; } if (IsGungnir(((Humanoid)player).m_rightItem)) { return ((Humanoid)player).m_rightItem; } if (!IsGungnir(((Humanoid)player).m_leftItem)) { return null; } return ((Humanoid)player).m_leftItem; } internal static ItemData CarriedBy(Player player) { Inventory val = ((Humanoid)(player?)).m_inventory; if (val == null) { return null; } foreach (ItemData allItem in val.GetAllItems()) { if (IsGungnir(allItem)) { return allItem; } } return null; } internal static ItemData Active(Player player) { if ((Object)(object)player == (Object)null || !ModConfig.Enabled.Value) { return null; } if (ModConfig.Activation.Value != ActivationMode.Carried) { return EquippedOn(player); } return CarriedBy(player); } } internal static class GungnirRecipe { internal const string Station = "piece_magetable"; internal const int MaxQuality = 3; internal const int MinStationLevel = 2; internal const int BaseSlots = 4; internal const int SlotsPerLevel = 2; private static readonly Dictionary Costs = new Dictionary { { "YggdrasilWood", new int[3] { 30, 15, 25 } }, { "Eitr", new int[3] { 30, 20, 30 } }, { "Thunderstone", new int[3] { 3, 2, 4 } }, { "BlackCore", new int[3] { 2, 1, 2 } } }; private static readonly Dictionary Aliases = new Dictionary { { "Thunderstone", new string[3] { "Thunderstone", "ThunderStone", "thunderstone" } }, { "BlackCore", new string[2] { "BlackCore", "Blackcore" } }, { "Eitr", new string[2] { "Eitr", "RefinedEitr" } }, { "YggdrasilWood", new string[2] { "YggdrasilWood", "Yggdrasilwood" } } }; internal static readonly Dictionary ExactCosts = new Dictionary(); private static bool _added; private static string Resolve(ObjectDB db, string wanted) { if (!Aliases.TryGetValue(wanted, out var value)) { value = new string[1] { wanted }; } return value.FirstOrDefault((string n) => (Object)(object)db.GetItemPrefab(n) != (Object)null); } internal static void Register() { //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: 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_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0141: 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_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Expected O, but got Unknown //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Expected O, but got Unknown ObjectDB db = ObjectDB.instance; if ((Object)(object)db == (Object)null || db.m_items == null || db.m_items.Count == 0) { return; } Dictionary resolved = Costs.Keys.ToDictionary((string k) => k, (string k) => Resolve(db, k)); List list = (from kv in resolved where kv.Value == null select kv.Key).ToList(); if (list.Count > 0) { GungnirStaffPlugin.Log.LogError((object)("Cannot build the Gungnir recipe, no prefab found for: " + string.Join(", ", list))); } else { if ((Object)(object)db.GetItemPrefab("GungnirStaff") == (Object)null) { return; } if (!_added) { try { RecipeConfig val = new RecipeConfig { Name = "Recipe_GungnirStaff", Item = "GungnirStaff", Amount = 1, CraftingStation = "piece_magetable", RepairStation = "piece_magetable", MinStationLevel = 2, Requirements = ((IEnumerable>)Costs).Select((Func, RequirementConfig>)((KeyValuePair kv) => new RequirementConfig { Item = resolved[kv.Key], Amount = kv.Value[0], AmountPerLevel = ((kv.Value.Length > 1) ? kv.Value[1] : 0), Recover = true })).ToArray() }; ItemManager.Instance.AddRecipe(new CustomRecipe(val)); _added = true; } catch (Exception arg) { GungnirStaffPlugin.Log.LogError((object)$"Could not add the Gungnir recipe: {arg}"); return; } } EnsureInObjectDb(db, resolved); BindExactCosts(db); } } private static void EnsureInObjectDb(ObjectDB db, Dictionary resolved) { if (db.m_recipes == null) { return; } GameObject itemPrefab = db.GetItemPrefab("GungnirStaff"); ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent() : null); if ((Object)(object)val == (Object)null) { return; } GameObject prefab = PrefabManager.Instance.GetPrefab("piece_magetable"); CraftingStation val2 = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent() : null); if ((Object)(object)val2 == (Object)null) { GungnirStaffPlugin.Log.LogError((object)"Crafting station 'piece_magetable' not found; Gungnir will not be craftable."); return; } Recipe val3 = FindRecipe(db); bool flag = (Object)(object)val3 == (Object)null; if (flag) { val3 = ScriptableObject.CreateInstance(); } ((Object)val3).name = "Recipe_GungnirStaff"; val3.m_item = val; val3.m_amount = 1; val3.m_enabled = true; val3.m_craftingStation = val2; val3.m_repairStation = val2; val3.m_minStationLevel = 2; val3.m_resources = (from r in ((IEnumerable>)Costs).Select((Func, Requirement>)delegate(KeyValuePair kv) { //IL_001e: 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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown GameObject itemPrefab2 = db.GetItemPrefab(resolved[kv.Key]); return new Requirement { m_resItem = (((Object)(object)itemPrefab2 != (Object)null) ? itemPrefab2.GetComponent() : null), m_amount = kv.Value[0], m_amountPerLevel = ((kv.Value.Length > 1) ? kv.Value[1] : 0), m_recover = true }; }) where (Object)(object)r.m_resItem != (Object)null select r).ToArray(); if (flag) { db.m_recipes.Add(val3); } ModConfig.Trace("Gungnir recipe " + (flag ? "registered at" : "refreshed for") + " the Galdr Table " + $"({val3.m_resources.Length} materials, station level {2}, " + $"up to level {3})."); } private static Recipe FindRecipe(ObjectDB db) { return ((IEnumerable)db.m_recipes).FirstOrDefault((Func)((Recipe r) => (Object)(object)r != (Object)null && (Object)(object)r.m_item != (Object)null && ((Object)((Component)r.m_item).gameObject).name == "GungnirStaff")); } private static void BindExactCosts(ObjectDB db) { if (db.m_recipes == null) { return; } Recipe val = FindRecipe(db); if ((Object)(object)val == (Object)null) { ModConfig.Trace("Gungnir recipe not in ObjectDB yet; will bind later."); return; } ExactCosts.Clear(); Requirement[] resources = val.m_resources; foreach (Requirement val2 in resources) { if (!((Object)(object)val2?.m_resItem == (Object)null)) { string name = ((Object)((Component)val2.m_resItem).gameObject).name; string text = Costs.Keys.FirstOrDefault((string k) => string.Equals(Resolve(db, k), name, StringComparison.Ordinal)); if (text != null) { ExactCosts[val2] = Costs[text]; } } } ModConfig.Trace($"Gungnir recipe bound with {ExactCosts.Count} exact cost table(s)."); } internal static int SlotsForQuality(int quality) { int num = Mathf.Max(0, quality - 1); return Mathf.Clamp(4 + num * 2, 4, 8); } internal static bool MoreSlotsAvailable(int quality) { if (quality < 3) { return SlotsForQuality(quality + 1) > SlotsForQuality(quality); } return false; } } internal static class GungnirStandalone { private const int ToolTier = 5; private const float BlockPower = 57f; private const float DeflectionForce = 20f; private const float AttackForce = 20f; private const string AttackAnimation = "spear_poke"; private const float AttackStamina = 16f; private const float AttackRange = 1.9f; private const float EquipDuration = 0.2f; private static GameObject _container; internal static GameObject Build(ObjectDB db) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0068: 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_00ae: Expected O, but got Unknown //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Expected O, but got Unknown //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0145: 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_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016d: 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_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Expected O, but got Unknown GameObject prefab = GungnirVisual.Prefab; if ((Object)(object)prefab == (Object)null) { GungnirStaffPlugin.Log.LogError((object)"Standalone build needs the model from the AssetBundle; it did not load."); return null; } GameObject val = new GameObject("GungnirStaff"); val.transform.SetParent(PrefabContainer().transform, false); val.layer = LayerMask.NameToLayer("item"); try { ZNetView val2 = val.AddComponent(); val2.m_persistent = true; val2.m_distant = false; val2.m_type = (ObjectType)0; val2.m_syncInitialScale = false; val.AddComponent(); Rigidbody val3 = val.AddComponent(); val3.mass = 1f; val3.useGravity = true; val3.interpolation = (RigidbodyInterpolation)0; val.AddComponent(); GameObject val4 = new GameObject("collider"); val4.transform.SetParent(val.transform, false); val4.layer = val.layer; BoxCollider val5 = val4.AddComponent(); val5.size = new Vector3(0.2f, 0.2f, 2.3f); GameObject val6 = new GameObject("attach"); val6.transform.SetParent(val.transform, false); GameObject val7 = Object.Instantiate(prefab, val6.transform, false); ((Object)val7).name = "GungnirVisual"; val7.transform.localPosition = Vector3.zero; val7.transform.localRotation = Quaternion.identity; ItemDrop val8 = val.AddComponent(); val8.m_autoPickup = true; val8.m_itemData = new ItemData { m_stack = 1, m_quality = 1, m_durability = 100f, m_dropPrefab = val, m_shared = BuildSharedData() }; BorrowEffects(val8.m_itemData.m_shared, db); return val; } catch (Exception arg) { GungnirStaffPlugin.Log.LogError((object)$"Standalone prefab build failed: {arg}"); Object.Destroy((Object)(object)val); return null; } } private static GameObject PrefabContainer() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if ((Object)(object)_container == (Object)null) { _container = new GameObject("GungnirStaff_Prefabs"); _container.SetActive(false); Object.DontDestroyOnLoad((Object)(object)_container); } return _container; } private static SharedData BuildSharedData() { //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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_0077: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected O, but got Unknown SharedData val = new SharedData { m_name = "$gungnir_item_name", m_description = "$gungnir_item_desc", m_itemType = (ItemType)3, m_skillType = (SkillType)5, m_animationState = (AnimationState)1, m_toolTier = 5, m_maxStackSize = 1, m_maxQuality = 3, m_weight = 1.5f, m_value = 0, m_teleportable = true, m_questItem = false, m_dlc = string.Empty, m_useDurability = false, m_maxDurability = 1000f, m_blockPower = 57f, m_deflectionForce = 20f, m_attackForce = 20f, m_equipDuration = 0.2f, m_attack = BuildAttack(1f), m_secondaryAttack = BuildAttack(1.1894736f) }; val.m_damages.m_pierce = 95f; Sprite icon = GungnirVisual.Icon; if ((Object)(object)icon != (Object)null) { val.m_icons = (Sprite[])(object)new Sprite[1] { icon }; } return val; } private static Attack BuildAttack(float damageMultiplier) { //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_0007: 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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown return new Attack { m_attackType = (AttackType)0, m_attackAnimation = "spear_poke", m_attackStamina = 16f, m_attackEitr = 0f, m_attackRange = 1.9f, m_damageMultiplier = damageMultiplier, m_consumeItem = false, m_requiresReload = false, m_attackChainLevels = 1, m_speedFactor = 0.2f, m_speedFactorRotation = 0.2f }; } internal static void BorrowEffects(SharedData shared, ObjectDB db) { if (shared == null) { return; } GameObject val = GungnirItem.PickBaseWeapon(db) ?? FindReferenceSpear(db); SharedData val2 = ((!((Object)(object)val != (Object)null)) ? null : val.GetComponent()?.m_itemData?.m_shared); if (val2 == null) { GungnirStaffPlugin.Log.LogWarning((object)"No vanilla spear found to read hit effects from; Gungnir will hit silently and without impact sparks."); return; } int num = 0; num += Take(val2.m_hitEffect, delegate(EffectList e) { shared.m_hitEffect = e; }); num += Take(val2.m_hitTerrainEffect, delegate(EffectList e) { shared.m_hitTerrainEffect = e; }); num += Take(val2.m_blockEffect, delegate(EffectList e) { shared.m_blockEffect = e; }); num += Take(val2.m_startEffect, delegate(EffectList e) { shared.m_startEffect = e; }); num += Take(val2.m_holdStartEffect, delegate(EffectList e) { shared.m_holdStartEffect = e; }); num += Take(val2.m_equipEffect, delegate(EffectList e) { shared.m_equipEffect = e; }); num += Take(val2.m_unequipEffect, delegate(EffectList e) { shared.m_unequipEffect = e; }); num += Take(val2.m_triggerEffect, delegate(EffectList e) { shared.m_triggerEffect = e; }); num += Take(val2.m_trailStartEffect, delegate(EffectList e) { shared.m_trailStartEffect = e; }); num += BorrowAttackEffects(val2.m_attack, shared.m_attack); num += BorrowAttackEffects(val2.m_attack, shared.m_secondaryAttack); ModConfig.Trace($"Standalone Gungnir borrowed {num} effect list(s) from '{((Object)val).name}'."); } private static int BorrowAttackEffects(Attack donor, Attack target) { if (donor == null || target == null) { return 0; } int num = 0; num += Take(donor.m_hitEffect, delegate(EffectList e) { target.m_hitEffect = e; }); num += Take(donor.m_hitTerrainEffect, delegate(EffectList e) { target.m_hitTerrainEffect = e; }); num += Take(donor.m_startEffect, delegate(EffectList e) { target.m_startEffect = e; }); num += Take(donor.m_triggerEffect, delegate(EffectList e) { target.m_triggerEffect = e; }); num += Take(donor.m_trailStartEffect, delegate(EffectList e) { target.m_trailStartEffect = e; }); return num + Take(donor.m_burstEffect, delegate(EffectList e) { target.m_burstEffect = e; }); } private static int Take(EffectList source, Action assign) { if (source == null || source.m_effectPrefabs == null || source.m_effectPrefabs.Length == 0) { return 0; } assign(source); return 1; } internal static Shader FindGameShader(ObjectDB db) { if ((Object)(object)db == (Object)null || db.m_items == null) { return null; } GameObject val = FindReferenceSpear(db); Shader val2 = ShaderOf(val); if ((Object)(object)val2 != (Object)null) { ModConfig.Trace("Standalone using shader '" + ((Object)val2).name + "' from '" + ((Object)val).name + "'."); return val2; } foreach (GameObject item in db.m_items) { if (!((Object)(object)item == (Object)null) && !(((Object)item).name == "GungnirStaff")) { val2 = ShaderOf(item); if ((Object)(object)val2 != (Object)null) { ModConfig.Trace("Standalone using shader '" + ((Object)val2).name + "' from '" + ((Object)item).name + "'."); return val2; } } } return null; } private static Shader ShaderOf(GameObject prefab) { if ((Object)(object)prefab == (Object)null) { return null; } Material val = (from r in prefab.GetComponentsInChildren(true) where !(r is ParticleSystemRenderer) select r).SelectMany((Renderer r) => r.sharedMaterials).FirstOrDefault((Func)((Material m) => (Object)(object)m != (Object)null && (Object)(object)m.shader != (Object)null)); if (!((Object)(object)val != (Object)null)) { return null; } return val.shader; } internal static GameObject FindReferenceSpear(ObjectDB db) { if ((Object)(object)db == (Object)null || db.m_items == null) { return null; } return ((IEnumerable)db.m_items).FirstOrDefault((Func)((GameObject p) => (Object)(object)p != (Object)null && ((Object)p).name != "GungnirStaff" && ((Object)p).name.StartsWith("Spear", StringComparison.OrdinalIgnoreCase))); } } internal static class GungnirVisual { internal const string BundleName = "gungnir"; internal const string PrefabName = "GungnirVisual"; internal const string IconName = "GungnirIcon"; private static AssetBundle _bundle; private static GameObject _visualPrefab; private static bool _failed; internal const float PrefabGripHeight = 0.95f; private static Sprite _icon; private static bool _iconMissing; private static bool _loggedBackAxis; private static bool _loggedBack; private static bool _lastStanceLogged; internal static GameObject Prefab { get { if ((Object)(object)_visualPrefab != (Object)null || _failed) { return _visualPrefab; } try { _bundle = _bundle ?? LoadBundle(); if ((Object)(object)_bundle == (Object)null) { _failed = true; return null; } _visualPrefab = _bundle.LoadAsset("GungnirVisual"); if ((Object)(object)_visualPrefab == (Object)null) { GungnirStaffPlugin.Log.LogError((object)("'GungnirVisual' not found in the bundle. Contents: " + string.Join(", ", _bundle.GetAllAssetNames()))); _failed = true; } } catch (Exception arg) { GungnirStaffPlugin.Log.LogError((object)$"Could not load the Gungnir bundle: {arg}"); _failed = true; } return _visualPrefab; } } internal static Sprite Icon { get { if ((Object)(object)_icon != (Object)null || _iconMissing) { return _icon; } if ((Object)(object)Prefab == (Object)null || (Object)(object)_bundle == (Object)null) { return null; } _icon = _bundle.LoadAsset("GungnirIcon"); if ((Object)(object)_icon == (Object)null) { _iconMissing = true; GungnirStaffPlugin.Log.LogWarning((object)"'GungnirIcon' not found in the bundle; the item keeps the donor icon."); } return _icon; } } private static AssetBundle LoadBundle() { foreach (AssetBundle item in AssetBundle.GetAllLoadedAssetBundles().ToList()) { if ((Object)(object)item == (Object)null) { continue; } bool flag; try { flag = item.GetAllAssetNames().Any((string n) => n.IndexOf("GungnirVisual", StringComparison.OrdinalIgnoreCase) >= 0); } catch (Exception ex) { GungnirStaffPlugin.Log.LogWarning((object)("Evicting an unreadable AssetBundle that is blocking the reload: " + ex.Message)); item.Unload(false); continue; } if (!flag) { continue; } try { if ((Object)(object)item.LoadAsset("GungnirVisual") != (Object)null) { ModConfig.Trace("Reusing the already-loaded Gungnir bundle."); return item; } } catch (Exception ex2) { GungnirStaffPlugin.Log.LogWarning((object)("Evicting an unreadable Gungnir bundle before reloading: " + ex2.Message)); } item.Unload(false); } Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = executingAssembly.GetManifestResourceNames().FirstOrDefault((string n) => n.EndsWith("gungnir", StringComparison.OrdinalIgnoreCase)); if (text == null) { GungnirStaffPlugin.Log.LogError((object)("No embedded resource ending in 'gungnir'. Embedded: " + string.Join(", ", executingAssembly.GetManifestResourceNames()))); return null; } using Stream stream = executingAssembly.GetManifestResourceStream(text); if (stream == null) { GungnirStaffPlugin.Log.LogError((object)("Embedded resource '" + text + "' could not be opened.")); return null; } byte[] array = new byte[stream.Length]; int num; int num2; for (num = 0; num < array.Length; num += num2) { num2 = stream.Read(array, num, array.Length - num); if (num2 <= 0) { break; } } ModConfig.Trace($"Read {num} bytes of bundle from '{text}'."); return AssetBundle.LoadFromMemory(array); } internal static bool Apply(GameObject itemPrefab) { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)itemPrefab == (Object)null || (Object)(object)Prefab == (Object)null) { return false; } Transform val = FindAttach(itemPrefab); if ((Object)(object)val == (Object)null) { GungnirStaffPlugin.Log.LogWarning((object)("No 'attach' child on the Gungnir prefab; leaving the placeholder model. Hierarchy: " + Describe(itemPrefab.transform, 0))); return false; } Transform val2 = val.Find("GungnirVisual"); if ((Object)(object)val2 != (Object)null) { return true; } int num = 0; Renderer[] componentsInChildren = ((Component)val).GetComponentsInChildren(true); foreach (Renderer val3 in componentsInChildren) { if (!(val3 is ParticleSystemRenderer)) { val3.enabled = false; num++; } } GameObject val4 = Object.Instantiate(Prefab, val, false); ((Object)val4).name = "GungnirVisual"; val4.transform.localPosition = Vector3.zero; val4.transform.localRotation = Quaternion.identity; val4.transform.localScale = Vector3.one; AdoptVanillaShaders(val4, itemPrefab); ModConfig.Trace($"Custom Gungnir model attached ({num} donor renderer(s) hidden)."); return true; } private static void AdoptVanillaShaders(GameObject visual, GameObject donor) { //IL_00fb: 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_0100: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) Material val = (from r in donor.GetComponentsInChildren(true) where !(r is ParticleSystemRenderer) select r).SelectMany((Renderer r) => r.sharedMaterials).FirstOrDefault((Func)((Material m) => (Object)(object)m != (Object)null && (Object)(object)m.shader != (Object)null)); if ((Object)(object)val == (Object)null) { GungnirStaffPlugin.Log.LogWarning((object)"No donor material to borrow a shader from; the model may render untextured."); return; } Shader shader = val.shader; Renderer[] componentsInChildren = visual.GetComponentsInChildren(true); foreach (Renderer val2 in componentsInChildren) { Material[] materials = val2.materials; foreach (Material val3 in materials) { if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3.shader == (Object)(object)shader)) { Color val4 = (val3.HasProperty("_Color") ? val3.GetColor("_Color") : Color.white); Color val5 = (val3.HasProperty("_EmissionColor") ? val3.GetColor("_EmissionColor") : Color.black); val3.shader = shader; if (val3.HasProperty("_Color")) { val3.SetColor("_Color", val4); } if (((Color)(ref val5)).maxColorComponent > 0f && val3.HasProperty("_EmissionColor")) { val3.EnableKeyword("_EMISSION"); val3.SetColor("_EmissionColor", val5); } } } } ModConfig.Trace("Adopted vanilla shader '" + ((Object)shader).name + "' for the Gungnir model."); } internal static void Orient(Player player, ItemData gungnir) { //IL_0069: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: 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_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: 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_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_0149: 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) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) VisEquipment val = ((Humanoid)(player?)).m_visEquipment; if ((Object)(object)val == (Object)null) { return; } OrientBack(val); GameObject val2 = PickHeldInstance(val); if ((Object)(object)val2 == (Object)null) { return; } Transform val3 = FindVisual(val2.transform); if (!((Object)(object)val3 == (Object)null)) { bool flag = (StaffContainer.For(gungnir)?.SelectedSlot ?? (-1)) >= 0; Vector3 val4 = ParseVector(ModConfig.ModelOffset.Value); Vector3 val5 = Vector3.one * ModConfig.ModelScale.Value; Quaternion val6 = BaseAttachRotation(); if (val2.transform.localRotation != val6) { val2.transform.localRotation = val6; } Quaternion val7 = Quaternion.Euler(ParseVector(flag ? ModConfig.RotationStaff.Value : ModConfig.RotationSpear.Value)); if (val3.localRotation != val7) { val3.localRotation = val7; } if (flag != _lastStanceLogged) { _lastStanceLogged = flag; ModConfig.Trace("Stance is now " + (flag ? "STAFF" : "SPEAR") + "."); } ApplyGrip(val3); OrientEffects(val2.transform, val3, flag); if (ModConfig.StandalonePrefab.Value) { BladeGlow.Apply(val2, val3, flag); } if (val3.localPosition != val4) { val3.localPosition = val4; } if (val3.localScale != val5) { val3.localScale = val5; } } } private static bool TryDonorLongAxis(Transform attach, Transform visual, out Vector3 axis) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) axis = Vector3.up; MeshFilter val = ((IEnumerable)((Component)attach).GetComponentsInChildren(true)).FirstOrDefault((Func)((MeshFilter mf) => (Object)(object)mf.sharedMesh != (Object)null && !((Component)mf).transform.IsChildOf(visual))); if ((Object)(object)val == (Object)null) { GameObject val2 = GungnirStandalone.FindReferenceSpear(ObjectDB.instance); Transform val3 = (((Object)(object)val2 != (Object)null) ? FindAttach(val2) : null); if ((Object)(object)val3 == (Object)null) { return false; } MeshFilter val4 = ((IEnumerable)((Component)val3).GetComponentsInChildren(true)).FirstOrDefault((Func)((MeshFilter mf) => (Object)(object)mf.sharedMesh != (Object)null)); if ((Object)(object)val4 == (Object)null) { return false; } if (!LongAxisOf(val4, val3, out axis)) { return false; } if (!_loggedBackAxis) { _loggedBackAxis = true; ModConfig.Trace("Back axis taken from reference spear '" + ((Object)val2).name + "'."); } return true; } return LongAxisOf(val, attach, out axis); } private static bool LongAxisOf(MeshFilter mesh, Transform attach, out Vector3 axis) { //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_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_001a: 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_0020: 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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: 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) //IL_0034: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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_008a: 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_00ac: 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_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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) axis = Vector3.up; Bounds bounds = mesh.sharedMesh.bounds; Vector3 size = ((Bounds)(ref bounds)).size; Vector3 val = ((size.x >= size.y && size.x >= size.z) ? Vector3.right : ((!(size.y >= size.z)) ? Vector3.forward : Vector3.up)); float num = Mathf.Max(size.x, Mathf.Max(size.y, size.z)); float num2 = size.x + size.y + size.z - num; if (num < num2 * 0.8f) { return false; } Vector3 val2 = ((Component)mesh).transform.TransformDirection(val); Vector3 val3 = attach.InverseTransformDirection(val2); axis = ((Vector3)(ref val3)).normalized; return ((Vector3)(ref axis)).sqrMagnitude > 0.001f; } private static GameObject PickHeldInstance(VisEquipment vis) { GameObject rightItemInstance = vis.m_rightItemInstance; if ((Object)(object)rightItemInstance != (Object)null && (Object)(object)FindVisual(rightItemInstance.transform) != (Object)null) { return rightItemInstance; } GameObject leftItemInstance = vis.m_leftItemInstance; if ((Object)(object)leftItemInstance != (Object)null && (Object)(object)FindVisual(leftItemInstance.transform) != (Object)null) { return leftItemInstance; } return rightItemInstance ?? leftItemInstance; } private static Transform FindVisual(Transform root) { return root.Find("GungnirVisual") ?? ((IEnumerable)((Component)root).GetComponentsInChildren(true)).FirstOrDefault((Func)((Transform t) => ((Object)t).name == "GungnirVisual")); } private static void OrientBack(VisEquipment vis) { //IL_00e1: 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_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: 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_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0132: 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_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: 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_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_010a: 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) //IL_0111: 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_0117: 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_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Expected O, but got Unknown //IL_0218: 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) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0228: 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_0241: 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_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) GameObject val = vis.m_rightBackItemInstance ?? vis.m_leftBackItemInstance; if ((Object)(object)val == (Object)null) { if (!_loggedBack) { _loggedBack = true; ModConfig.Trace("Sheathed: no back instance on VisEquipment."); } return; } Transform val2 = FindVisual(val.transform); if ((Object)(object)val2 == (Object)null) { if (!_loggedBack) { _loggedBack = true; GungnirStaffPlugin.Log.LogWarning((object)("Sheathed model '" + ((Object)val).name + "' has no GungnirVisual child - the back copy is built from a different attach than the hand. Children: " + string.Join(", ", (from t in val.GetComponentsInChildren(true) select ((Object)t).name).Take(12)))); } return; } if (!_loggedBack) { _loggedBack = true; ModConfig.Trace("Sheathed model found under '" + ((Object)val).name + "'."); } Quaternion val3 = Quaternion.Euler(ParseVector(ModConfig.RotationBack.Value)); Quaternion val4 = val3; if (ModConfig.AlignBackToVanilla.Value && TryDonorLongAxis(val.transform, val2, out var axis)) { val4 = Quaternion.FromToRotation(Vector3.up, axis) * val3; } if (val2.localRotation != val4) { val2.localRotation = val4; } Vector3 val5 = val4 * Vector3.up; Vector3 val6 = val5 * ModConfig.BackSlide.Value; if (val2.localPosition != val6) { val2.localPosition = val6; } Vector3 val7 = Vector3.one * ModConfig.ModelScale.Value; if (val2.localScale != val7) { val2.localScale = val7; } Transform val8 = (((Object)(object)GungnirItem.Prefab != (Object)null) ? FindAttach(GungnirItem.Prefab) : null); foreach (Transform item in val.transform) { Transform val9 = item; if ((Object)(object)val9 == (Object)(object)val2 || (Object)(object)((Component)val9).GetComponentInChildren(true) == (Object)null) { continue; } Transform val10 = (((Object)(object)val8 != (Object)null) ? val8.Find(((Object)val9).name) : null); if (!((Object)(object)val10 == (Object)null)) { Vector3 val11 = val10.localPosition + val6; if (val9.localPosition != val11) { val9.localPosition = val11; } if (val9.localRotation != val10.localRotation) { val9.localRotation = val10.localRotation; } } } } private static void ApplyGrip(Transform visual) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) Transform val = visual.Find("Model"); if (!((Object)(object)val == (Object)null)) { Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(0f, 0f - ModConfig.GripHeight.Value, 0f); if (val.localPosition != val2) { val.localPosition = val2; } } } internal static void Preload() { if (!((Object)(object)_visualPrefab != (Object)null) && !_failed) { Stopwatch stopwatch = Stopwatch.StartNew(); bool flag = (Object)(object)Prefab != (Object)null; stopwatch.Stop(); if (flag) { ModConfig.Trace($"Bundle preloaded in {stopwatch.ElapsedMilliseconds} ms."); } } } private static Quaternion BaseAttachRotation() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) GameObject prefab = GungnirItem.Prefab; Transform val = (((Object)(object)prefab != (Object)null) ? FindAttach(prefab) : null); if (!((Object)(object)val != (Object)null)) { return Quaternion.identity; } return val.localRotation; } private static void OrientEffects(Transform attachInstance, Transform visual, bool staffStance) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0138: 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_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: 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_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0141: 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_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_018b: 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_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: 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_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) bool flag = ModConfig.WeaponEffect.Value switch { WeaponEffectMode.Always => true, WeaponEffectMode.Never => false, _ => !staffStance, }; Quaternion val = Quaternion.Euler(ParseVector(ModConfig.WeaponEffectRotation.Value)); float value = ModConfig.WeaponEffectDistance.Value; Transform val2 = (((Object)(object)GungnirItem.Prefab != (Object)null) ? FindAttach(GungnirItem.Prefab) : null); foreach (Transform item in attachInstance) { Transform val3 = item; if ((Object)(object)val3 == (Object)(object)visual || (Object)(object)((Component)val3).GetComponentInChildren(true) == (Object)null) { continue; } if (((Component)val3).gameObject.activeSelf != flag) { ((Component)val3).gameObject.SetActive(flag); } if (flag) { Transform val4 = (((Object)(object)val2 != (Object)null) ? val2.Find(((Object)val3).name) : null); Vector3 val5 = (((Object)(object)val4 != (Object)null) ? val4.localPosition : Vector3.zero); Quaternion val6 = (((Object)(object)val4 != (Object)null) ? val4.localRotation : Quaternion.identity); Vector3 val7; Vector3 normalized; if (!(((Vector3)(ref val5)).sqrMagnitude > 1E-06f)) { val7 = attachInstance.InverseTransformDirection(visual.TransformDirection(Vector3.up)); normalized = ((Vector3)(ref val7)).normalized; } else { normalized = ((Vector3)(ref val5)).normalized; } Vector3 val8 = normalized; val7 = attachInstance.InverseTransformDirection(visual.TransformDirection(Vector3.up)); Vector3 normalized2 = ((Vector3)(ref val7)).normalized; float num = ((Vector3.Dot(val8, normalized2) >= 0f) ? 1f : (-1f)); float num2 = 0.95f - ModConfig.GripHeight.Value; Vector3 val9 = val5 + val8 * (value + num * num2); Quaternion val10 = val6 * val; if (val3.localPosition != val9) { val3.localPosition = val9; } if (val3.localRotation != val10) { val3.localRotation = val10; } } } } internal static Vector3 ParseVector(string raw) { //IL_0008: 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_009f: 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 (string.IsNullOrEmpty(raw)) { return Vector3.zero; } string[] array = raw.Split(new char[1] { ',' }); if (array.Length != 3) { return Vector3.zero; } float result = 0f; float result2 = 0f; float result3 = 0f; if (!float.TryParse(array[0].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out result) || !float.TryParse(array[1].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out result2) || !float.TryParse(array[2].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out result3)) { return Vector3.zero; } return new Vector3(result, result2, result3); } private static Transform FindAttach(GameObject itemPrefab) { Transform val = itemPrefab.transform.Find("attach"); if ((Object)(object)val != (Object)null) { return val; } return ((IEnumerable)itemPrefab.GetComponentsInChildren(true)).FirstOrDefault((Func)((Transform t) => ((Object)t).name.StartsWith("attach", StringComparison.OrdinalIgnoreCase))); } internal static string Describe(Transform t, int depth) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown if (depth > 3) { return string.Empty; } string text = new string(' ', depth * 2) + ((Object)t).name; foreach (Transform item in t) { Transform t2 = item; text = text + "\n" + Describe(t2, depth + 1); } return text; } } internal static class Inputs { private static bool GameplayInput() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { return ((Character)localPlayer).TakeInput(); } return false; } internal static bool StatusPressed() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut value = ModConfig.StatusKey.Value; return ((KeyboardShortcut)(ref value)).IsDown(); } internal static bool HolsterPressed() { //IL_000c: 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) if (GameplayInput()) { KeyboardShortcut value = ModConfig.HolsterKey.Value; return ((KeyboardShortcut)(ref value)).IsDown(); } return false; } internal static int PressedSlot() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (!GameplayInput()) { return -1; } for (int i = 0; i < 8; i++) { KeyboardShortcut value = ModConfig.SlotKeys[i].Value; if (((KeyboardShortcut)(ref value)).IsDown()) { return i; } } return -1; } internal static string ShortLabel(KeyboardShortcut shortcut) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) string text = KeyName(((KeyboardShortcut)(ref shortcut)).MainKey); if (string.IsNullOrEmpty(text)) { return string.Empty; } string[] array = (from n in ((KeyboardShortcut)(ref shortcut)).Modifiers?.Select(ModifierName) where !string.IsNullOrEmpty(n) select n).Distinct().ToArray(); if (array != null && array.Length != 0) { return string.Join("+", array) + "+" + text; } return text; } private static string ModifierName(KeyCode key) { //IL_0000: 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_0038: Expected I4, but got Unknown //IL_0052: Unknown result type (might be due to invalid IL or missing references) switch (key - 303) { case 4: case 5: case 10: return "Alt"; case 2: case 3: return "Ctrl"; case 0: case 1: return "Shift"; case 6: case 7: return "Cmd"; default: return KeyName(key); } } private unsafe static string KeyName(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_0013: 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_0018: Expected I4, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected I4, but got Unknown if ((int)key == 0) { return string.Empty; } if ((int)key >= 48 && (int)key <= 57) { return (key - 48).ToString(); } if ((int)key >= 256 && (int)key <= 265) { return "#" + (key - 256); } return ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString(); } internal static bool SlotShortcutActive() { //IL_000b: 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_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) KeyboardShortcut value; for (int i = 0; i < 8; i++) { value = ModConfig.SlotKeys[i].Value; if (((KeyboardShortcut)(ref value)).IsDown()) { return true; } } value = ModConfig.HolsterKey.Value; return ((KeyboardShortcut)(ref value)).IsDown(); } } internal static class LightningStrike { private static readonly string[] EffectCandidates = new string[3] { "fx_lightningstaffprojectile_hit", "vfx_lightningstaff_fire", "fx_lightningstaff_charge" }; private static GameObject _effect; private static bool _searched; private static bool _warned; internal static bool TryStrike(HitData hit, Player attacker) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Invalid comparison between Unknown and I4 //IL_00a3: Unknown result type (might be due to invalid IL or missing references) if (hit == null || (Object)(object)attacker == (Object)null || !ModConfig.Enabled.Value) { return false; } if ((int)hit.m_hitType != 2) { return false; } ItemData currentWeapon = ((Humanoid)attacker).GetCurrentWeapon(); if (!GungnirItem.IsGungnir(currentWeapon)) { return false; } if ((StaffContainer.For(currentWeapon)?.SelectedSlot ?? (-1)) >= 0) { return false; } float totalDamage = hit.GetTotalDamage(); if (totalDamage <= 0f) { return false; } if (Random.value > ModConfig.LightningChance.Value) { ModConfig.Trace($"Gungnir hit for {totalDamage:0.#} base damage; storm touch did not trigger."); return false; } float value = ModConfig.LightningDamage.Value; hit.m_damage.m_lightning += value; SpawnEffect(hit.m_point); ModConfig.Trace($"Storm touch: {totalDamage:0.#} base damage + {value:0.#} lightning " + $"= {hit.GetTotalDamage():0.#} before resistances."); return true; } private static void SpawnEffect(Vector3 point) { //IL_002d: 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) GameObject val = Effect(); if ((Object)(object)val == (Object)null) { if (!_warned) { _warned = true; GungnirStaffPlugin.Log.LogWarning((object)"No lightning impact effect found; strikes still deal damage but show nothing. Set LightningEffectPrefab to a valid effect name."); } return; } GameObject val2 = Object.Instantiate(val, point, Quaternion.identity); ZNetView[] componentsInChildren = val2.GetComponentsInChildren(true); foreach (ZNetView val3 in componentsInChildren) { Object.Destroy((Object)(object)val3); } Aoe[] componentsInChildren2 = val2.GetComponentsInChildren(true); foreach (Aoe val4 in componentsInChildren2) { Object.Destroy((Object)(object)val4); } Projectile[] componentsInChildren3 = val2.GetComponentsInChildren(true); foreach (Projectile val5 in componentsInChildren3) { Object.Destroy((Object)(object)val5); } Object.Destroy((Object)(object)val2, 5f); } private static GameObject Effect() { if (_searched) { return _effect; } _searched = true; string value = ModConfig.LightningEffectPrefab.Value; string[] array = (string.IsNullOrEmpty(value) ? EffectCandidates : new string[1] { value }.Concat(EffectCandidates).ToArray()); string[] array2 = array; foreach (string text in array2) { GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(text) : null); if ((Object)(object)val == (Object)null) { val = PrefabManager.Instance.GetPrefab(text); } if ((Object)(object)val != (Object)null) { _effect = val; ModConfig.Trace("Lightning strikes will use '" + text + "'."); return _effect; } } return null; } internal static void Reset() { _searched = false; _effect = null; _warned = false; } } internal static class Localizations { internal static void Register() { CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); string text = "English"; localization.AddTranslation(ref text, new Dictionary { { "gungnir_item_name", "Gungnir" }, { "gungnir_item_desc", "Odin's own spear, that never misses its mark and never breaks its oath. The shaft thrums with a magic too vast to spend on a single form, so it takes the power of other staffs into itself and wields them as one." }, { "gungnir_bar_title", "Staff rack" }, { "gungnir_msg_only_staffs", "Only magic staffs fit in the rack" }, { "gungnir_msg_rack_full", "The staff rack is full" } }); } } internal enum ActivationMode { Equipped, Carried } internal enum BladeGlowStyle { Lightning, SoftGlow, None } internal enum WeaponEffectMode { OnlyInMeleeStance, Always, Never } internal enum CrystalParticleMode { OnlyInCastingStance, Always, Never } internal enum BarVisibility { WhenGungnirActive, InventoryOnly, Always } internal static class ModConfig { internal const int MaxSlots = 8; internal static ConfigEntry Enabled; internal static ConfigEntry VerboseLogging; internal static ConfigEntry SlotCount; internal static ConfigEntry Activation; internal static ConfigEntry Visibility; internal static ConfigEntry BaseWeapon; internal static ConfigEntry StandalonePrefab; internal static ConfigEntry RotationSpear; internal static ConfigEntry RotationStaff; internal static ConfigEntry RotationBack; internal static ConfigEntry AlignBackToVanilla; internal static ConfigEntry BackSlide; internal static ConfigEntry ModelOffset; internal static ConfigEntry ModelScale; internal static ConfigEntry GripHeight; internal static ConfigEntry NormaliseStaffStance; internal static ConfigEntry CrystalParticles; internal static ConfigEntry CrystalParticleRate; internal static ConfigEntry CrystalParticleScale; internal static ConfigEntry CrystalParticleBrightness; internal static ConfigEntry WeaponEffect; internal static ConfigEntry WeaponEffectRotation; internal static ConfigEntry WeaponEffectDistance; internal static ConfigEntry BladeGlowStyle; internal static ConfigEntry LightningChance; internal static ConfigEntry LightningDamage; internal static ConfigEntry LightningEffectPrefab; internal static ConfigEntry BladeGlowPrefab; internal static ConfigEntry BladeGlowColour; internal static ConfigEntry BladeGlowRate; internal static ConfigEntry BladeGlowScale; internal static ConfigEntry BladeGlowOffset; internal static ConfigEntry BladeGlowBrightness; internal static ConfigEntry StatusKey; internal static ConfigEntry HolsterKey; internal static ConfigEntry[] SlotKeys; internal static ConfigEntry BarOffsetX; internal static ConfigEntry BarOffsetY; internal static ConfigEntry BarScale; internal static ConfigEntry MoveBarMouseButton; internal static ConfigEntry ShowSlotKeys; internal static ConfigEntry SlotKeyScale; internal static event Action OnLayoutChanged; internal static void Bind(ConfigFile config) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Expected O, but got Unknown //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Expected O, but got Unknown //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Expected O, but got Unknown //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Expected O, but got Unknown //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Expected O, but got Unknown //IL_02c5: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Expected O, but got Unknown //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Expected O, but got Unknown //IL_038a: Unknown result type (might be due to invalid IL or missing references) //IL_0394: Expected O, but got Unknown //IL_03c2: Unknown result type (might be due to invalid IL or missing references) //IL_03cc: Expected O, but got Unknown //IL_03fa: Unknown result type (might be due to invalid IL or missing references) //IL_0404: Expected O, but got Unknown //IL_044d: Unknown result type (might be due to invalid IL or missing references) //IL_0457: Expected O, but got Unknown //IL_0485: Unknown result type (might be due to invalid IL or missing references) //IL_048f: Expected O, but got Unknown //IL_051a: Unknown result type (might be due to invalid IL or missing references) //IL_0524: Expected O, but got Unknown //IL_0552: Unknown result type (might be due to invalid IL or missing references) //IL_055c: Expected O, but got Unknown //IL_058a: Unknown result type (might be due to invalid IL or missing references) //IL_0594: Expected O, but got Unknown //IL_05c2: Unknown result type (might be due to invalid IL or missing references) //IL_05cc: Expected O, but got Unknown //IL_05ee: Unknown result type (might be due to invalid IL or missing references) //IL_05f8: Expected O, but got Unknown //IL_0641: Unknown result type (might be due to invalid IL or missing references) //IL_064b: Expected O, but got Unknown //IL_065b: Unknown result type (might be due to invalid IL or missing references) //IL_068a: Unknown result type (might be due to invalid IL or missing references) //IL_06b1: Unknown result type (might be due to invalid IL or missing references) //IL_06d3: Unknown result type (might be due to invalid IL or missing references) //IL_06e2: Unknown result type (might be due to invalid IL or missing references) Enabled = config.Bind("General", "Enabled", true, "Master switch. Turn off to disable the mod's behaviour without uninstalling it. The status key keeps working either way."); VerboseLogging = config.Bind("General", "VerboseLogging", false, "Log extra detail to the BepInEx console. Useful while developing."); SlotCount = config.Bind("Staff bar", "SlotCount", 0, new ConfigDescription("0 follows the staff's own upgrade level - four slots to start and two more per upgrade, so 4/6/8. Set 1-8 to override with a fixed number regardless of level. Shrinking it while staffs sit in the removed slots will strand them, so empty the bar first.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 8), Array.Empty())); Activation = config.Bind("Staff bar", "Activation", ActivationMode.Carried, "Carried (default): the staff bar and slot keys work whenever a Gungnir is anywhere in your inventory. Equipped: only while it is actually in hand."); StandalonePrefab = config.Bind("Appearance", "StandalonePrefab", true, "Build Gungnir as its own item with no vanilla weapon behind it, instead of cloning a spear. Every stat is then authored by the mod. TAKES EFFECT ON THE NEXT GAME START - the prefab is registered once at load."); BaseWeapon = config.Bind("Appearance", "BaseWeaponPrefab", "SpearSplitner_Lightning", "Which vanilla weapon Gungnir is built from - its model, animations and handling. Only the look and feel come from here; Gungnir's own damage and flavour text are applied on top. Vanilla candidates worth trying: SpearSplitner_Lightning, SpearSplitner, SpearSplitner_Blood, SpearSplitner_Nature, SpearCarapace, SpearElderbark, SpearWolfFang. TAKES EFFECT ON THE NEXT GAME START - the held model comes from the prefab, which is registered once at load."); RotationSpear = config.Bind("Appearance", "RotationSpear", "-90,0,0", "Model rotation with NO staff selected - right hand, blade leading. Degrees (x,y,z). Independent of RotationStaff."); RotationStaff = config.Bind("Appearance", "RotationStaff", "-90,0,0", "Model rotation WITH a staff selected - left hand, crystal leading. Degrees (x,y,z). Independent of RotationSpear."); GripHeight = config.Bind("Appearance", "GripHeight", 1.18f, new ConfigDescription("Where the hand holds the shaft, in metres from the crystal end. The shaft runs 0.20-1.74 and the blade tip is at 2.30. Lower values grip further down, raising the head; the blade effect follows automatically.", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 2f), Array.Empty())); RotationBack = config.Bind("Appearance", "RotationBack", "0,0,0", "Rotation applied on top of the back alignment, in degrees (x,y,z). With AlignBackToVanilla on, 0,0,0 lays it along the vanilla spear's axis and 180,0,0 swaps which end points up. The blade glow is turned by the same amount, about the same pivot, so it stays on the blade."); AlignBackToVanilla = config.Bind("Appearance", "AlignBackToVanilla", true, "Lay the sheathed model along the same axis as the vanilla spear it was cloned from, whose hidden mesh is still inside the same attach and is already angled correctly for the back. Measured from the game rather than guessed. Turn off to use RotationBack alone."); BackSlide = config.Bind("Appearance", "BackSlide", -0.35f, new ConfigDescription("Slides the sheathed model along its own shaft, in metres. Negative carries it lower down the back; positive rides it higher. The blade glow slides with it.", (AcceptableValueBase)(object)new AcceptableValueRange(-2f, 2f), Array.Empty())); ModelOffset = config.Bind("Appearance", "ModelOffset", "0,0,0", "Positional nudge of the model in the hand, in metres. Format: x,y,z."); ModelScale = config.Bind("Appearance", "ModelScale", 1f, new ConfigDescription("Size of the Gungnir model in hand.", (AcceptableValueBase)(object)new AcceptableValueRange(0.25f, 3f), Array.Empty())); NormaliseStaffStance = config.Bind("Appearance", "NormaliseStaffStance", true, "Hold Gungnir the same way whichever staff is selected. Vanilla gives some magic items their own posture - the Dead Raiser is a skull, and is carried like one - which looks wrong on a spear. Off uses each staff's own stance."); CrystalParticles = config.Bind("Crystal particles", "Mode", CrystalParticleMode.OnlyInCastingStance, "When to show the motes orbiting the crystal and the sparks shooting out of it, tinted to match the selected staff. OnlyInCastingStance: just while a staff is selected. Always: both stances. Never: off."); CrystalParticleRate = config.Bind("Crystal particles", "Rate", 1f, new ConfigDescription("How many particles are emitted, as a multiplier. Lower it if the effect is too busy, or to save a little performance.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 4f), Array.Empty())); CrystalParticleScale = config.Bind("Crystal particles", "Scale", 1f, new ConfigDescription("Size of the motes and how far from the crystal they orbit.", (AcceptableValueBase)(object)new AcceptableValueRange(0.25f, 4f), Array.Empty())); CrystalParticleBrightness = config.Bind("Crystal particles", "Brightness", 2.2f, new ConfigDescription("Pushes the particle colour past white so the motes read as glowing. 1 is the flat crystal colour.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 8f), Array.Empty())); WeaponEffect = config.Bind("Weapon effect", "Mode", WeaponEffectMode.OnlyInMeleeStance, "When to show the glow on the blade. OnlyInMeleeStance: just while Gungnir is a spear, off once a staff is selected. Always: both stances. Never: off."); WeaponEffectRotation = config.Bind("Weapon effect", "Rotation", "180,0,0", "Rotation of the glow about its own centre, in degrees (x,y,z)."); WeaponEffectDistance = config.Bind("Weapon effect", "Distance", -1.75f, new ConfigDescription("Moves the glow along its axis from the weapon's origin point, in metres. Negative pulls it back past the grip towards the blade.", (AcceptableValueBase)(object)new AcceptableValueRange(-3f, 3f), Array.Empty())); Visibility = config.Bind("Staff bar", "Visibility", BarVisibility.WhenGungnirActive, "WhenGungnirActive: on screen the whole time you have Gungnir, like a second hotbar. InventoryOnly: only while the inventory is open. Always: on screen permanently, even with no Gungnir."); BarOffsetX = config.Bind("Staff bar", "PositionX", 0f, new ConfigDescription("Horizontal position of the staff bar in pixels, from the bottom-centre of the screen.", (AcceptableValueBase)(object)new AcceptableValueRange(-2000f, 2000f), Array.Empty())); BarOffsetY = config.Bind("Staff bar", "PositionY", 190f, new ConfigDescription("Vertical position of the staff bar in pixels, up from the bottom of the screen. The vanilla hotbar sits at roughly 60-120.", (AcceptableValueBase)(object)new AcceptableValueRange(-2000f, 2000f), Array.Empty())); BarScale = config.Bind("Staff bar", "Scale", 1f, new ConfigDescription("Size multiplier for the staff bar.", (AcceptableValueBase)(object)new AcceptableValueRange(0.25f, 3f), Array.Empty())); BladeGlowStyle = config.Bind("Weapon effect", "BladeGlowStyle", GungnirStaff.BladeGlowStyle.None, "Lightning: fast crackling streaks along the blade. SoftGlow: the calmer haze this replaced. None (default): no particles. Off for now because the glow can render at the wrong size after some stance changes."); LightningChance = config.Bind("Weapon effect", "LightningChance", 0.25f, new ConfigDescription("Chance per hit of triggering the game's own lightning strike, with its vanilla visual and sound.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); LightningDamage = config.Bind("Weapon effect", "LightningDamage", 40f, new ConfigDescription("Lightning damage added when a strike triggers. At the default 25 percent chance this averages 10 per hit, matching the vanilla lightning spear which adds a flat 10 every time - the same damage, delivered as an occasional jolt.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 300f), Array.Empty())); LightningEffectPrefab = config.Bind("Weapon effect", "LightningEffectPrefab", "", "Vanilla effect spawned where a strike lands, carrying the game own visual and sound. Blank picks the best available automatically."); BladeGlowPrefab = config.Bind("Weapon effect", "BladeGlowPrefab", "", "Optional: name of a vanilla effect prefab to mount on the spear head. Blank (the default) uses the mod's own particles. Be careful - most of these are authored as one-shot, world-scale spawns, not weapon decorations: fx_lightningstaff_charge fills the screen with a two-second burst and then stops."); BladeGlowColour = config.Bind("Weapon effect", "BladeGlowColour", "#7FC8FF", "Colour of the glow on the spear head (standalone prefab only). Hex."); BladeGlowRate = config.Bind("Weapon effect", "BladeGlowRate", 1f, new ConfigDescription("How much the blade glows, as a multiplier. 0 stops emission.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 4f), Array.Empty())); BladeGlowScale = config.Bind("Weapon effect", "BladeGlowScale", 1f, new ConfigDescription("Size of the glow around the blade.", (AcceptableValueBase)(object)new AcceptableValueRange(0.25f, 4f), Array.Empty())); BladeGlowOffset = config.Bind("Weapon effect", "BladeGlowOffset", -0.04f, new ConfigDescription("Where the blade effect sits along the shaft, in metres from the middle of the blade. Negative moves it down toward the socket, positive up toward the point.", (AcceptableValueBase)(object)new AcceptableValueRange(-1f, 1f), Array.Empty())); BladeGlowBrightness = config.Bind("Weapon effect", "BladeGlowBrightness", 2.2f, new ConfigDescription("Pushes the glow past white so it reads as emissive. 1 is flat colour.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 8f), Array.Empty())); MoveBarMouseButton = config.Bind("Staff bar", "MoveBarMouseButton", 2, new ConfigDescription("Mouse button that drags the staff bar to a new place while the inventory is open. 2 is the middle button; 0 is left and 1 is right, though both of those are already used by the slots. -1 turns dragging off and leaves PositionX/PositionY as the only way to move it.", (AcceptableValueBase)(object)new AcceptableValueRange(-1, 6), Array.Empty())); ShowSlotKeys = config.Bind("Staff bar", "ShowSlotKeys", true, "Print each slot's shortcut under it, the way the vanilla hotbar numbers its own slots. The text is read from the live binding, so rebinding a slot relabels it."); SlotKeyScale = config.Bind("Staff bar", "SlotKeyScale", 1f, new ConfigDescription("Size of the shortcut labels, as a multiplier. The base size follows the slot size, so the labels already scale with the bar - this is for nudging them relative to it.", (AcceptableValueBase)(object)new AcceptableValueRange(0.25f, 3f), Array.Empty())); StatusKey = config.Bind("Keys", "StatusKey", KeyboardShortcut.Empty, "Optional diagnostic key, unbound by default. When bound, prints the running version and build timestamp to the BepInEx console, the in-game console and the screen. 'gungnir' in the F5 console shows the same thing."); HolsterKey = config.Bind("Keys", "HolsterStaff", new KeyboardShortcut((KeyCode)48, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Puts the active staff away and turns Gungnir back into its plain self."); SlotKeys = new ConfigEntry[8]; for (int i = 0; i < 8; i++) { KeyCode val = (KeyCode)(49 + i); SlotKeys[i] = config.Bind("Keys", "SelectSlot" + (i + 1), new KeyboardShortcut(val, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Selects staff slot " + (i + 1) + ". While a slot shortcut is triggered the vanilla hotbar is suppressed, so the number key does not do both things."); } ShowSlotKeys.SettingChanged += delegate { ModConfig.OnLayoutChanged?.Invoke(); }; SlotKeyScale.SettingChanged += delegate { ModConfig.OnLayoutChanged?.Invoke(); }; ConfigEntry[] slotKeys = SlotKeys; foreach (ConfigEntry val2 in slotKeys) { val2.SettingChanged += delegate { ModConfig.OnLayoutChanged?.Invoke(); }; } Visibility.SettingChanged += delegate { ModConfig.OnLayoutChanged?.Invoke(); }; SlotCount.SettingChanged += delegate { ModConfig.OnLayoutChanged?.Invoke(); }; BarOffsetX.SettingChanged += delegate { ModConfig.OnLayoutChanged?.Invoke(); }; BarOffsetY.SettingChanged += delegate { ModConfig.OnLayoutChanged?.Invoke(); }; BarScale.SettingChanged += delegate { ModConfig.OnLayoutChanged?.Invoke(); }; } internal static Color ParseColour(string hex, Color fallback) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) Color result = default(Color); if (string.IsNullOrEmpty(hex) || !ColorUtility.TryParseHtmlString(hex.Trim(), ref result)) { return fallback; } return result; } internal static void Trace(string message) { if (VerboseLogging != null && VerboseLogging.Value) { GungnirStaffPlugin.Log.LogInfo((object)message); } } } [BepInPlugin("dev.samspel.gungnirstaff", "Gungnir Staff", "1.0.3")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInProcess("valheim.exe")] [BepInProcess("valheim_server.exe")] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal sealed class GungnirStaffPlugin : BaseUnityPlugin { public const string ModGuid = "dev.samspel.gungnirstaff"; public const string ModName = "Gungnir Staff"; public const string ModVersion = "1.0.3"; internal static GungnirStaffPlugin Instance; internal static ManualLogSource Log; private Harmony _harmony; private ItemData _lastActive; internal Harmony Harmony => _harmony; private void Awake() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; ModConfig.Bind(((BaseUnityPlugin)this).Config); CrystalColors.Bind(((BaseUnityPlugin)this).Config); ModConfig.OnLayoutChanged += GungnirBar.OnLayoutSettingChanged; _harmony = new Harmony("dev.samspel.gungnirstaff"); _harmony.PatchAll(Assembly.GetExecutingAssembly()); try { Localizations.Register(); GungnirCommand.Register(); } catch (Exception ex) { Log.LogError((object)("Jotunn was not ready during Awake; localisation and the 'gungnir' console command are unavailable this session: " + ex.Message)); } LightningStrike.Reset(); if (!GUIManager.IsHeadless()) { GungnirVisual.Preload(); } if (Alive.InGame) { StaffRegistry.Invalidate(); GungnirItem.Create(); GungnirItem.RepairInventory(Player.m_localPlayer); } Log.LogInfo((object)Alive.StatusLine(_harmony)); } private void Update() { if (Inputs.StatusPressed()) { Alive.Announce("alive", _harmony); } if (!ModConfig.Enabled.Value) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { _lastActive = null; return; } ItemData val = GungnirItem.Active(localPlayer); try { GungnirBar.Refresh(localPlayer); } catch (Exception arg) { Log.LogError((object)$"Staff bar update failed: {arg}"); } if (val != _lastActive) { _lastActive = val; if (val != null) { StaffSwitcher.Reapply(localPlayer, val); } } try { GungnirVisual.Orient(localPlayer, val ?? GungnirItem.CarriedBy(localPlayer)); BladeGlow.PurgeStrays(localPlayer); } catch (Exception arg2) { Log.LogError((object)$"Model orientation failed: {arg2}"); } if (val == null) { CrystalGlow.Clear(); return; } CrystalGlow.Apply(localPlayer, val); StaffSwitcher.SyncActiveDurability(val); if (Inputs.HolsterPressed()) { StaffSwitcher.Holster(localPlayer, val); return; } int num = Inputs.PressedSlot(); if (num >= 0) { StaffSwitcher.Select(localPlayer, val, num); } } private void OnDestroy() { ModConfig.OnLayoutChanged -= GungnirBar.OnLayoutSettingChanged; GungnirBar.Teardown(); CrystalGlow.Clear(); BladeGlow.Clear(); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } _harmony = null; ModConfig.Trace("Gungnir Staff unloaded."); } } internal sealed class StaffContainer { internal const string InventoryKey = "gungnir.inv"; internal const string SelectedKey = "gungnir.sel"; internal const string OwnQualityKey = "gungnir.q"; internal const string OwnVariantKey = "gungnir.var"; private static readonly ConditionalWeakTable Cache = new ConditionalWeakTable(); private readonly ItemData _owner; internal Inventory Inventory { get; } internal int SelectedSlot { get { if (_owner.m_customData != null && _owner.m_customData.TryGetValue("gungnir.sel", out var value) && int.TryParse(value, out var result)) { return result; } return -1; } set { EnsureCustomData(); _owner.m_customData["gungnir.sel"] = value.ToString(); } } internal int OwnQuality { get { if (_owner.m_customData != null && _owner.m_customData.TryGetValue("gungnir.q", out var value) && int.TryParse(value, out var result) && result >= 1) { return result; } return Math.Max(1, _owner.m_quality); } set { EnsureCustomData(); _owner.m_customData["gungnir.q"] = Math.Max(1, value).ToString(); } } internal int OwnVariant { get { if (_owner.m_customData != null && _owner.m_customData.TryGetValue("gungnir.var", out var value) && int.TryParse(value, out var result)) { return result; } return 0; } set { EnsureCustomData(); _owner.m_customData["gungnir.var"] = value.ToString(); } } private StaffContainer(ItemData owner) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown _owner = owner; Inventory = new Inventory("$gungnir_bar_title", (Sprite)null, WantedWidth(), 1); LoadFromItem(); Inventory inventory = Inventory; inventory.m_onChanged = (Action)Delegate.Combine(inventory.m_onChanged, new Action(OnInventoryChanged)); } private void OnInventoryChanged() { NormaliseGrid(); SaveToItem(); } private void NormaliseGrid() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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_00bf: 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) int width = Inventory.m_width; if (width <= 0) { return; } bool[] array = new bool[width]; List list = new List(); foreach (ItemData item in Inventory.m_inventory) { Vector2i gridPos = item.m_gridPos; if (gridPos.y == 0 && gridPos.x >= 0 && gridPos.x < width && !array[gridPos.x]) { array[gridPos.x] = true; } else { list.Add(item); } } foreach (ItemData item2 in list) { int num = Array.IndexOf(array, value: false); if (num < 0) { item2.m_gridPos = new Vector2i(width - 1, 0); continue; } array[num] = true; item2.m_gridPos = new Vector2i(num, 0); } } internal void RememberOwnLevel() { OwnQuality = _owner.m_quality; OwnVariant = _owner.m_variant; } internal static StaffContainer For(ItemData gungnir) { if (gungnir == null) { return null; } if (Cache.TryGetValue(gungnir, out var value)) { value.SyncWidth(); return value; } StaffContainer staffContainer = new StaffContainer(gungnir); Cache.Add(gungnir, staffContainer); return staffContainer; } internal static void Forget(ItemData item) { if (item != null) { Cache.Remove(item); } } internal ItemData ItemAt(int slot) { if (slot < 0 || slot >= Inventory.m_width) { return null; } return Inventory.GetItemAt(slot, 0); } internal void SaveToItem() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown EnsureCustomData(); ZPackage val = new ZPackage(); Inventory.Save(val); _owner.m_customData["gungnir.inv"] = val.GetBase64(); } private void LoadFromItem() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown if (_owner.m_customData == null || !_owner.m_customData.TryGetValue("gungnir.inv", out var value) || string.IsNullOrEmpty(value)) { return; } try { Inventory.Load(new ZPackage(value)); SyncWidth(); NormaliseGrid(); } catch (Exception ex) { GungnirStaffPlugin.Log.LogError((object)("Could not read the staffs stored in this Gungnir, starting empty: " + ex.Message)); } } private int WantedWidth() { int value = ModConfig.SlotCount.Value; if (value <= 0) { return GungnirRecipe.SlotsForQuality(OwnQuality); } return value; } private void SyncWidth() { int num = WantedWidth(); if (Inventory.m_width != num || Inventory.m_height != 1) { Inventory.m_width = num; Inventory.m_height = 1; NormaliseGrid(); } } private void EnsureCustomData() { if (_owner.m_customData == null) { _owner.m_customData = new Dictionary(); } } } internal static class StaffRegistry { private static List _cache; internal static bool IsStaff(ItemData item) { if (item?.m_shared == null || GungnirItem.IsGungnir(item)) { return false; } return IsStaffShared(item.m_shared); } private static bool IsStaffShared(SharedData shared) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Invalid comparison between Unknown and I4 //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 if ((int)shared.m_skillType != 9 && (int)shared.m_skillType != 10) { return false; } if ((int)shared.m_itemType != 22 && (int)shared.m_itemType != 14) { return (int)shared.m_itemType == 3; } return true; } internal static List AllStaffPrefabs() { if (_cache != null) { return _cache; } ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null || instance.m_items == null) { return new List(); } List list = new List(); foreach (GameObject item in instance.m_items) { if (!((Object)(object)item == (Object)null) && !(((Object)item).name == "GungnirStaff")) { ItemDrop component = item.GetComponent(); if (component?.m_itemData?.m_shared != null && IsStaffShared(component.m_itemData.m_shared)) { list.Add(item); } } } _cache = list; ModConfig.Trace(string.Format("Detected {0} staff(s): {1}", list.Count, string.Join(", ", list.Select((GameObject p) => ((Object)p).name)))); return _cache; } internal static void Invalidate() { _cache = null; StaffStance.Reset(); } } internal static class StaffStance { private const AnimationState DefaultStance = (AnimationState)12; private static readonly ConditionalWeakTable Adjusted = new ConditionalWeakTable(); private static AnimationState? _common; internal static SharedData Normalise(SharedData staff) { //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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_0041: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) if (staff == null || !ModConfig.NormaliseStaffStance.Value) { return staff; } AnimationState val = CommonStance(); if (staff.m_animationState == val) { return staff; } if (Adjusted.TryGetValue(staff, out var value)) { return value; } SharedData val2 = new SharedData(); GungnirItem.CopyFields(staff, val2); val2.m_animationState = val; Adjusted.Add(staff, val2); ModConfig.Trace($"Holding '{staff.m_name}' as {val} instead of {staff.m_animationState}."); return val2; } private static AnimationState CommonStance() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: 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_0119: Unknown result type (might be due to invalid IL or missing references) if (_common.HasValue) { return _common.Value; } List list = StaffRegistry.AllStaffPrefabs(); if (list.Count == 0) { return (AnimationState)12; } _common = (AnimationState)(((??)((IEnumerable>)(from p in list select p.GetComponent()?.m_itemData?.m_shared into s where s != null group s by s.m_animationState into g orderby g.Count() descending select g)).Select((Func, AnimationState?>)((IGrouping g) => g.Key)).FirstOrDefault()) ?? 12); ModConfig.Trace($"Common staff stance is {_common.Value}."); return _common.Value; } internal static void Reset() { _common = null; } } internal static class StaffSwitcher { internal static void Select(Player player, ItemData gungnir, int slot) { StaffContainer staffContainer = StaffContainer.For(gungnir); if (staffContainer == null) { return; } ItemData val = staffContainer.ItemAt(slot); if (val == null) { ModConfig.Trace($"Slot {slot + 1} is empty."); return; } if (staffContainer.SelectedSlot == slot) { Holster(player, gungnir); return; } SyncActiveDurability(gungnir); if (staffContainer.SelectedSlot < 0) { staffContainer.RememberOwnLevel(); } staffContainer.SelectedSlot = slot; Project(player, gungnir, val); ModConfig.Trace($"Selected slot {slot + 1}: {val.m_shared.m_name}"); } internal static void Holster(Player player, ItemData gungnir) { StaffContainer staffContainer = StaffContainer.For(gungnir); if (staffContainer != null && staffContainer.SelectedSlot >= 0) { SyncActiveDurability(gungnir); staffContainer.SelectedSlot = -1; Project(player, gungnir, null); ModConfig.Trace("Holstered."); } } internal static void Reapply(Player player, ItemData gungnir) { StaffContainer staffContainer = StaffContainer.For(gungnir); if (staffContainer != null) { int selectedSlot = staffContainer.SelectedSlot; ItemData val = ((selectedSlot >= 0) ? staffContainer.ItemAt(selectedSlot) : null); if (selectedSlot < 0) { staffContainer.RememberOwnLevel(); } if (selectedSlot >= 0 && val == null) { staffContainer.SelectedSlot = -1; } Project(player, gungnir, val); } } internal static void SyncActiveDurability(ItemData gungnir) { StaffContainer staffContainer = StaffContainer.For(gungnir); int num = staffContainer?.SelectedSlot ?? (-1); if (num >= 0) { ItemData val = staffContainer.ItemAt(num); if (val != null && val.m_durability != gungnir.m_durability) { val.m_durability = gungnir.m_durability; staffContainer.SaveToItem(); } } } private static void Project(Player player, ItemData gungnir, ItemData staff) { bool flag = (Object)(object)player != (Object)null && gungnir.m_equipped; if (flag) { ((Humanoid)player).UnequipItem(gungnir, false); } if (staff?.m_shared != null) { gungnir.m_shared = StaffStance.Normalise(staff.m_shared); gungnir.m_quality = staff.m_quality; gungnir.m_variant = staff.m_variant; gungnir.m_durability = staff.m_durability; gungnir.m_worldLevel = staff.m_worldLevel; } else if (GungnirItem.BaseShared != null) { gungnir.m_shared = GungnirItem.BaseShared; StaffContainer staffContainer = StaffContainer.For(gungnir); gungnir.m_quality = staffContainer?.OwnQuality ?? Math.Max(1, gungnir.m_quality); gungnir.m_variant = staffContainer?.OwnVariant ?? 0; } if (flag) { ((Humanoid)player).EquipItem(gungnir, false); } } } internal static class BuildInfo { internal const string BuildTime = "2026-08-30 22:20:13"; internal const string Configuration = "Release"; } } namespace GungnirStaff.Patches { [HarmonyPatch(typeof(InventoryGui), "DoCrafting")] internal static class CraftingUpgradePatch { private static Dictionary _carried; private static Vector2i _slot; private static int _expectedQuality; private static void Prefix(InventoryGui __instance, Player player) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) _carried = null; ItemData val = __instance?.m_craftUpgradeItem; if (!((Object)(object)player == (Object)null) && GungnirItem.IsGungnir(val)) { StaffSwitcher.Holster(player, val); StaffContainer.For(val)?.SaveToItem(); _carried = ((val.m_customData == null) ? null : new Dictionary(val.m_customData)); _slot = val.m_gridPos; _expectedQuality = val.m_quality + 1; } } private static void Postfix(Player player) { Dictionary carried = _carried; _carried = null; if (carried != null && ((Humanoid)(player?)).m_inventory != null) { ItemData itemAt = ((Humanoid)player).m_inventory.GetItemAt(_slot.x, _slot.y); if (!GungnirItem.IsGungnir(itemAt)) { GungnirStaffPlugin.Log.LogWarning((object)"An upgraded Gungnir could not be found in its old slot; its staff rack has been left on the original item rather than moved."); } else if (itemAt.m_quality == _expectedQuality) { Dictionary dictionary = new Dictionary(carried); dictionary["gungnir.q"] = itemAt.m_quality.ToString(); dictionary["gungnir.var"] = itemAt.m_variant.ToString(); itemAt.m_customData = dictionary; StaffContainer.Forget(itemAt); ModConfig.Trace($"Carried the staff rack onto the upgraded Gungnir (level {itemAt.m_quality})."); } } } } [HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")] internal static class QuickMoveToRackPatch { private static bool Prefix(InventoryGui __instance, InventoryGrid grid, ItemData item, Modifier mod) { //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Invalid comparison between Unknown and I4 //IL_0061: Unknown result type (might be due to invalid IL or missing references) if (ModConfig.VerboseLogging.Value) { string arg = (((Object)(object)grid == (Object)(object)GungnirBar.Grid) ? "RACK" : (((Object)(object)grid == (Object)(object)__instance.m_playerGrid) ? "PLAYER" : (((Object)(object)grid == (Object)(object)__instance.m_containerGrid) ? "CONTAINER" : "other"))); ModConfig.Trace($"OnSelectedItem grid={arg} mod={mod} " + "item=" + (item?.m_shared?.m_name ?? "empty") + " drag=" + (__instance.m_dragItem?.m_shared?.m_name ?? "nothing")); } if (!ModConfig.Enabled.Value || (int)mod != 2 || item == null) { return true; } if (__instance.m_dragItem != null || (Object)(object)grid == (Object)(object)GungnirBar.Grid || (Object)(object)grid != (Object)(object)__instance.m_playerGrid) { return true; } if ((Object)(object)__instance.m_currentContainer != (Object)null || !StaffRegistry.IsStaff(item)) { return true; } Player localPlayer = Player.m_localPlayer; ItemData val = GungnirItem.Active(localPlayer); StaffContainer staffContainer = ((val != null) ? StaffContainer.For(val) : null); if (staffContainer == null) { return true; } if (!staffContainer.Inventory.CanAddItem(item, -1)) { ((Character)localPlayer).Message((MessageType)2, "$gungnir_msg_rack_full", 0, (Sprite)null); return false; } staffContainer.Inventory.MoveItemToThis(((Humanoid)localPlayer).m_inventory, item); staffContainer.SaveToItem(); ModConfig.Trace("Quick-moved " + item.m_shared.m_name + " into the rack."); return false; } } [HarmonyPatch(typeof(InventoryGui), "OnDropOutside")] internal static class DropOutsidePatch { private static bool Prefix(InventoryGui __instance) { if (!ModConfig.Enabled.Value || __instance.m_dragItem == null) { return true; } if (!GungnirBar.PointerIsOverBar()) { return true; } ModConfig.Trace("Drop-outside landed on the staff rack; placing instead."); return !GungnirBar.TryPlaceDraggedItem(__instance); } } [HarmonyPatch(typeof(InventoryGrid), "DropItem")] internal static class InventoryGridDropPatch { private static bool Prefix(InventoryGrid __instance, ItemData item, ref bool __result) { if ((Object)(object)GungnirBar.Grid == (Object)null || (Object)(object)__instance != (Object)(object)GungnirBar.Grid) { return true; } if (StaffRegistry.IsStaff(item)) { ModConfig.Trace("Accepting " + item.m_shared.m_name + " into the rack."); return true; } ModConfig.Trace("Rejecting " + (item?.m_shared?.m_name ?? "null") + " from the rack."); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "$gungnir_msg_only_staffs", 0, (Sprite)null); } __result = false; return false; } } [HarmonyPatch(typeof(ItemData), "GetIcon")] internal static class ItemIconPatch { private static void Postfix(ItemData __instance, ref Sprite __result) { if (ModConfig.Enabled.Value && GungnirItem.IsGungnir(__instance)) { Sprite[] array = GungnirItem.BaseShared?.m_icons; if (array != null && array.Length != 0 && (Object)(object)array[0] != (Object)null) { __result = array[0]; } } } } [HarmonyPatch(typeof(Character), "Damage")] internal static class CharacterDamagePatch { private static void Prefix(HitData hit) { if (hit != null) { Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if (!((Object)(object)val == (Object)null) && !((Object)(object)val != (Object)(object)Player.m_localPlayer)) { LightningStrike.TryStrike(hit, val); } } } } internal static class ObjectDbRegistration { internal static void Ensure(string source) { try { ObjectDB instance = ObjectDB.instance; if (!GungnirItem.HasVanillaItems(instance)) { ModConfig.Trace("ObjectDB." + source + " is the start scene's; waiting for the game's."); return; } GungnirVisual.Preload(); if (GungnirItem.Create()) { ModConfig.Trace("Gungnir registered from ObjectDB." + source + "."); } } catch (Exception arg) { GungnirStaffPlugin.Log.LogError((object)("Registering Gungnir during ObjectDB." + source + " failed. Any Gungnir in a " + $"loaded inventory will be dropped on load: {arg}")); } } } [HarmonyPatch(typeof(ObjectDB), "Awake")] internal static class ObjectDbAwakePatch { private static void Postfix() { ObjectDbRegistration.Ensure("Awake"); } } [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] internal static class ObjectDbCopyPatch { private static void Postfix() { ObjectDbRegistration.Ensure("CopyOtherDB"); } } [HarmonyPatch(typeof(Player))] internal static class PlayerPatches { [HarmonyPostfix] [HarmonyPatch("OnSpawned")] private static void OnSpawned_Postfix(Player __instance) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { StaffRegistry.Invalidate(); GungnirVisual.Preload(); GungnirItem.Create(); GungnirItem.RepairInventory(__instance); ItemData val = GungnirItem.CarriedBy(__instance); if (val != null) { StaffSwitcher.Reapply(__instance, val); } } } [HarmonyPrefix] [HarmonyPatch("UseHotbarItem")] private static bool UseHotbarItem_Prefix() { if (!ModConfig.Enabled.Value) { return true; } if (GungnirItem.Active(Player.m_localPlayer) == null) { return true; } return !Inputs.SlotShortcutActive(); } } [HarmonyPatch(typeof(Requirement), "GetAmount")] internal static class RequirementAmountPatch { private static void Postfix(Requirement __instance, int qualityLevel, ref int __result) { if (GungnirRecipe.ExactCosts.TryGetValue(__instance, out var value) && value.Length != 0) { int num = Mathf.Clamp(qualityLevel, 1, value.Length) - 1; __result = value[num]; } } } [HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[] { typeof(ItemData), typeof(int), typeof(bool), typeof(float), typeof(int) })] internal static class TooltipPatch { private static void Postfix(ItemData item, int qualityLevel, ref string __result) { if (!ModConfig.Enabled.Value || !GungnirItem.IsGungnir(item)) { return; } int num = ((ModConfig.SlotCount.Value > 0) ? ModConfig.SlotCount.Value : GungnirRecipe.SlotsForQuality(qualityLevel)); int num2 = 0; StaffContainer staffContainer = StaffContainer.For(item); if (staffContainer != null) { for (int i = 0; i < staffContainer.Inventory.m_width; i++) { if (staffContainer.ItemAt(i) != null) { num2++; } } } string text = "\n"; text = text + "\nStaff rack: " + num2 + " / " + num + " staffs"; if (GungnirRecipe.MoreSlotsAvailable(qualityLevel)) { text = text + " (+" + 2 + " per upgrade)"; } float value = ModConfig.LightningChance.Value; if (value > 0f && ModConfig.LightningDamage.Value > 0f) { text = text + "\nStorm-touched: " + value.ToString("P0") + " chance of " + ModConfig.LightningDamage.Value.ToString("0") + " extra lightning damage on top of every hit's damage"; } __result += text; } } [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(string), typeof(int), typeof(int), typeof(int), typeof(long), typeof(string), typeof(bool) })] internal static class InventoryAddItemPatch { private static void Postfix(string name, ItemData __result) { if (__result != null && !((Object)(object)__result.m_dropPrefab != (Object)null) && !(name != "GungnirStaff")) { GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab("GungnirStaff") : null); if ((Object)(object)val != (Object)null) { __result.m_dropPrefab = val; ModConfig.Trace("Filled in m_dropPrefab on a newly created Gungnir."); } } } } [HarmonyPatch(typeof(Humanoid), "SetupVisEquipment")] internal static class SetupVisEquipmentPatch { private static bool _logged; private static void Prefix(Humanoid __instance) { Repair(__instance.m_rightItem); Repair(__instance.m_leftItem); Repair(__instance.m_hiddenRightItem); Repair(__instance.m_hiddenLeftItem); } private static void Repair(ItemData item) { if (item == null || (Object)(object)item.m_dropPrefab != (Object)null || item.m_shared == null || item.m_shared.m_name != "$gungnir_item_name") { return; } GameObject val = GungnirItem.Prefab ?? (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab("GungnirStaff") : null); if (!((Object)(object)val == (Object)null)) { item.m_dropPrefab = val; if (!_logged) { _logged = true; GungnirStaffPlugin.Log.LogWarning((object)"A Gungnir reached the player without m_dropPrefab - restored it. The standalone prefab is inactive, so ItemDrop.Awake never fills it in."); } } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }