Decompiled source of DeepNorthStaffVisuals v1.0.1

DeepNorthStaffVisuals.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("DeepNorthStaffVisuals")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1+dcd1a19a5036bc7f9bca0a78bc825712e3af73c6")]
[assembly: AssemblyProduct("DeepNorthStaffVisuals")]
[assembly: AssemblyTitle("DeepNorthStaffVisuals")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace DeepNorthStaffVisuals
{
	internal static class Copier
	{
		public static void Copy(Transform part, Transform donorModel, Transform container, Fit fit, MeshRenderer surface, double rateBoost, double ringRate, double ringLife)
		{
			//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)
			//IL_001b: 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_0025: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: 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_00c4: 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_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: 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_0107: 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_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_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: 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_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: 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_0209: 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_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = Object.Instantiate<GameObject>(((Component)part).gameObject, container, false).transform;
			Matrix4x4 worldToLocalMatrix = donorModel.worldToLocalMatrix;
			Quaternion val = Quaternion.Inverse(donorModel.rotation);
			Quaternion val2 = Quaternion.LookRotation(ToUnity(fit.Rotate(new V3(0.0, 0.0, 1.0))), ToUnity(fit.Rotate(new V3(0.0, 1.0, 0.0))));
			Matrix4x4 val3 = worldToLocalMatrix * part.localToWorldMatrix;
			Vector4 column = ((Matrix4x4)(ref val3)).GetColumn(0);
			float magnitude = ((Vector4)(ref column)).magnitude;
			column = ((Matrix4x4)(ref val3)).GetColumn(1);
			float magnitude2 = ((Vector4)(ref column)).magnitude;
			column = ((Matrix4x4)(ref val3)).GetColumn(2);
			transform.localScale = new Vector3(magnitude, magnitude2, ((Vector4)(ref column)).magnitude);
			Transform[] componentsInChildren = ((Component)part).GetComponentsInChildren<Transform>(true);
			Transform[] componentsInChildren2 = ((Component)transform).GetComponentsInChildren<Transform>(true);
			for (int i = 0; i < componentsInChildren.Length && i < componentsInChildren2.Length; i++)
			{
				Vector3 val4 = ((Matrix4x4)(ref worldToLocalMatrix)).MultiplyPoint3x4(componentsInChildren[i].position);
				componentsInChildren2[i].position = container.TransformPoint(ToUnity(fit.Point(new V3(val4.x, val4.y, val4.z))));
				componentsInChildren2[i].rotation = container.rotation * val2 * (val * componentsInChildren[i].rotation);
			}
			ParticleSystem[] componentsInChildren3 = ((Component)part).GetComponentsInChildren<ParticleSystem>(true);
			ParticleSystem[] componentsInChildren4 = ((Component)transform).GetComponentsInChildren<ParticleSystem>(true);
			List<ParticleSystem> list = new List<ParticleSystem>();
			for (int j = 0; j < componentsInChildren3.Length && j < componentsInChildren4.Length; j++)
			{
				string name = ((Object)((Component)componentsInChildren3[j]).gameObject).name;
				if ((Object)(object)surface != (Object)null && Looks.FollowsWeapon(name))
				{
					Trace(componentsInChildren4[j], surface, fit);
				}
				else
				{
					Stretch(componentsInChildren4[j], val * ((Component)componentsInChildren3[j]).transform.rotation, fit);
				}
				EmissionModule emission = componentsInChildren4[j].emission;
				if (Looks.SpreadsAlongWeapon(name))
				{
					EmissionModule emission2 = componentsInChildren3[j].emission;
					((EmissionModule)(ref emission)).rateOverTimeMultiplier = ((EmissionModule)(ref emission2)).rateOverTimeMultiplier;
					Scale(componentsInChildren4[j], ringRate);
					MainModule main = componentsInChildren4[j].main;
					((MainModule)(ref main)).startLifetime = Times(((MainModule)(ref main)).startLifetime, ringLife);
					list.Add(componentsInChildren4[j]);
				}
				else
				{
					((EmissionModule)(ref emission)).rateOverTimeMultiplier = ((EmissionModule)(ref emission)).rateOverTimeMultiplier * (float)rateBoost;
				}
			}
			foreach (ParticleSystem item in list)
			{
				Spread(item, container, fit);
			}
		}

		private static void Spread(ParticleSystem ring, Transform container, Fit fit)
		{
			//IL_0013: 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_001b: 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_0025: 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_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_0072: 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_0078: 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_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_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: 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_00d0: 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_00f5: 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_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)ring).transform;
			Vector3 val = ToUnity(fit.Target.Unit(0));
			Vector3 val2 = container.InverseTransformPoint(transform.position);
			double num = fit.Target.Size(0);
			double num2 = fit.Target.Fraction(FromUnity(val2), 0);
			Quaternion rotation = transform.rotation;
			bool flag = Leans(ring, container, fit);
			if (flag)
			{
				Scale(ring, 0.5);
			}
			Quaternion rotation2 = Quaternion.AngleAxis(180f, container.TransformDirection(val)) * rotation;
			List<double> list = Fit.RingFractions(num, Drift(ring));
			for (int i = 0; i < list.Count; i++)
			{
				Vector3 position = container.TransformPoint(val2 + val * (float)((list[i] - num2) * num));
				Place((i == 0) ? transform : Object.Instantiate<GameObject>(((Component)transform).gameObject, transform.parent, false).transform, position, rotation);
				if (flag)
				{
					Place(Object.Instantiate<GameObject>(((Component)transform).gameObject, transform.parent, false).transform, position, rotation2);
				}
			}
		}

		private static void Place(Transform copy, Vector3 position, Quaternion rotation)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			copy.position = position;
			copy.rotation = rotation;
		}

		private static bool Leans(ParticleSystem ring, Transform container, Fit fit)
		{
			//IL_0011: 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_001c: 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_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_002e: 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_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_003f: Unknown result type (might be due to invalid IL or missing references)
			if (!IsCone(ring))
			{
				return false;
			}
			Quaternion rotation = ((Component)ring).transform.rotation;
			ShapeModule shape = ring.shape;
			Vector3 v = container.InverseTransformDirection(rotation * Quaternion.Euler(((ShapeModule)(ref shape)).rotation) * Vector3.forward);
			return fit.Leans(FromUnity(v));
		}

		private static void Scale(ParticleSystem system, double factor)
		{
			//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_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_0037: Unknown result type (might be due to invalid IL or missing references)
			EmissionModule emission = system.emission;
			((EmissionModule)(ref emission)).rateOverTimeMultiplier = ((EmissionModule)(ref emission)).rateOverTimeMultiplier * (float)factor;
			for (int i = 0; i < ((EmissionModule)(ref emission)).burstCount; i++)
			{
				Burst burst = ((EmissionModule)(ref emission)).GetBurst(i);
				((Burst)(ref burst)).probability = ((Burst)(ref burst)).probability * (float)factor;
				((EmissionModule)(ref emission)).SetBurst(i, burst);
			}
		}

		private static bool IsCone(ParticleSystem system)
		{
			//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_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: 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_0011: Invalid comparison between Unknown and I4
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Invalid comparison between Unknown and I4
			ShapeModule shape = system.shape;
			ParticleSystemShapeType shapeType = ((ShapeModule)(ref shape)).shapeType;
			if ((int)shapeType != 4)
			{
				return (int)shapeType == 8;
			}
			return true;
		}

		private static double Drift(ParticleSystem ring)
		{
			//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_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)
			//IL_0016: 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_0050: 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)
			//IL_0061: 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)
			VelocityOverLifetimeModule velocityOverLifetime = ring.velocityOverLifetime;
			bool firedAlongAxis = IsCone(ring);
			MainModule main = ring.main;
			double startSpeed = Mean(((MainModule)(ref main)).startSpeed);
			double velocityAlongAxis = (((VelocityOverLifetimeModule)(ref velocityOverLifetime)).enabled ? Mean(((VelocityOverLifetimeModule)(ref velocityOverLifetime)).z) : 0f);
			double radial = (((VelocityOverLifetimeModule)(ref velocityOverLifetime)).enabled ? Mean(((VelocityOverLifetimeModule)(ref velocityOverLifetime)).radial) : 0f);
			main = ring.main;
			return Fit.Drift(firedAlongAxis, startSpeed, velocityAlongAxis, radial, Mean(((MainModule)(ref main)).startLifetime));
		}

		private static MinMaxCurve Times(MinMaxCurve curve, double factor)
		{
			//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)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			float num = (float)factor;
			ParticleSystemCurveMode mode = ((MinMaxCurve)(ref curve)).mode;
			if ((int)mode != 0)
			{
				if ((int)mode == 3)
				{
					((MinMaxCurve)(ref curve)).constantMin = ((MinMaxCurve)(ref curve)).constantMin * num;
					((MinMaxCurve)(ref curve)).constantMax = ((MinMaxCurve)(ref curve)).constantMax * num;
				}
				else
				{
					((MinMaxCurve)(ref curve)).curveMultiplier = ((MinMaxCurve)(ref curve)).curveMultiplier * num;
				}
			}
			else
			{
				((MinMaxCurve)(ref curve)).constant = ((MinMaxCurve)(ref curve)).constant * num;
			}
			return curve;
		}

		private static float Mean(MinMaxCurve curve)
		{
			//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_0008: 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_000d: Invalid comparison between Unknown and I4
			ParticleSystemCurveMode mode = ((MinMaxCurve)(ref curve)).mode;
			if ((int)mode != 0)
			{
				if ((int)mode == 3)
				{
					return (((MinMaxCurve)(ref curve)).constantMin + ((MinMaxCurve)(ref curve)).constantMax) / 2f;
				}
				return ((MinMaxCurve)(ref curve)).curveMultiplier;
			}
			return ((MinMaxCurve)(ref curve)).constant;
		}

		private static void Trace(ParticleSystem system, MeshRenderer surface, Fit fit)
		{
			//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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: 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_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_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)
			ShapeModule shape = system.shape;
			((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)13;
			((ShapeModule)(ref shape)).meshRenderer = surface;
			((ShapeModule)(ref shape)).meshShapeType = (ParticleSystemMeshShapeType)1;
			((ShapeModule)(ref shape)).useMeshColors = false;
			((ShapeModule)(ref shape)).position = Vector3.zero;
			((ShapeModule)(ref shape)).rotation = Vector3.zero;
			((ShapeModule)(ref shape)).scale = Vector3.one;
			EmissionModule emission = system.emission;
			((EmissionModule)(ref emission)).rateOverTimeMultiplier = ((EmissionModule)(ref emission)).rateOverTimeMultiplier * (float)fit.TraceRateFactor;
			MainModule main = system.main;
			((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1;
		}

		private static void Stretch(ParticleSystem system, Quaternion donorRotation, Fit fit)
		{
			//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_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_0019: Unknown result type (might be due to invalid IL or missing references)
			//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_0025: 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_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_003f: 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_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)
			ShapeModule shape = system.shape;
			Quaternion rotation = donorRotation * Quaternion.Euler(((ShapeModule)(ref shape)).rotation);
			((ShapeModule)(ref shape)).scale = Vector3.Scale(((ShapeModule)(ref shape)).scale, Along(rotation, fit));
			((ShapeModule)(ref shape)).position = Vector3.Scale(((ShapeModule)(ref shape)).position, Along(donorRotation, fit));
			EmissionModule emission = system.emission;
			((EmissionModule)(ref emission)).rateOverTimeMultiplier = ((EmissionModule)(ref emission)).rateOverTimeMultiplier * (float)fit.RateFactor;
		}

		private static Vector3 Along(Quaternion rotation, Fit fit)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//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_0018: 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)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3((float)fit.EmitterStretch(FromUnity(rotation * Vector3.right)), (float)fit.EmitterStretch(FromUnity(rotation * Vector3.up)), (float)fit.EmitterStretch(FromUnity(rotation * Vector3.forward)));
		}

		private static Vector3 ToUnity(V3 v)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3((float)v.X, (float)v.Y, (float)v.Z);
		}

		private static V3 FromUnity(Vector3 v)
		{
			//IL_0000: 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_000e: Unknown result type (might be due to invalid IL or missing references)
			return new V3(v.x, v.y, v.z);
		}
	}
	[HarmonyPatch]
	internal static class Dresser
	{
		private sealed class Worn
		{
			public string Look;
		}

		private sealed class StandLooks
		{
			public ArmorStand Stand;

			public bool Read;

			public uint Revision;

			public readonly string[] ByModel = new string[4];
		}

		private static readonly int s_lookKey = StringExtensionMethods.GetStableHashCode("DeepNorthStaffVisuals_look");

		private static FieldRef<VisEquipment, GameObject>[] s_models;

		private static FieldRef<VisEquipment, int>[] s_hashes;

		private static FieldRef<VisEquipment, ZNetView> s_nview;

		private static FieldRef<Humanoid, ItemData>[] s_items;

		private static readonly VisSlot[] s_modelSlots;

		private static ConditionalWeakTable<GameObject, Worn> s_worn;

		private static ConditionalWeakTable<VisEquipment, StandLooks> s_stands;

		private static bool s_updateOff;

		private static bool Prepare()
		{
			s_models = new FieldRef<VisEquipment, GameObject>[4]
			{
				AccessTools.FieldRefAccess<VisEquipment, GameObject>("m_rightItemInstance"),
				AccessTools.FieldRefAccess<VisEquipment, GameObject>("m_leftItemInstance"),
				AccessTools.FieldRefAccess<VisEquipment, GameObject>("m_rightBackItemInstance"),
				AccessTools.FieldRefAccess<VisEquipment, GameObject>("m_leftBackItemInstance")
			};
			s_hashes = new FieldRef<VisEquipment, int>[4]
			{
				AccessTools.FieldRefAccess<VisEquipment, int>("m_currentRightItemHash"),
				AccessTools.FieldRefAccess<VisEquipment, int>("m_currentLeftItemHash"),
				AccessTools.FieldRefAccess<VisEquipment, int>("m_currentRightBackItemHash"),
				AccessTools.FieldRefAccess<VisEquipment, int>("m_currentLeftBackItemHash")
			};
			s_nview = AccessTools.FieldRefAccess<VisEquipment, ZNetView>("m_nview");
			s_items = new FieldRef<Humanoid, ItemData>[4]
			{
				AccessTools.FieldRefAccess<Humanoid, ItemData>("m_rightItem"),
				AccessTools.FieldRefAccess<Humanoid, ItemData>("m_leftItem"),
				AccessTools.FieldRefAccess<Humanoid, ItemData>("m_hiddenRightItem"),
				AccessTools.FieldRefAccess<Humanoid, ItemData>("m_hiddenLeftItem")
			};
			return true;
		}

		internal static void Reset()
		{
			s_worn = new ConditionalWeakTable<GameObject, Worn>();
			s_stands = new ConditionalWeakTable<VisEquipment, StandLooks>();
			s_updateOff = false;
		}

		[HarmonyPatch(typeof(VisEquipment), "CustomUpdate")]
		[HarmonyPostfix]
		private static void CustomUpdate(VisEquipment __instance)
		{
			if (s_updateOff)
			{
				return;
			}
			try
			{
				CheckLook(__instance);
			}
			catch (Exception arg)
			{
				s_updateOff = true;
				Plugin.ErrorOnce("update", $"Looks stop changing until the next world (a game update?): {arg}");
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void CheckLook(VisEquipment vis)
		{
			if (!vis.m_isPlayer || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return;
			}
			ZNetView val = s_nview.Invoke(vis);
			ZDO val2 = (((Object)(object)val != (Object)null) ? val.GetZDO() : null);
			if (val2 == null)
			{
				return;
			}
			if (vis.m_isArmorStand)
			{
				CheckArmorStand(vis, val2);
				return;
			}
			if (IsLocalPlayer(vis))
			{
				int num = Looks.Code(Looks.FromNote(StaffOnShow()?.m_customData));
				if (val2.GetInt(s_lookKey, 0) != num)
				{
					val2.Set(s_lookKey, num, false);
				}
			}
			string look = Looks.FromCode(val2.GetInt(s_lookKey, 0));
			for (int i = 0; i < s_models.Length; i++)
			{
				WearModel(vis, i, look);
			}
		}

		private static void CheckArmorStand(VisEquipment vis, ZDO record)
		{
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			StandLooks value = s_stands.GetValue(vis, (VisEquipment v) => new StandLooks
			{
				Stand = ((Component)v).GetComponentInParent<ArmorStand>()
			});
			if ((Object)(object)value.Stand == (Object)null)
			{
				return;
			}
			if (!value.Read || value.Revision != record.DataRevision)
			{
				for (int num = 0; num < value.ByModel.Length; num++)
				{
					value.ByModel[num] = "Plain";
				}
				List<ArmorStandSlot> slots = value.Stand.m_slots;
				for (int num2 = 0; num2 < slots.Count; num2++)
				{
					int num3 = Array.IndexOf(s_modelSlots, slots[num2].m_slot);
					if (num3 >= 0 && record.GetInt(StringExtensionMethods.GetStableHashCode(num2 + "_item"), 0) != 0)
					{
						value.ByModel[num3] = Looks.FromNote(NotesOf(record, num2));
					}
				}
				value.Read = true;
				value.Revision = record.DataRevision;
			}
			for (int num4 = 0; num4 < s_models.Length; num4++)
			{
				WearModel(vis, num4, value.ByModel[num4]);
			}
		}

		internal static Dictionary<string, string> NotesOf(ZDO record, int slot)
		{
			//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_000d: Expected O, but got Unknown
			ItemData val = new ItemData();
			ItemDrop.LoadFromZDO(val, record, slot);
			return val.m_customData;
		}

		private static void WearModel(VisEquipment vis, int i, string look)
		{
			GameObject val = s_models[i].Invoke(vis);
			if ((Object)(object)val != (Object)null)
			{
				Wear(val, ObjectDB.instance.GetItemPrefab(s_hashes[i].Invoke(vis)), look);
			}
		}

		internal static void Wear(GameObject model, GameObject prefab, string look)
		{
			Worn orCreateValue = s_worn.GetOrCreateValue(model);
			if (orCreateValue.Look == look)
			{
				return;
			}
			orCreateValue.Look = look;
			try
			{
				Dress(model.transform, prefab, look);
			}
			catch (Exception arg)
			{
				Plugin.ErrorOnce("dress", $"Couldn't put the look on a weapon (it stays plain): {arg}");
			}
		}

		private static bool IsLocalPlayer(VisEquipment vis)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null)
			{
				return (Object)(object)((Component)vis).gameObject == (Object)(object)((Component)localPlayer).gameObject;
			}
			return false;
		}

		private static ItemData StaffOnShow()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return null;
			}
			FieldRef<Humanoid, ItemData>[] array = s_items;
			for (int i = 0; i < array.Length; i++)
			{
				ItemData val = array[i].Invoke((Humanoid)(object)localPlayer);
				if (val != null && EffectKit.LookKind(val.m_dropPrefab) != Kind.None)
				{
					return val;
				}
			}
			return null;
		}

		internal static void OnKey()
		{
			if (s_updateOff)
			{
				return;
			}
			ItemData val = StaffOnShow();
			if (val != null)
			{
				string text = Looks.StepNote(val.m_customData, EffectKit.IsAvailable);
				if ((Object)(object)MessageHud.instance != (Object)null)
				{
					MessageHud.instance.ShowMessage((MessageType)2, text, 0, (Sprite)null, false, false);
				}
			}
		}

		internal static bool HasLookable(bool handsOnly)
		{
			if (s_updateOff)
			{
				return false;
			}
			VisEquipment val = LocalVisEquipment();
			if ((Object)(object)val == (Object)null || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return false;
			}
			for (int i = 0; i < (handsOnly ? 2 : s_models.Length); i++)
			{
				if ((Object)(object)s_models[i].Invoke(val) != (Object)null && EffectKit.LookKind(ObjectDB.instance.GetItemPrefab(s_hashes[i].Invoke(val))) != Kind.None)
				{
					return true;
				}
			}
			return false;
		}

		private static VisEquipment LocalVisEquipment()
		{
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer != (Object)null))
			{
				return null;
			}
			return ((Component)localPlayer).GetComponent<VisEquipment>();
		}

		private static void Dress(Transform model, GameObject prefab, string look)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Expected O, but got Unknown
			foreach (Transform item in model)
			{
				Transform val = item;
				if (((Object)val).name == "DeepNorthStaffVisuals_look")
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
			}
			if (look == "Plain")
			{
				return;
			}
			Kind kind = EffectKit.LookKind(prefab);
			if (kind == Kind.None)
			{
				return;
			}
			Fix fix = Fixes.For(((Object)prefab).name, look);
			EffectKit.Donor donor = EffectKit.DonorFor(look, (fix != null && fix.DonorKind != Kind.None) ? fix.DonorKind : kind);
			if (donor == null || !EffectKit.ModelFrameOf(model, kind, out var frame, out var main))
			{
				return;
			}
			Fit fit = new Fit(donor.Frame, frame, WeaponKinds.GameEffectStart(donor.Kind), WeaponKinds.EffectStart(kind), fix);
			MeshRenderer val2 = ((Component)main).GetComponent<MeshRenderer>();
			if ((Object)(object)val2 == (Object)null || !EffectKit.CanEmitFrom(model, main))
			{
				val2 = null;
			}
			GameObject val3 = new GameObject("DeepNorthStaffVisuals_look");
			val3.SetActive(false);
			val3.transform.SetParent(model, false);
			foreach (Transform part in donor.Parts)
			{
				Copier.Copy(part, donor.Model, val3.transform, fit, val2, Looks.RateBoost(look), Looks.RingRate(look), Looks.RingLife(look));
			}
			val3.SetActive(true);
		}

		static Dresser()
		{
			VisSlot[] array = new VisSlot[4];
			RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
			s_modelSlots = (VisSlot[])(object)array;
			s_worn = new ConditionalWeakTable<GameObject, Worn>();
			s_stands = new ConditionalWeakTable<VisEquipment, StandLooks>();
		}
	}
	internal static class EffectKit
	{
		internal sealed class Donor
		{
			public string Name;

			public Kind Kind;

			public Transform Model;

			public ModelFrame Frame;

			public List<Transform> Parts;
		}

		public const string Container = "DeepNorthStaffVisuals_look";

		private static readonly HashSet<string> s_skip = new HashSet<string> { "UpgraderGlow", "equiped", "DeepNorthStaffVisuals_look" };

		private static readonly Dictionary<string, Kind> s_kinds = new Dictionary<string, Kind>();

		private static readonly Dictionary<string, Donor> s_donors = new Dictionary<string, Donor>();

		private static readonly Dictionary<string, bool> s_available = new Dictionary<string, bool>();

		public static void Clear()
		{
			s_kinds.Clear();
			s_donors.Clear();
			s_available.Clear();
		}

		public static Kind LookKind(GameObject prefab)
		{
			if ((Object)(object)prefab == (Object)null)
			{
				return Kind.None;
			}
			if (s_kinds.TryGetValue(((Object)prefab).name, out var value))
			{
				return value;
			}
			Kind kind = ReadLookKind(prefab);
			s_kinds[((Object)prefab).name] = kind;
			return kind;
		}

		private static Kind ReadLookKind(GameObject prefab)
		{
			//IL_002c: 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)
			ItemDrop component = prefab.GetComponent<ItemDrop>();
			if ((Object)(object)component == (Object)null || !WeaponKinds.CanTakeLook(((Object)prefab).name))
			{
				return Kind.None;
			}
			SharedData shared = component.m_itemData.m_shared;
			Kind kind = WeaponKinds.KindOf(shared.m_itemType, shared.m_skillType, ((Object)prefab).name);
			if (kind == Kind.None)
			{
				return Kind.None;
			}
			Transform val = HeldModel(prefab.transform);
			if ((Object)(object)val == (Object)null || ((Object)val).name != "attach")
			{
				return Kind.None;
			}
			if (HasOwnEffects(val))
			{
				return Kind.None;
			}
			if (!ModelFrameOf(val, kind, out var _, out var _))
			{
				return Kind.None;
			}
			return kind;
		}

		private static Transform HeldModel(Transform prefab)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			foreach (Transform item in prefab)
			{
				Transform val = item;
				if (((Object)val).name == "attach" || ((Object)val).name == "attach_skin")
				{
					return val;
				}
			}
			return null;
		}

		private static bool HasOwnEffects(Transform t)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			if ((Object)(object)((Component)t).GetComponent<ParticleSystem>() != (Object)null || (Object)(object)((Component)t).GetComponent<Light>() != (Object)null)
			{
				return true;
			}
			foreach (Transform item in t)
			{
				Transform val = item;
				if (!s_skip.Contains(((Object)val).name) && HasOwnEffects(val))
				{
					return true;
				}
			}
			return false;
		}

		public static bool ModelFrameOf(Transform model, Kind kind, out ModelFrame frame, out MeshFilter main)
		{
			//IL_001b: 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_005e: 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_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_007a: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: 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_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: 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_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_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: 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)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: 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_00e2: Unknown result type (might be due to invalid IL or missing references)
			frame = null;
			main = null;
			List<V3> list = new List<V3>();
			V3[] array = null;
			double[] meshSizes = null;
			double num = -1.0;
			Matrix4x4 worldToLocalMatrix = model.worldToLocalMatrix;
			MeshFilter[] componentsInChildren = ((Component)model).GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val in componentsInChildren)
			{
				if (!((Object)(object)val.sharedMesh == (Object)null) && !IsSkipped(((Component)val).transform, model))
				{
					Matrix4x4 val2 = worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix;
					Bounds bounds = val.sharedMesh.bounds;
					for (int j = 0; j < 8; j++)
					{
						Vector3 val3 = ((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3((float)(((j & 1) != 0) ? 1 : (-1)), (float)(((j & 2) != 0) ? 1 : (-1)), (float)(((j & 4) != 0) ? 1 : (-1))));
						Vector3 val4 = ((Matrix4x4)(ref val2)).MultiplyPoint3x4(val3);
						list.Add(new V3(val4.x, val4.y, val4.z));
					}
					V3[] array2 = new V3[3];
					double[] array3 = new double[3];
					for (int k = 0; k < 3; k++)
					{
						Vector3 val5 = Vector4.op_Implicit(((Matrix4x4)(ref val2)).GetColumn(k));
						array2[k] = new V3(val5.x, val5.y, val5.z);
						int num2 = k;
						Vector3 extents = ((Bounds)(ref bounds)).extents;
						array3[num2] = 2f * ((Vector3)(ref extents))[k] * ((Vector3)(ref val5)).magnitude;
					}
					double num3 = Math.Max(array3[0], Math.Max(array3[1], array3[2]));
					if (num3 > num)
					{
						num = num3;
						array = array2;
						meshSizes = array3;
						main = val;
					}
				}
			}
			if (array == null)
			{
				return false;
			}
			frame = new ModelFrame(array, meshSizes, WeaponKinds.HeadSign(kind), list);
			return true;
		}

		public static bool CanEmitFrom(Transform model, MeshFilter main)
		{
			//IL_004e: 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)
			Mesh val = (((Object)(object)main != (Object)null) ? main.sharedMesh : null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			if (val.isReadable)
			{
				return true;
			}
			Transform val2 = model.Find("UpgraderGlow");
			if ((Object)(object)val2 == (Object)null)
			{
				return false;
			}
			ParticleSystem[] componentsInChildren = ((Component)val2).GetComponentsInChildren<ParticleSystem>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				ShapeModule shape = componentsInChildren[i].shape;
				if ((Object)(object)((ShapeModule)(ref shape)).mesh == (Object)(object)val)
				{
					return true;
				}
			}
			return false;
		}

		private static bool IsSkipped(Transform t, Transform model)
		{
			while ((Object)(object)t != (Object)null && (Object)(object)t != (Object)(object)model)
			{
				if (s_skip.Contains(((Object)t).name))
				{
					return true;
				}
				t = t.parent;
			}
			return false;
		}

		public static Donor DonorFor(string look, Kind kind)
		{
			foreach (string item in Looks.DonorsFor(look, kind))
			{
				Donor donor = GetDonor(item);
				if (donor != null)
				{
					return donor;
				}
			}
			return null;
		}

		public static bool IsAvailable(string look)
		{
			if (s_available.TryGetValue(look, out var value))
			{
				return value;
			}
			value = DonorFor(look, Kind.None) != null;
			if (!value)
			{
				Plugin.WarnOnce("look:" + look, "The look " + look + " has no donor weapon in this game version: skipped");
			}
			s_available[look] = value;
			return value;
		}

		private static Donor GetDonor(string name)
		{
			if (s_donors.TryGetValue(name, out var value))
			{
				return value;
			}
			value = ReadDonor(name);
			if (value == null)
			{
				Plugin.WarnOnce("donor:" + name, "Donor weapon " + name + " or its effects weren't found (a game update?): skipped");
			}
			s_donors[name] = value;
			return value;
		}

		private static Donor ReadDonor(string name)
		{
			//IL_006d: 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)
			GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(name) : null);
			ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null);
			Transform val3 = (((Object)(object)val != (Object)null) ? val.transform.Find("attach") : null);
			if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null)
			{
				return null;
			}
			SharedData shared = val2.m_itemData.m_shared;
			Kind kind = WeaponKinds.KindOf(shared.m_itemType, shared.m_skillType, name);
			if (!ModelFrameOf(val3, kind, out var frame, out var _))
			{
				return null;
			}
			List<Transform> list = new List<Transform>();
			FindParts(val3, list);
			if (list.Count == 0)
			{
				return null;
			}
			return new Donor
			{
				Name = name,
				Kind = kind,
				Model = val3,
				Frame = frame,
				Parts = list
			};
		}

		private static void FindParts(Transform t, List<Transform> parts)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			foreach (Transform item in t)
			{
				Transform val = item;
				if (!s_skip.Contains(((Object)val).name) && (((Component)val).GetComponentsInChildren<ParticleSystem>(true).Length != 0 || ((Component)val).GetComponentsInChildren<Light>(true).Length != 0))
				{
					if (((Component)val).GetComponentsInChildren<MeshFilter>(true).Length == 0)
					{
						parts.Add(val);
					}
					else
					{
						FindParts(val, parts);
					}
				}
			}
		}
	}
	internal readonly struct V3
	{
		public readonly double X;

		public readonly double Y;

		public readonly double Z;

		public double this[int axis] => axis switch
		{
			1 => Y, 
			0 => X, 
			_ => Z, 
		};

		public double Length => Math.Sqrt(X * X + Y * Y + Z * Z);

		public V3(double x, double y, double z)
		{
			X = x;
			Y = y;
			Z = z;
		}

		public static V3 operator +(V3 a, V3 b)
		{
			return new V3(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
		}

		public static V3 operator *(double s, V3 v)
		{
			return new V3(s * v.X, s * v.Y, s * v.Z);
		}

		public static double Dot(V3 a, V3 b)
		{
			return a.X * b.X + a.Y * b.Y + a.Z * b.Z;
		}

		public static V3 Axis(int axis, int sign)
		{
			return new V3((axis == 0) ? sign : 0, (axis == 1) ? sign : 0, (axis == 2) ? sign : 0);
		}

		public static V3 Cross(V3 a, V3 b)
		{
			return new V3(a.Y * b.Z - a.Z * b.Y, a.Z * b.X - a.X * b.Z, a.X * b.Y - a.Y * b.X);
		}

		public V3 Normalized()
		{
			if (!(Length < 1E-12))
			{
				return 1.0 / Length * this;
			}
			return this;
		}

		public double Largest()
		{
			if (!(Math.Abs(X) >= Math.Abs(Y)) || !(Math.Abs(X) >= Math.Abs(Z)))
			{
				if (!(Math.Abs(Y) >= Math.Abs(Z)))
				{
					return Z;
				}
				return Y;
			}
			return X;
		}

		public override string ToString()
		{
			return $"({X:0.###}, {Y:0.###}, {Z:0.###})";
		}
	}
	internal readonly struct Box
	{
		public readonly V3 Min;

		public readonly V3 Max;

		public Box(V3 min, V3 max)
		{
			Min = min;
			Max = max;
		}

		public double Size(int axis)
		{
			return Max[axis] - Min[axis];
		}
	}
	internal sealed class ModelFrame
	{
		private const double Tiny = 1E-06;

		public readonly V3[] Axes = new V3[3];

		public readonly double[] Min = new double[3];

		public readonly double[] Max = new double[3];

		public ModelFrame(V3[] meshAxes, double[] meshSizes, int headSign, IEnumerable<V3> corners)
		{
			int[] array = (from i in Enumerable.Range(0, 3)
				orderby meshSizes[i] descending, i
				select i).ToArray();
			V3 v = meshAxes[array[0]].Normalized();
			V3 v2 = meshAxes[array[1]].Normalized();
			if (((Math.Abs(v.Z) >= 0.1) ? v.Z : v.Largest()) < 0.0 != headSign < 0)
			{
				v = -1.0 * v;
			}
			if (v2.Largest() < 0.0)
			{
				v2 = -1.0 * v2;
			}
			Axes[0] = v;
			Axes[1] = v2;
			Axes[2] = V3.Cross(v, v2);
			for (int num = 0; num < 3; num++)
			{
				Min[num] = double.MaxValue;
				Max[num] = double.MinValue;
			}
			foreach (V3 corner in corners)
			{
				for (int num2 = 0; num2 < 3; num2++)
				{
					double num3 = V3.Dot(corner, Axes[num2]);
					if (num3 < Min[num2])
					{
						Min[num2] = num3;
					}
					if (num3 > Max[num2])
					{
						Max[num2] = num3;
					}
				}
			}
		}

		public ModelFrame(Box box, int headSign)
			: this(new V3[3]
			{
				V3.Axis(0, 1),
				V3.Axis(1, 1),
				V3.Axis(2, 1)
			}, new double[3]
			{
				box.Size(0),
				box.Size(1),
				box.Size(2)
			}, headSign, from i in Enumerable.Range(0, 8)
				select new V3(((i & 1) == 0) ? box.Min.X : box.Max.X, ((i & 2) == 0) ? box.Min.Y : box.Max.Y, ((i & 4) == 0) ? box.Min.Z : box.Max.Z))
		{
		}

		public double Size(int k)
		{
			return Max[k] - Min[k];
		}

		public V3 Unit(int k)
		{
			return Axes[k];
		}

		public double Fraction(V3 p, int k)
		{
			double num = Size(k);
			if (!(num < 1E-06))
			{
				return (V3.Dot(p, Axes[k]) - Min[k]) / num;
			}
			return 0.5;
		}

		public double Coordinate(int k, double fraction)
		{
			return Min[k] + fraction * Size(k);
		}
	}
	internal sealed class Fit
	{
		public const double MinLengthStretch = 0.25;

		public const double MaxLengthStretch = 4.0;

		public const double MinSideStretch = 0.5;

		public const double MaxSideStretch = 2.0;

		public const double MinRate = 0.5;

		public const double MaxRate = 2.0;

		public readonly ModelFrame Donor;

		public readonly ModelFrame Target;

		private readonly double[] m_stretch = new double[3];

		private readonly double[] m_shift = new double[3];

		private readonly double m_donorStart;

		private readonly double m_targetStart;

		public readonly double RateFactor;

		public readonly double TraceRateFactor;

		public const double LeanDegrees = 1.0;

		public Fit(ModelFrame donor, ModelFrame target, double donorStart, double targetStart, Fix fix)
		{
			Donor = donor;
			Target = target;
			m_donorStart = donorStart;
			m_targetStart = targetStart;
			double num = fix?.Stretch ?? 1.0;
			double v = BusinessEndRatio();
			m_stretch[0] = Clamp(v, 0.25, 4.0) * num;
			for (int i = 1; i < 3; i++)
			{
				m_stretch[i] = Clamp(Ratio(i), 0.5, 2.0) * num;
			}
			RateFactor = Clamp(v, 0.5, 2.0);
			double num2 = (1.0 - donorStart) * donor.Size(0);
			TraceRateFactor = ((num2 < 1E-06) ? 1.0 : Clamp(target.Size(0) / num2, 0.5, 2.0));
			m_shift[0] = fix?.Along ?? 0.0;
			m_shift[1] = fix?.Across ?? 0.0;
		}

		private double Ratio(int k)
		{
			double num = Donor.Size(k);
			if (!(num < 1E-06))
			{
				return Target.Size(k) / num;
			}
			return 1.0;
		}

		private double BusinessEndRatio()
		{
			double num = (1.0 - m_donorStart) * Donor.Size(0);
			if (!(num < 1E-06))
			{
				return (1.0 - m_targetStart) * Target.Size(0) / num;
			}
			return 1.0;
		}

		private double MapLength(double f)
		{
			if (f < m_donorStart && m_donorStart > 1E-06)
			{
				return f * m_targetStart / m_donorStart;
			}
			double num = 1.0 - m_donorStart;
			if (!(num < 1E-06))
			{
				return m_targetStart + (f - m_donorStart) * (1.0 - m_targetStart) / num;
			}
			return f;
		}

		private static double Clamp(double v, double min, double max)
		{
			if (!(v < min))
			{
				if (!(v > max))
				{
					return v;
				}
				return max;
			}
			return min;
		}

		public static double Drift(bool firedAlongAxis, double startSpeed, double velocityAlongAxis, double radial, double lifetime)
		{
			return Math.Max(0.0, (firedAlongAxis ? Math.Abs(startSpeed) : 0.0) + Math.Abs(velocityAlongAxis) + radial) * lifetime;
		}

		public static List<double> RingFractions(double length, double drift = 0.0, double spacing = 0.4, double from = 0.08, double to = 0.95)
		{
			if (length > 1E-06)
			{
				to = Math.Min(to, 1.0 - drift / length);
			}
			if (to < from)
			{
				to = from;
			}
			int num = Math.Max(1, (int)Math.Round((to - from) * length / spacing) + 1);
			List<double> list = new List<double>();
			if (num == 1)
			{
				list.Add((from + to) / 2.0);
				return list;
			}
			for (int i = 0; i < num; i++)
			{
				list.Add(from + (double)i * (to - from) / (double)(num - 1));
			}
			return list;
		}

		public bool Leans(V3 aim)
		{
			double length = aim.Length;
			if (length < 1E-09)
			{
				return false;
			}
			return Math.Abs(V3.Dot(aim, Target.Unit(0))) / length < Math.Cos(Math.PI / 180.0);
		}

		public V3 Point(V3 p)
		{
			V3 result = new V3(0.0, 0.0, 0.0);
			for (int i = 0; i < 3; i++)
			{
				double num = Donor.Fraction(p, i);
				if (i == 0)
				{
					num = MapLength(num);
				}
				result += Target.Coordinate(i, num + m_shift[i]) * Target.Unit(i);
			}
			return result;
		}

		public V3 Rotate(V3 d)
		{
			V3 result = new V3(0.0, 0.0, 0.0);
			for (int i = 0; i < 3; i++)
			{
				result += V3.Dot(d, Donor.Unit(i)) * Target.Unit(i);
			}
			return result;
		}

		public double EmitterStretch(V3 d)
		{
			double length = d.Length;
			if (length < 1E-09)
			{
				return 1.0;
			}
			V3 v = new V3(0.0, 0.0, 0.0);
			for (int i = 0; i < 3; i++)
			{
				v += V3.Dot(d, Donor.Unit(i)) * m_stretch[i] * Target.Unit(i);
			}
			return v.Length / length;
		}
	}
	internal sealed class Fix
	{
		public double Along { get; set; }

		public double Across { get; set; }

		public double Stretch { get; set; } = 1.0;

		public Kind DonorKind { get; set; }
	}
	internal static class Fixes
	{
		private static readonly Dictionary<string, Fix> s_fixes = new Dictionary<string, Fix>();

		public static Fix For(string prefab, string look)
		{
			if (!s_fixes.TryGetValue(prefab + "/" + look, out var value) && !s_fixes.TryGetValue(prefab, out value))
			{
				return null;
			}
			return value;
		}
	}
	[HarmonyPatch]
	internal static class HintPatches
	{
		internal const string RowName = "DeepNorthStaffVisuals_hint";

		internal const string Label = "Change look";

		private static KeyHints s_hints;

		private static GameObject s_row;

		private static bool s_off;

		[HarmonyPatch(typeof(KeyHints), "UpdateHints")]
		[HarmonyPostfix]
		private static void UpdateHints(KeyHints __instance)
		{
			if (s_off)
			{
				return;
			}
			try
			{
				Refresh(__instance);
			}
			catch (Exception arg)
			{
				TurnOff($"The 'Change look' key hint failed; no hint from now on: {arg}");
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void Refresh(KeyHints hints)
		{
			if ((Object)(object)hints != (Object)(object)s_hints)
			{
				s_hints = hints;
				s_row = null;
			}
			GameObject combatHints = hints.m_combatHints;
			bool flag = (Object)(object)combatHints != (Object)null && combatHints.activeSelf && Dresser.HasLookable(handsOnly: true);
			if ((Object)(object)s_row == (Object)null)
			{
				if (!flag)
				{
					return;
				}
				s_row = BuildRow(combatHints.transform);
				if ((Object)(object)s_row == (Object)null)
				{
					TurnOff("The key hint's Block row wasn't found (a game update?): no 'Change look' hint");
					return;
				}
			}
			if (s_row.activeSelf != flag)
			{
				s_row.SetActive(flag);
			}
		}

		private static GameObject BuildRow(Transform combat)
		{
			Transform val = combat.Find("Keyboard/Block");
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, val.parent, false);
			((Object)val2).name = "DeepNorthStaffVisuals_hint";
			Transform val3 = val2.transform.Find("Text");
			Transform val4 = val2.transform.Find("key_bkg/Key");
			TMP_Text val5 = (((Object)(object)val3 != (Object)null) ? ((Component)val3).GetComponent<TMP_Text>() : null);
			TMP_Text val6 = (((Object)(object)val4 != (Object)null) ? ((Component)val4).GetComponent<TMP_Text>() : null);
			if ((Object)(object)val5 == (Object)null || (Object)(object)val6 == (Object)null)
			{
				Object.Destroy((Object)(object)val2);
				return null;
			}
			val5.text = "Change look";
			val6.text = Plugin.KeyName;
			return val2;
		}

		private static void TurnOff(string message)
		{
			s_off = true;
			Plugin.Log.LogWarning((object)message);
			if ((Object)(object)s_row != (Object)null)
			{
				s_row.SetActive(false);
			}
		}
	}
	internal static class Looks
	{
		public const string Plain = "Plain";

		public static readonly string[] Order = new string[7] { "Frostfire", "Thunderblood", "Bleeding", "Storming", "Primal", "Dyrnwyn", "Frostner" };

		private static readonly Dictionary<string, Dictionary<Kind, string>> s_donors = new Dictionary<string, Dictionary<Kind, string>>
		{
			["Frostfire"] = DeepNorth("FrostFire"),
			["Thunderblood"] = DeepNorth("BloodLightning"),
			["Bleeding"] = Ashlands("SwordNiedhoggBlood", "THSwordSlayerBlood", "MaceEldnerBlood", "SpearSplitner_Blood", "BowAshlandsBlood", "CrossbowRipperBlood"),
			["Storming"] = Ashlands("SwordNiedhoggLightning", "THSwordSlayerLightning", "MaceEldnerLightning", "SpearSplitner_Lightning", "BowAshlandsStorm", "CrossbowRipperLightning"),
			["Primal"] = Ashlands("SwordNiedhoggNature", "THSwordSlayerNature", "MaceEldnerNature", "SpearSplitner_Nature", "BowAshlandsRoot", "CrossbowRipperNature"),
			["Dyrnwyn"] = new Dictionary<Kind, string> { [Kind.Sword] = "SwordDyrnwyn" },
			["Frostner"] = new Dictionary<Kind, string> { [Kind.Mace] = "MaceSilver" }
		};

		private static readonly Dictionary<Kind, Kind[]> s_fallbacks = new Dictionary<Kind, Kind[]>
		{
			[Kind.Sword] = new Kind[2]
			{
				Kind.Greatsword,
				Kind.Knife
			},
			[Kind.Greatsword] = new Kind[1] { Kind.Sword },
			[Kind.Knife] = new Kind[1] { Kind.Sword },
			[Kind.Axe] = new Kind[2]
			{
				Kind.Battleaxe,
				Kind.Mace
			},
			[Kind.Battleaxe] = new Kind[3]
			{
				Kind.Axe,
				Kind.Sledge,
				Kind.Mace
			},
			[Kind.Mace] = new Kind[1] { Kind.Sledge },
			[Kind.Sledge] = new Kind[1] { Kind.Mace },
			[Kind.Spear] = new Kind[1] { Kind.Atgeir },
			[Kind.Atgeir] = new Kind[1] { Kind.Spear },
			[Kind.Staff] = new Kind[2]
			{
				Kind.Atgeir,
				Kind.Spear
			},
			[Kind.Bow] = new Kind[1] { Kind.Crossbow },
			[Kind.Crossbow] = new Kind[1] { Kind.Bow }
		};

		private static readonly string[] s_followers = new string[11]
		{
			"flames", "fx_Torch_Basic", "Burny vfx", "Clouds", "Spores", "Spores_World", "soft cloud", "vfx_BloodHit 1", "blood drip", "Sparcs",
			"Splats"
		};

		private static readonly string[] s_spreaders = new string[2] { "Swirls", "Lightning" };

		public const string NoteKey = "DeepNorthStaffVisuals_look";

		private static Dictionary<Kind, string> DeepNorth(string variant)
		{
			return new Dictionary<Kind, string>
			{
				[Kind.Sword] = "SwordGold_" + variant,
				[Kind.Greatsword] = "THSwordGold_" + variant,
				[Kind.Knife] = "KnifeGold_" + variant,
				[Kind.Axe] = "AxeGold_" + variant,
				[Kind.Battleaxe] = "BattleaxeGold_" + variant,
				[Kind.Mace] = "MaceGold_" + variant,
				[Kind.Sledge] = "SledgeGold_" + variant,
				[Kind.Spear] = "SpearGold_" + variant,
				[Kind.Atgeir] = "AtgeirGold_" + variant,
				[Kind.Bow] = "BowGold_" + variant,
				[Kind.Crossbow] = "CrossbowGold_" + variant
			};
		}

		private static Dictionary<Kind, string> Ashlands(string sword, string greatsword, string mace, string spear, string bow, string crossbow)
		{
			return new Dictionary<Kind, string>
			{
				[Kind.Sword] = sword,
				[Kind.Greatsword] = greatsword,
				[Kind.Mace] = mace,
				[Kind.Spear] = spear,
				[Kind.Bow] = bow,
				[Kind.Crossbow] = crossbow
			};
		}

		public static List<string> DonorsFor(string look, Kind kind)
		{
			List<string> names = new List<string>();
			if (look == null || !s_donors.TryGetValue(look, out var donors))
			{
				return names;
			}
			Add(kind);
			if (s_fallbacks.TryGetValue(kind, out var value))
			{
				Kind[] array = value;
				for (int i = 0; i < array.Length; i++)
				{
					Add(array[i]);
				}
			}
			foreach (Kind value3 in Enum.GetValues(typeof(Kind)))
			{
				Add(value3);
			}
			return names;
			void Add(Kind k)
			{
				if (donors.TryGetValue(k, out var value2) && !names.Contains(value2))
				{
					names.Add(value2);
				}
			}
		}

		public static bool FollowsWeapon(string emitterName)
		{
			return Array.IndexOf(s_followers, BaseName(emitterName)) >= 0;
		}

		public static bool SpreadsAlongWeapon(string emitterName)
		{
			return Array.IndexOf(s_spreaders, BaseName(emitterName)) >= 0;
		}

		private static string BaseName(string emitterName)
		{
			if (string.IsNullOrEmpty(emitterName))
			{
				return "";
			}
			int num = emitterName.LastIndexOf(" (", StringComparison.Ordinal);
			if (num <= 0 || !emitterName.EndsWith(")", StringComparison.Ordinal))
			{
				return emitterName;
			}
			return emitterName.Substring(0, num);
		}

		public static double RateBoost(string look)
		{
			if (!(look == "Bleeding"))
			{
				return 1.0;
			}
			return 2.5;
		}

		public static double RingRate(string look)
		{
			if (!(look == "Thunderblood"))
			{
				return 1.0;
			}
			return 0.6;
		}

		public static double RingLife(string look)
		{
			if (!(look == "Thunderblood"))
			{
				return 1.0;
			}
			return 0.6;
		}

		public static int Code(string look)
		{
			if (Array.IndexOf(Order, look) < 0)
			{
				return 0;
			}
			return StringExtensionMethods.GetStableHashCode(look);
		}

		public static string FromCode(int code)
		{
			if (code == 0)
			{
				return "Plain";
			}
			string[] order = Order;
			foreach (string text in order)
			{
				if (StringExtensionMethods.GetStableHashCode(text) == code)
				{
					return text;
				}
			}
			return "Plain";
		}

		public static string FromNote(IDictionary<string, string> notes)
		{
			if (notes == null || !notes.TryGetValue("DeepNorthStaffVisuals_look", out var value) || Array.IndexOf(Order, value) < 0)
			{
				return "Plain";
			}
			return value;
		}

		public static void SetNote(IDictionary<string, string> notes, string look)
		{
			if (Array.IndexOf(Order, look) >= 0)
			{
				notes["DeepNorthStaffVisuals_look"] = look;
			}
			else
			{
				notes.Remove("DeepNorthStaffVisuals_look");
			}
		}

		public static string StepNote(IDictionary<string, string> notes, Func<string, bool> isAvailable)
		{
			string text = Next(FromNote(notes), isAvailable);
			SetNote(notes, text);
			return text;
		}

		public static string TooltipLine(string look)
		{
			if (Array.IndexOf(Order, look) < 0)
			{
				return "";
			}
			return "\nLook: <color=orange>" + look + "</color>";
		}

		public static string Next(string current, Func<string, bool> isAvailable)
		{
			for (int i = Array.IndexOf(Order, current) + 1; i < Order.Length; i++)
			{
				if (isAvailable(Order[i]))
				{
					return Order[i];
				}
			}
			return "Plain";
		}
	}
	[BepInPlugin("algo7.deepnorthstaffvisuals", "DeepNorthStaffVisuals", "1.0.1")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "algo7.deepnorthstaffvisuals";

		public const string Name = "DeepNorthStaffVisuals";

		public const string PluginVersion = "1.0.1";

		internal static ManualLogSource Log;

		private static ConfigEntry<KeyboardShortcut> s_key;

		private static Func<Player, bool> s_takeInput;

		private static bool s_running;

		private static readonly HashSet<string> s_logged = new HashSet<string>();

		internal static string KeyName => ((object)s_key.Value/*cast due to .constrained prefix*/).ToString();

		private void Awake()
		{
			//IL_0039: 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_0097: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			if (Application.isBatchMode)
			{
				Log.LogInfo((object)"DeepNorthStaffVisuals loaded (v1.0.1): dedicated server, nothing to do");
				return;
			}
			s_key = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "Change look key", new KeyboardShortcut((KeyCode)108, Array.Empty<KeyCode>()), "Changes the look of your equipped staff (also while it's on your back).");
			try
			{
				s_takeInput = AccessTools.MethodDelegate<Func<Player, bool>>(AccessTools.Method(typeof(Player), "TakeInput", (Type[])null, (Type[])null), (object)null, true);
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Looks are off: the game's input check wasn't found (a game update?): {arg}");
				return;
			}
			Harmony harmony = new Harmony("algo7.deepnorthstaffvisuals");
			if (!TryPatch(harmony, typeof(Dresser), "equipment hook"))
			{
				Log.LogError((object)"Looks are off: without the equipment hook nothing can be shown");
				return;
			}
			if (!TryPatch(harmony, typeof(HintPatches), "key hint hook"))
			{
				Log.LogWarning((object)"No 'Change look' key hint (the key still works)");
			}
			if (!TryPatch(harmony, typeof(StandPatches), "item stand hook"))
			{
				Log.LogWarning((object)"No looks on item stands (the rest works)");
			}
			if (!TryPatch(harmony, typeof(GroundPatches), "dropped item hook"))
			{
				Log.LogWarning((object)"No looks on dropped staffs (the rest works)");
			}
			if (!TryPatch(harmony, typeof(TooltipPatches), "tooltip hook"))
			{
				Log.LogWarning((object)"No look line in tooltips (the rest works)");
			}
			SceneManager.sceneLoaded += OnSceneLoaded;
			s_running = true;
			Log.LogInfo((object)"DeepNorthStaffVisuals loaded (v1.0.1)");
		}

		private void OnDestroy()
		{
			SceneManager.sceneLoaded -= OnSceneLoaded;
		}

		private static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			Dresser.Reset();
			StandPatches.Reset();
			EffectKit.Clear();
		}

		private void Update()
		{
			if (!s_running)
			{
				return;
			}
			try
			{
				CheckKey();
			}
			catch (Exception arg)
			{
				ErrorOnce("key", $"Changing the look failed: {arg}");
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void CheckKey()
		{
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null) && KeyPressed() && s_takeInput(localPlayer))
			{
				Dresser.OnKey();
			}
		}

		private static bool KeyPressed()
		{
			//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)
			//IL_000d: 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_0035: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = s_key.Value;
			if ((int)((KeyboardShortcut)(ref value)).MainKey == 0 || !ZInput.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey, false))
			{
				return false;
			}
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				if (!ZInput.GetKey(modifier, false))
				{
					return false;
				}
			}
			return true;
		}

		private static bool TryPatch(Harmony harmony, Type patches, string what)
		{
			try
			{
				harmony.PatchAll(patches);
				return true;
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Could not install the {what}: {arg}");
				return false;
			}
		}

		internal static void ErrorOnce(string kind, string message)
		{
			if (s_logged.Add("error:" + kind))
			{
				Log.LogError((object)message);
			}
		}

		internal static void WarnOnce(string kind, string message)
		{
			if (s_logged.Add("warn:" + kind))
			{
				Log.LogWarning((object)message);
			}
		}
	}
	[HarmonyPatch]
	internal static class StandPatches
	{
		private sealed class StandLook
		{
			public bool Read;

			public uint Revision;

			public string Look;
		}

		private static FieldRef<ItemStand, GameObject> s_model;

		private static FieldRef<ItemStand, int> s_modelItem;

		private static FieldRef<ItemStand, ZNetView> s_nview;

		private static ConditionalWeakTable<ItemStand, StandLook> s_looks = new ConditionalWeakTable<ItemStand, StandLook>();

		private static bool Prepare()
		{
			s_model = AccessTools.FieldRefAccess<ItemStand, GameObject>("m_visualItem");
			s_modelItem = AccessTools.FieldRefAccess<ItemStand, int>("m_visualHash");
			s_nview = AccessTools.FieldRefAccess<ItemStand, ZNetView>("m_nview");
			return true;
		}

		internal static void Reset()
		{
			s_looks = new ConditionalWeakTable<ItemStand, StandLook>();
		}

		[HarmonyPatch(typeof(ItemStand), "SetVisualItem")]
		[HarmonyPostfix]
		private static void SetVisualItem(ItemStand __instance)
		{
			Check(__instance);
		}

		[HarmonyPatch(typeof(ItemStand), "UpdateVisual")]
		[HarmonyPostfix]
		private static void UpdateVisual(ItemStand __instance)
		{
			Check(__instance);
		}

		private static void Check(ItemStand stand)
		{
			try
			{
				Wear(stand);
			}
			catch (Exception arg)
			{
				Plugin.ErrorOnce("stand", $"Couldn't show the look on an item stand (the staff stays plain): {arg}");
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void Wear(ItemStand stand)
		{
			GameObject val = s_model.Invoke(stand);
			ZNetView val2 = s_nview.Invoke(stand);
			ZDO val3 = (((Object)(object)val2 != (Object)null) ? val2.GetZDO() : null);
			if ((Object)(object)val == (Object)null || val3 == null || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return;
			}
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(s_modelItem.Invoke(stand));
			if (EffectKit.LookKind(itemPrefab) != Kind.None)
			{
				StandLook orCreateValue = s_looks.GetOrCreateValue(stand);
				if (!orCreateValue.Read || orCreateValue.Revision != val3.DataRevision)
				{
					orCreateValue.Look = Looks.FromNote(Dresser.NotesOf(val3, -1));
					orCreateValue.Read = true;
					orCreateValue.Revision = val3.DataRevision;
				}
				Dresser.Wear(val, itemPrefab, orCreateValue.Look);
			}
		}
	}
	[HarmonyPatch]
	internal static class GroundPatches
	{
		[HarmonyPatch(typeof(ItemDrop), "Start")]
		[HarmonyPostfix]
		private static void Start(ItemDrop __instance)
		{
			try
			{
				Wear(__instance);
			}
			catch (Exception arg)
			{
				Plugin.ErrorOnce("ground", $"Couldn't show the look on a dropped staff (it stays plain): {arg}");
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void Wear(ItemDrop drop)
		{
			ItemData itemData = drop.m_itemData;
			if (itemData == null || EffectKit.LookKind(itemData.m_dropPrefab) == Kind.None)
			{
				return;
			}
			string text = Looks.FromNote(itemData.m_customData);
			if (!(text == "Plain"))
			{
				Transform val = ((Component)drop).transform.Find("attach");
				if ((Object)(object)val != (Object)null)
				{
					Dresser.Wear(((Component)val).gameObject, itemData.m_dropPrefab, text);
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class TooltipPatches
	{
		[HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[]
		{
			typeof(ItemData),
			typeof(int),
			typeof(bool),
			typeof(float),
			typeof(int),
			typeof(bool)
		})]
		[HarmonyPostfix]
		private static void GetTooltip(ItemData item, bool crafting, ref string __result)
		{
			if (crafting)
			{
				return;
			}
			try
			{
				__result += LookLine(item);
			}
			catch (Exception arg)
			{
				Plugin.ErrorOnce("tooltip", $"Couldn't add the look to a tooltip: {arg}");
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static string LookLine(ItemData item)
		{
			if (item == null || EffectKit.LookKind(item.m_dropPrefab) == Kind.None)
			{
				return "";
			}
			return Looks.TooltipLine(Looks.FromNote(item.m_customData));
		}
	}
	internal enum Kind
	{
		None,
		Sword,
		Greatsword,
		Knife,
		Axe,
		Battleaxe,
		Mace,
		Sledge,
		Spear,
		Atgeir,
		Bow,
		Crossbow,
		Staff
	}
	internal static class WeaponKinds
	{
		private static readonly string[] s_notWeapons = new string[4] { "Tankard", "TankardAnniversary", "TankardOdin", "Tankard_dvergr" };

		private static readonly string[] s_takeLooks = new string[2] { "StaffOrbofAhri", "StaffThunderBlood" };

		public static Kind KindOf(ItemType type, SkillType skill, string prefabName)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Invalid comparison between Unknown and I4
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Invalid comparison between Unknown and I4
			//IL_002a: 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_006a: Expected I4, but got Unknown
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Invalid comparison between Unknown and I4
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Invalid comparison between Unknown and I4
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			if (Array.IndexOf(s_notWeapons, prefabName) >= 0)
			{
				return Kind.None;
			}
			if ((int)type != 3 && (int)type != 14 && (int)type != 22 && (int)type != 4)
			{
				return Kind.None;
			}
			bool flag = (int)type == 14;
			switch (skill - 1)
			{
			case 0:
				if (!flag)
				{
					return Kind.Sword;
				}
				return Kind.Greatsword;
			case 1:
				return Kind.Knife;
			case 2:
				if (!flag)
				{
					return Kind.Mace;
				}
				return Kind.Sledge;
			case 3:
				return Kind.Atgeir;
			case 4:
				return Kind.Spear;
			case 6:
				if (!flag)
				{
					return Kind.Axe;
				}
				return Kind.Battleaxe;
			case 7:
				return Kind.Bow;
			case 13:
				return Kind.Crossbow;
			case 8:
			case 9:
				return Kind.Staff;
			default:
				return Kind.None;
			}
		}

		public static bool CanTakeLook(string prefabName)
		{
			return Array.IndexOf(s_takeLooks, prefabName) >= 0;
		}

		public static int HeadSign(Kind kind)
		{
			if (kind != Kind.Spear)
			{
				return 1;
			}
			return -1;
		}

		public static double EffectStart(Kind kind)
		{
			return kind switch
			{
				Kind.Sword => 0.21, 
				Kind.Greatsword => 0.27, 
				Kind.Knife => 0.26, 
				Kind.Axe => 0.58, 
				Kind.Battleaxe => 0.74, 
				Kind.Mace => 0.81, 
				Kind.Sledge => 0.74, 
				Kind.Spear => 0.66, 
				Kind.Atgeir => 0.4, 
				Kind.Staff => 0.55, 
				Kind.Crossbow => 0.69, 
				_ => 0.0, 
			};
		}

		public static double GameEffectStart(Kind kind)
		{
			if (kind != Kind.Atgeir)
			{
				return EffectStart(kind);
			}
			return 0.55;
		}
	}
	internal static class PluginInfo
	{
		public const string Version = "1.0.1";
	}
}