Decompiled source of Offliner v1.0.2

Offliner.dll

Decompiled a month ago
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.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Offliner.Core;
using Offliner.Effects;
using Offliner.Patches;
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("Offliner")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+0359a4700e53b4186a27e33f60e9ed9fe4d510cd")]
[assembly: AssemblyProduct("Offliner")]
[assembly: AssemblyTitle("Offliner")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Offliner
{
	internal abstract class CheatCommand : ConsoleCommand
	{
		public sealed override bool IsCheat => true;

		public sealed override void Run(string[] args)
		{
			RunCheat(args);
		}

		protected abstract void RunCheat(string[] args);
	}
	internal class DebugCommand : CheatCommand
	{
		public override string Name => "offliner_debug";

		public override string Help => "offliner_debug - report effect state, writes BepInEx/offliner_debug.txt";

		protected override void RunCheat(string[] args)
		{
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//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_01b7: 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)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: 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_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_037f: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Unknown result type (might be due to invalid IL or missing references)
			//IL_038f: Unknown result type (might be due to invalid IL or missing references)
			//IL_039e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0448: Unknown result type (might be due to invalid IL or missing references)
			//IL_0454: Unknown result type (might be due to invalid IL or missing references)
			//IL_0460: Unknown result type (might be due to invalid IL or missing references)
			//IL_0465: Unknown result type (might be due to invalid IL or missing references)
			//IL_0479: Unknown result type (might be due to invalid IL or missing references)
			//IL_047e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0482: Unknown result type (might be due to invalid IL or missing references)
			//IL_0487: Unknown result type (might be due to invalid IL or missing references)
			//IL_049d: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fa: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			OfflinerAvatar offlinerAvatar = (((Object)(object)localPlayer != (Object)null) ? ((Component)localPlayer).GetComponent<OfflinerAvatar>() : null);
			if ((Object)(object)offlinerAvatar == (Object)null)
			{
				Console.instance.Print("offliner_debug: no local player.");
				return;
			}
			StringBuilder stringBuilder = new StringBuilder();
			Camera main = Camera.main;
			Stage stage = offlinerAvatar.Stage;
			stringBuilder.AppendLine($"level {offlinerAvatar.Level:F2} | tint {stage.Tint:F2} groans {stage.Groans} eyes {stage.Eyes} mist {stage.Mist} draugr {stage.Draugr}");
			stringBuilder.AppendLine(string.Format("camera '{0}' cullingMask {1:X8} pos {2}", ((Object)(object)main != (Object)null) ? ((Object)main).name : "none", ((Object)(object)main != (Object)null) ? main.cullingMask : 0, ((Object)(object)main != (Object)null) ? ((Component)main).transform.position : Vector3.zero));
			Transform val = Priv.Head.Invoke((Character)(object)localPlayer);
			object arg = ((Component)localPlayer).transform.position;
			object arg2;
			Vector3 val2;
			if (!((Object)(object)val != (Object)null))
			{
				arg2 = "null";
			}
			else
			{
				val2 = val.position;
				arg2 = ((Vector3)(ref val2)).ToString("F3");
			}
			stringBuilder.AppendLine($"player pos {arg} head {arg2}");
			Transform val3 = ((IEnumerable<Transform>)((Component)localPlayer).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "Offliner_HeadGlow"));
			stringBuilder.AppendLine();
			object value;
			if (!((Object)(object)val3 == (Object)null))
			{
				object[] obj = new object[4] { val3.position, null, null, null };
				object obj2;
				if (!((Object)(object)val != (Object)null))
				{
					obj2 = "?";
				}
				else
				{
					val2 = val3.position - val.position;
					obj2 = ((Vector3)(ref val2)).ToString("F3");
				}
				obj[1] = obj2;
				obj[2] = val3.lossyScale;
				obj[3] = ((Component)val3).gameObject.activeInHierarchy;
				value = string.Format("HEAD GLOW: pos {0:F3} (from head {1}) lossyScale {2:F4} active {3}", obj);
			}
			else
			{
				value = "HEAD GLOW: none";
			}
			stringBuilder.AppendLine((string?)value);
			if ((Object)(object)val3 != (Object)null)
			{
				Renderer[] componentsInChildren = ((Component)val3).GetComponentsInChildren<Renderer>(true);
				foreach (Renderer r in componentsInChildren)
				{
					Describe(stringBuilder, r, main);
				}
				Light[] componentsInChildren2 = ((Component)val3).GetComponentsInChildren<Light>(true);
				foreach (Light val4 in componentsInChildren2)
				{
					stringBuilder.AppendLine($"  light range {val4.range} intensity {val4.intensity} enabled {((Behaviour)val4).enabled} renderMode {val4.renderMode}");
				}
			}
			Transform[] array = (from t in ((Component)localPlayer).GetComponentsInChildren<Transform>(true)
				where ((Object)t).name.StartsWith("Offliner_Aura_")
				select t).ToArray();
			stringBuilder.AppendLine();
			stringBuilder.AppendLine((array.Length == 0) ? "AURA: none" : $"AURA: {array.Length} effect(s)");
			Transform[] array2 = array;
			foreach (Transform val5 in array2)
			{
				object[] obj3 = new object[5]
				{
					((Object)val5).name,
					null,
					null,
					null,
					null
				};
				Transform parent = val5.parent;
				obj3[1] = ((parent != null) ? ((Object)parent).name : null);
				obj3[2] = val5.position - ((Component)localPlayer).transform.position;
				obj3[3] = val5.lossyScale;
				obj3[4] = ((Component)val5).gameObject.activeInHierarchy;
				stringBuilder.AppendLine(string.Format(" '{0}' on '{1}' pos from player {2:F3} lossyScale {3:F3} active {4}", obj3));
				ParticleSystem[] componentsInChildren3 = ((Component)val5).GetComponentsInChildren<ParticleSystem>(true);
				foreach (ParticleSystem val6 in componentsInChildren3)
				{
					MainModule main2 = val6.main;
					string text = $"  ps '{((Object)val6).name}' playing {val6.isPlaying} count {val6.particleCount} maxParticles {((MainModule)(ref main2)).maxParticles} loop {((MainModule)(ref main2)).loop} ";
					object arg3 = ((MainModule)(ref main2)).simulationSpace;
					object arg4 = ((MainModule)(ref main2)).scalingMode;
					ShapeModule shape = val6.shape;
					object arg5;
					if (!((ShapeModule)(ref shape)).enabled)
					{
						arg5 = "off";
					}
					else
					{
						shape = val6.shape;
						string? text2 = ((object)((ShapeModule)(ref shape)).shapeType/*cast due to .constrained prefix*/).ToString();
						shape = val6.shape;
						object obj4;
						if (!((Object)(object)((ShapeModule)(ref shape)).skinnedMeshRenderer != (Object)null))
						{
							obj4 = "-";
						}
						else
						{
							shape = val6.shape;
							obj4 = ((Object)((ShapeModule)(ref shape)).skinnedMeshRenderer).name;
						}
						arg5 = text2 + " mesh " + (string?)obj4;
					}
					string text3 = $"space {arg3} scaling {arg4} shape {arg5} ";
					MinMaxCurve val7 = ((MainModule)(ref main2)).startSize;
					object arg6 = ((MinMaxCurve)(ref val7)).constant;
					val7 = ((MainModule)(ref main2)).startLifetime;
					stringBuilder.AppendLine(text + text3 + $"startSize {arg6:F2} startLifetime {((MinMaxCurve)(ref val7)).constant:F2}");
				}
				Renderer[] componentsInChildren = ((Component)val5).GetComponentsInChildren<Renderer>(true);
				foreach (Renderer r2 in componentsInChildren)
				{
					Describe(stringBuilder, r2, main);
				}
			}
			string text4 = Path.Combine(Paths.BepInExRootPath, "offliner_debug.txt");
			File.WriteAllText(text4, stringBuilder.ToString());
			Console.instance.Print(stringBuilder.ToString().Split(new char[1] { '\n' })[0]);
			Console.instance.Print("Details written to " + text4);
		}

		private static void Describe(StringBuilder sb, Renderer r, Camera cam)
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			Material sharedMaterial = r.sharedMaterial;
			bool flag = (Object)(object)cam != (Object)null && (cam.cullingMask & (1 << ((Component)r).gameObject.layer)) != 0;
			string text = $"  renderer '{((Object)r).name}' {((object)r).GetType().Name} enabled {r.enabled} visible {r.isVisible} layer {((Component)r).gameObject.layer}({LayerMask.LayerToName(((Component)r).gameObject.layer)}) ";
			object arg = flag;
			Bounds bounds = r.bounds;
			object arg2 = ((Bounds)(ref bounds)).center;
			bounds = r.bounds;
			sb.AppendLine(text + $"cameraSeesLayer {arg} bounds {arg2:F2} size {((Bounds)(ref bounds)).size:F3} " + string.Format("shader '{0}' color {1} queue {2}", ((Object)(object)sharedMaterial != (Object)null && (Object)(object)sharedMaterial.shader != (Object)null) ? ((Object)sharedMaterial.shader).name : "none", ((Object)(object)sharedMaterial != (Object)null && sharedMaterial.HasProperty("_Color")) ? ((object)sharedMaterial.color/*cast due to .constrained prefix*/).ToString() : "-", ((Object)(object)sharedMaterial != (Object)null) ? sharedMaterial.renderQueue : 0));
		}
	}
	internal static class DraugrAssets
	{
		public static string PrefabName = "Draugr";

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

		public static GameObject Prefab
		{
			get
			{
				if ((Object)(object)ZNetScene.instance == (Object)null)
				{
					return null;
				}
				GameObject prefab = ZNetScene.instance.GetPrefab(PrefabName);
				if ((Object)(object)prefab == (Object)null)
				{
					WarnOnce("prefab", "Prefab '" + PrefabName + "' not found; draugr effects disabled.");
				}
				return prefab;
			}
		}

		public static EffectList IdleSound
		{
			get
			{
				GameObject prefab = Prefab;
				if ((Object)(object)prefab == (Object)null)
				{
					return null;
				}
				BaseAI component = prefab.GetComponent<BaseAI>();
				if ((Object)(object)component == (Object)null || component.m_idleSound == null || component.m_idleSound.m_effectPrefabs.Length == 0)
				{
					WarnOnce("idle", "'" + PrefabName + "' has no idle sound; groans disabled.");
					return null;
				}
				return component.m_idleSound;
			}
		}

		public static GameObject Visual
		{
			get
			{
				GameObject prefab = Prefab;
				Transform val = (((Object)(object)prefab != (Object)null) ? prefab.transform.Find("Visual") : null);
				GameObject val2 = (((Object)(object)val != (Object)null) ? ((Component)val).gameObject : null);
				if ((Object)(object)prefab != (Object)null && (Object)(object)val2 == (Object)null)
				{
					WarnOnce("visual", "'" + PrefabName + "' has no visual; draugr form disabled.");
				}
				return val2;
			}
		}

		public static void InfoOnce(string key, string message)
		{
			if (Warned.Add("info:" + key))
			{
				Plugin.Log.LogInfo((object)message);
			}
		}

		public static void WarnOnce(string key, string message)
		{
			if (Warned.Add(key))
			{
				Plugin.Log.LogWarning((object)message);
			}
		}
	}
	internal class FindFxCommand : CheatCommand
	{
		public override string Name => "offliner_findfx";

		public override string Help => "offliner_findfx <text> - list particle effect prefabs by name";

		protected override void RunCheat(string[] args)
		{
			string text = ((args.Length != 0) ? args[0].ToLowerInvariant() : "mist");
			foreach (string item in from n in (from go in MistEffect.ParticlePrefabs()
					select ((Object)go).name into n
					where n.ToLowerInvariant().Contains(text)
					select n).Distinct()
				orderby n
				select n)
			{
				Console.instance.Print(item);
			}
		}
	}
	internal static class LevelSync
	{
		public const string ZdoKey = "Offliner_Level";

		public static float Read(ZNetView nview)
		{
			if ((Object)(object)nview == (Object)null || !nview.IsValid())
			{
				return 0f;
			}
			return nview.GetZDO().GetFloat("Offliner_Level", 0f);
		}

		public static void Write(ZNetView nview, float level)
		{
			if (!((Object)(object)nview == (Object)null) && nview.IsValid() && nview.IsOwner())
			{
				ZDO zDO = nview.GetZDO();
				if (Mathf.Abs(zDO.GetFloat("Offliner_Level", 0f) - level) > 0.01f)
				{
					zDO.Set("Offliner_Level", level);
				}
			}
		}
	}
	[DefaultExecutionOrder(-10)]
	internal class OfflinerAvatar : MonoBehaviour
	{
		public Player Player { get; private set; }

		public ZNetView NView { get; private set; }

		public float Level { get; private set; }

		public Stage Stage { get; private set; }

		public bool IsValid
		{
			get
			{
				if ((Object)(object)NView != (Object)null)
				{
					return NView.IsValid();
				}
				return false;
			}
		}

		private void Awake()
		{
			Player = ((Component)this).GetComponent<Player>();
			NView = ((Component)this).GetComponent<ZNetView>();
		}

		private void LateUpdate()
		{
			if (!IsValid)
			{
				Level = 0f;
				Stage = default(Stage);
				return;
			}
			if ((Object)(object)Player == (Object)(object)Player.m_localPlayer)
			{
				LevelSync.Write(NView, OffliningSkill.EffectiveLevel(Player));
			}
			Level = LevelSync.Read(NView);
			Stage = Progression.For(Level);
		}
	}
	internal class OffliningCommand : CheatCommand
	{
		public override string Name => "offlining";

		public override string Help => "offlining <0-100> - set your Offlining level (testing)";

		protected override void RunCheat(string[] args)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || args.Length != 1 || !float.TryParse(args[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
			{
				Console.instance.Print(((ConsoleCommand)this).Help);
				return;
			}
			result = Mathf.Clamp(result, 0f, 100f);
			Skills skills = ((Character)localPlayer).GetSkills();
			if (OffliningSkill.Find(localPlayer) == null)
			{
				skills.RaiseSkill(OffliningSkill.Type, 0f);
			}
			Skill obj = OffliningSkill.Find(localPlayer);
			obj.m_level = result;
			obj.m_accumulator = 0f;
			Console.instance.Print($"Offlining set to {result}");
		}
	}
	internal static class OffliningSkill
	{
		public const string Identifier = "wannie.offliner.offlining";

		public static SkillType Type { get; private set; }

		public static void Register(string pluginDir)
		{
			//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_0015: 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_002b: 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_0047: Expected O, but got Unknown
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			Type = SkillManager.Instance.AddSkill(new SkillConfig
			{
				Identifier = "wannie.offliner.offlining",
				Name = "Offlining",
				Description = "Time spent alone on the server. Nobody knows what it's doing to you.",
				IncreaseStep = 15f,
				Icon = LoadIcon(pluginDir)
			});
		}

		private static Sprite LoadIcon(string pluginDir)
		{
			string text = IconPath.Find(pluginDir);
			if (text == null)
			{
				Plugin.Log.LogWarning((object)"Offlining icon 'offlining_icon.png' not found next to the mod; the skill has no icon.");
				return null;
			}
			return AssetUtils.LoadSpriteFromFile(text);
		}

		public static Skill Find(Player player)
		{
			//IL_0021: 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)
			foreach (Skill skill in ((Character)player).GetSkills().GetSkillList())
			{
				if (skill.m_info.m_skill == Type)
				{
					return skill;
				}
			}
			return null;
		}

		public static float EffectiveLevel(Player player)
		{
			Skill val = Find(player);
			if (val != null)
			{
				return XpTuning.EffectiveLevel(val.m_level, val.m_accumulator);
			}
			return 0f;
		}
	}
	[BepInPlugin("wannie.offliner", "Offliner", "1.0.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	internal class Plugin : BaseUnityPlugin
	{
		public const string Guid = "wannie.offliner";

		public const string Version = "1.0.2";

		internal static ManualLogSource Log;

		private void Awake()
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			OffliningSkill.Register(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location));
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new OffliningCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new FindFxCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new TuneCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new DebugCommand());
			((Component)this).gameObject.AddComponent<SoloXpTicker>();
			new Harmony("wannie.offliner").PatchAll();
		}
	}
	internal static class Priv
	{
		public static readonly int SkinColorId = (int)AccessTools.Field(typeof(VisEquipment), "s_skinColorID").GetValue(null);

		public static readonly FieldRef<Character, Transform> Head = AccessTools.FieldRefAccess<Character, Transform>("m_head");

		public static readonly FieldRef<Character, GameObject> Visual = AccessTools.FieldRefAccess<Character, GameObject>("m_visual");

		public static readonly FieldRef<Character, Animator> CharAnimator = AccessTools.FieldRefAccess<Character, Animator>("m_animator");

		public static readonly FieldRef<VisEquipment, GameObject> RightItemInstance = AccessTools.FieldRefAccess<VisEquipment, GameObject>("m_rightItemInstance");

		public static readonly FieldRef<VisEquipment, GameObject> LeftItemInstance = AccessTools.FieldRefAccess<VisEquipment, GameObject>("m_leftItemInstance");

		public static readonly FieldRef<VisEquipment, GameObject> RightBackItemInstance = AccessTools.FieldRefAccess<VisEquipment, GameObject>("m_rightBackItemInstance");

		public static readonly FieldRef<VisEquipment, GameObject> LeftBackItemInstance = AccessTools.FieldRefAccess<VisEquipment, GameObject>("m_leftBackItemInstance");

		public static readonly FieldRef<Humanoid, VisEquipment> VisEquip = AccessTools.FieldRefAccess<Humanoid, VisEquipment>("m_visEquipment");
	}
	internal static class SoloCheck
	{
		public static bool IsAloneOnServer()
		{
			ZNet instance = ZNet.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			return SoloRules.CountsAsAlone(instance.IsServer(), instance.GetPlayerList().Count);
		}
	}
	internal class SoloXpTicker : MonoBehaviour
	{
		private float _elapsed;

		private void Update()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || !SoloCheck.IsAloneOnServer())
			{
				_elapsed = 0f;
				return;
			}
			_elapsed += Time.deltaTime;
			if (!(_elapsed < 60f))
			{
				_elapsed -= 60f;
				((Character)localPlayer).GetSkills().RaiseSkill(OffliningSkill.Type, 1f);
			}
		}
	}
	internal class TuneCommand : CheatCommand
	{
		public override string Name => "offliner_tune";

		public override string Help => "offliner_tune [skin r g b | glow r g b | glowlight range intensity up]";

		protected override void RunCheat(string[] args)
		{
			//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_00d4: 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)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: 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_0130: 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_005f: 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)
			float[] values2;
			float[] values3;
			if (args.Length == 4 && args[0] == "skin" && TryFloats(args, out var values))
			{
				SkinTintPatch.DraugrSkin = new Color(values[0], values[1], values[2]);
			}
			else if (args.Length == 4 && args[0] == "glow" && TryFloats(args, out values2))
			{
				HeadGlow.Color = new Color(values2[0], values2[1], values2[2]);
				HeadGlow.Version++;
			}
			else if (args.Length == 4 && args[0] == "glowlight" && TryFloats(args, out values3))
			{
				HeadGlow.Range = values3[0];
				HeadGlow.Intensity = values3[1];
				HeadGlow.UpOffset = values3[2];
				HeadGlow.Version++;
			}
			else if (args.Length != 0)
			{
				Console.instance.Print(((ConsoleCommand)this).Help);
				return;
			}
			Color draugrSkin = SkinTintPatch.DraugrSkin;
			Color color = HeadGlow.Color;
			Console.instance.Print(string.Format(CultureInfo.InvariantCulture, "skin {0:F2} {1:F2} {2:F2} | glow {3:F2} {4:F2} {5:F2} | glowlight {6:F2} {7:F2} {8:F2}", draugrSkin.r, draugrSkin.g, draugrSkin.b, color.r, color.g, color.b, HeadGlow.Range, HeadGlow.Intensity, HeadGlow.UpOffset));
		}

		private static bool TryFloats(string[] args, out float[] values)
		{
			values = new float[args.Length - 1];
			for (int i = 1; i < args.Length; i++)
			{
				if (!float.TryParse(args[i], NumberStyles.Float, CultureInfo.InvariantCulture, out values[i - 1]))
				{
					return false;
				}
			}
			return true;
		}
	}
	internal static class VisualClone
	{
		public static GameObject Create(GameObject source, Transform parent)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//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)
			GameObject val = new GameObject("Offliner_CloneHolder");
			val.SetActive(false);
			GameObject val2 = Object.Instantiate<GameObject>(source, val.transform, false);
			for (int i = 0; i < 3; i++)
			{
				MonoBehaviour[] componentsInChildren = val2.GetComponentsInChildren<MonoBehaviour>(true);
				for (int j = 0; j < componentsInChildren.Length; j++)
				{
					Object.DestroyImmediate((Object)(object)componentsInChildren[j]);
				}
				Collider[] componentsInChildren2 = val2.GetComponentsInChildren<Collider>(true);
				for (int j = 0; j < componentsInChildren2.Length; j++)
				{
					Object.DestroyImmediate((Object)(object)componentsInChildren2[j]);
				}
				Rigidbody[] componentsInChildren3 = val2.GetComponentsInChildren<Rigidbody>(true);
				for (int j = 0; j < componentsInChildren3.Length; j++)
				{
					Object.DestroyImmediate((Object)(object)componentsInChildren3[j]);
				}
			}
			val2.transform.SetParent(parent, false);
			val2.transform.localPosition = Vector3.zero;
			val2.transform.localRotation = Quaternion.identity;
			Object.Destroy((Object)(object)val);
			val2.SetActive(true);
			return val2;
		}
	}
}
namespace Offliner.Core
{
	public static class BoneMap
	{
		private static readonly Dictionary<string, string> Aliases = new Dictionary<string, string>
		{
			{ "Spine0", "Spine" },
			{ "LeftHip", "Hips" },
			{ "RightHip", "Hips" }
		};

		public static string Resolve(IEnumerable<string> chainToRoot, ISet<string> playerBones)
		{
			foreach (string item in chainToRoot)
			{
				if (playerBones.Contains(item))
				{
					return item;
				}
				if (Aliases.TryGetValue(item, out var value) && playerBones.Contains(value))
				{
					return value;
				}
			}
			return null;
		}
	}
	public static class IconPath
	{
		public const string FileName = "offlining_icon.png";

		public static string Find(string pluginDir)
		{
			string text = Path.Combine(pluginDir, "offlining_icon.png");
			if (File.Exists(text))
			{
				return text;
			}
			string text2 = Path.Combine(pluginDir, "Assets", "offlining_icon.png");
			if (!File.Exists(text2))
			{
				return null;
			}
			return text2;
		}
	}
	public enum GroanRate
	{
		None,
		Occasional,
		Frequent
	}
	public readonly struct Stage
	{
		public float Tint { get; }

		public GroanRate Groans { get; }

		public bool Eyes { get; }

		public bool Mist { get; }

		public bool Draugr { get; }

		public Stage(float tint, GroanRate groans, bool eyes, bool mist, bool draugr)
		{
			Tint = tint;
			Groans = groans;
			Eyes = eyes;
			Mist = mist;
			Draugr = draugr;
		}
	}
	public static class Progression
	{
		public const float EffectsStart = 30f;

		public const float FrequentGroansAt = 45f;

		public const float EyesAt = 65f;

		public const float MistAt = 75f;

		public const float DraugrAt = 100f;

		public static Stage For(float level)
		{
			if (float.IsNaN(level) || level < 30f)
			{
				return default(Stage);
			}
			return new Stage(TintFor(level), (!(level >= 45f)) ? GroanRate.Occasional : GroanRate.Frequent, level >= 65f, level >= 75f, level >= 100f);
		}

		public static float TintFor(float level)
		{
			if (float.IsNaN(level) || level <= 30f)
			{
				return 0f;
			}
			float num = (level - 30f) / 70f;
			if (!(num > 1f))
			{
				return num;
			}
			return 1f;
		}

		public static float NextGroanDelaySeconds(GroanRate rate, float random01)
		{
			return rate switch
			{
				GroanRate.Occasional => 300f + 300f * random01, 
				GroanRate.Frequent => 60f + 120f * random01, 
				_ => float.PositiveInfinity, 
			};
		}
	}
	public static class SoloRules
	{
		public static bool CountsAsAlone(bool isServer, int playersOnServer)
		{
			if (!isServer)
			{
				return playersOnServer == 1;
			}
			return false;
		}
	}
	public static class XpTuning
	{
		public const float XpPerTick = 15f;

		public const float TickSeconds = 60f;

		public const float MaxLevel = 100f;

		public const float FinalLevelMinutes = 420f;

		public static float NextLevelRequirement(float level)
		{
			float num = (float)Math.Floor(level + 1f);
			if (num >= 100f)
			{
				return 6300f;
			}
			return (float)Math.Pow(num, 1.5) * 0.5f + 0.5f;
		}

		public static int TicksToReach(float targetLevel)
		{
			float num = 0f;
			float num2 = 0f;
			int num3 = 0;
			while (num < targetLevel && num < 100f)
			{
				num2 += 15f;
				num3++;
				if (num2 >= NextLevelRequirement(num))
				{
					num = Math.Min(num + 1f, 100f);
					num2 = 0f;
				}
			}
			return num3;
		}

		public static float EffectiveLevel(float level, float accumulator)
		{
			if (level >= 100f)
			{
				return 100f;
			}
			float num = accumulator / NextLevelRequirement(level);
			if (num < 0f)
			{
				num = 0f;
			}
			if (num > 1f)
			{
				num = 1f;
			}
			return level + num;
		}
	}
}
namespace Offliner.Patches
{
	[HarmonyPatch(typeof(Skill), "GetNextLevelRequirement")]
	internal static class FinalLevelPatch
	{
		private static void Postfix(Skill __instance, ref float __result)
		{
			//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)
			if (__instance.m_info != null && __instance.m_info.m_skill == OffliningSkill.Type)
			{
				__result = XpTuning.NextLevelRequirement(__instance.m_level);
			}
		}
	}
	[HarmonyPatch(typeof(Player), "Awake")]
	internal static class PlayerAwakePatch
	{
		private static void Postfix(Player __instance)
		{
			((Component)__instance).gameObject.AddComponent<OfflinerAvatar>();
			((Component)__instance).gameObject.AddComponent<GroanEffect>();
			((Component)__instance).gameObject.AddComponent<MistEffect>();
			((Component)__instance).gameObject.AddComponent<HeadGlow>();
			((Component)__instance).gameObject.AddComponent<DraugrForm>();
		}
	}
	[HarmonyPatch(typeof(VisEquipment), "UpdateColors")]
	internal static class SkinTintPatch
	{
		public static Color DraugrSkin = new Color(0.55f, 0.95f, 1.2f);

		private static void Postfix(VisEquipment __instance)
		{
			//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_0065: Unknown result type (might be due to invalid IL or missing references)
			if (!__instance.m_isPlayer || (Object)(object)__instance.m_bodyModel == (Object)null)
			{
				return;
			}
			OfflinerAvatar componentInParent = ((Component)__instance).GetComponentInParent<OfflinerAvatar>();
			if (!((Object)(object)componentInParent == (Object)null))
			{
				float tint = componentInParent.Stage.Tint;
				if (!(tint <= 0f))
				{
					Material val = ((Renderer)__instance.m_bodyModel).materials[0];
					val.SetColor(Priv.SkinColorId, Color.Lerp(val.GetColor(Priv.SkinColorId), DraugrSkin, tint));
				}
			}
		}
	}
}
namespace Offliner.Effects
{
	internal class DraugrForm : MonoBehaviour
	{
		private OfflinerAvatar _avatar;

		private GameObject _skin;

		private Animator _playerAnimator;

		private AnimatorCullingMode _playerCulling;

		private readonly List<Renderer> _hidden = new List<Renderer>();

		private void Awake()
		{
			_avatar = ((Component)this).GetComponent<OfflinerAvatar>();
		}

		private void LateUpdate()
		{
			bool flag = _avatar.IsValid && _avatar.Stage.Draugr && !((Character)_avatar.Player).IsDead();
			if (flag && (Object)(object)_skin == (Object)null)
			{
				Create();
			}
			else if (!flag && (Object)(object)_skin != (Object)null)
			{
				Remove();
			}
			if ((Object)(object)_skin != (Object)null)
			{
				HidePlayerRenderers();
			}
		}

		private void Create()
		{
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Expected O, but got Unknown
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			GameObject visual = DraugrAssets.Visual;
			VisEquipment val = Priv.VisEquip.Invoke((Humanoid)(object)_avatar.Player);
			if ((Object)(object)visual == (Object)null || (Object)(object)val == (Object)null || (Object)(object)val.m_bodyModel == (Object)null || (Object)(object)val.m_bodyModel.rootBone == (Object)null)
			{
				return;
			}
			SkinnedMeshRenderer bodyModel = val.m_bodyModel;
			Transform rootBone = bodyModel.rootBone;
			Dictionary<string, Transform> dictionary = new Dictionary<string, Transform>();
			Transform[] componentsInChildren = ((Component)rootBone).GetComponentsInChildren<Transform>(true);
			foreach (Transform val2 in componentsInChildren)
			{
				if (!dictionary.ContainsKey(((Object)val2).name))
				{
					dictionary[((Object)val2).name] = val2;
				}
			}
			HashSet<string> playerBones = new HashSet<string>(dictionary.Keys);
			_skin = new GameObject("Offliner_Draugr");
			_skin.layer = ((Component)bodyModel).gameObject.layer;
			_skin.transform.SetParent(((Component)bodyModel).transform.parent, false);
			_skin.transform.localPosition = ((Component)bodyModel).transform.localPosition;
			_skin.transform.localRotation = ((Component)bodyModel).transform.localRotation;
			_skin.transform.localScale = ((Component)bodyModel).transform.localScale;
			int num = 0;
			SkinnedMeshRenderer[] componentsInChildren2 = visual.GetComponentsInChildren<SkinnedMeshRenderer>(true);
			foreach (SkinnedMeshRenderer val3 in componentsInChildren2)
			{
				GameObject val4 = new GameObject(((Object)val3).name)
				{
					layer = _skin.layer
				};
				val4.transform.SetParent(_skin.transform, false);
				SkinnedMeshRenderer val5 = val4.AddComponent<SkinnedMeshRenderer>();
				val5.sharedMesh = val3.sharedMesh;
				((Renderer)val5).sharedMaterials = ((Renderer)val3).sharedMaterials;
				val5.rootBone = rootBone;
				val5.updateWhenOffscreen = true;
				Transform[] array = (Transform[])(object)new Transform[val3.bones.Length];
				for (int j = 0; j < array.Length; j++)
				{
					string text = BoneMap.Resolve(ChainToRoot(val3.bones[j]), playerBones);
					if (text == null)
					{
						num++;
					}
					array[j] = ((text != null) ? dictionary[text] : rootBone);
				}
				val5.bones = array;
			}
			if (num > 0)
			{
				DraugrAssets.WarnOnce("bones", $"{num} draugr bone(s) had no player match; they follow the hips.");
			}
			_playerAnimator = Priv.CharAnimator.Invoke((Character)(object)_avatar.Player);
			if ((Object)(object)_playerAnimator != (Object)null)
			{
				_playerCulling = _playerAnimator.cullingMode;
				_playerAnimator.cullingMode = (AnimatorCullingMode)0;
			}
		}

		private static bool IsAura(Transform t)
		{
			while ((Object)(object)t != (Object)null)
			{
				if (((Object)t).name.StartsWith("Offliner_Aura_"))
				{
					return true;
				}
				t = t.parent;
			}
			return false;
		}

		private static IEnumerable<string> ChainToRoot(Transform bone)
		{
			Transform t = bone;
			while ((Object)(object)t != (Object)null)
			{
				yield return ((Object)t).name;
				t = t.parent;
			}
		}

		private void Remove()
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			foreach (Renderer item in _hidden)
			{
				if ((Object)(object)item != (Object)null)
				{
					item.enabled = true;
				}
			}
			_hidden.Clear();
			if ((Object)(object)_playerAnimator != (Object)null)
			{
				_playerAnimator.cullingMode = _playerCulling;
			}
			_playerAnimator = null;
			Object.Destroy((Object)(object)_skin);
			_skin = null;
		}

		private void HidePlayerRenderers()
		{
			GameObject val = Priv.Visual.Invoke((Character)(object)_avatar.Player);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			VisEquipment val2 = Priv.VisEquip.Invoke((Humanoid)(object)_avatar.Player);
			GameObject[] source = (GameObject[])(((Object)(object)val2 == (Object)null) ? ((Array)new GameObject[0]) : ((Array)((IEnumerable<GameObject>)(object)new GameObject[4]
			{
				Priv.RightItemInstance.Invoke(val2),
				Priv.LeftItemInstance.Invoke(val2),
				Priv.RightBackItemInstance.Invoke(val2),
				Priv.LeftBackItemInstance.Invoke(val2)
			}).Where((GameObject go) => (Object)(object)go != (Object)null).ToArray()));
			Renderer[] componentsInChildren = val.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer r in componentsInChildren)
			{
				if (r.enabled && !((Component)r).transform.IsChildOf(_skin.transform) && !IsAura(((Component)r).transform) && !source.Any((GameObject item) => ((Component)r).transform.IsChildOf(item.transform)))
				{
					r.enabled = false;
					_hidden.Add(r);
				}
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)_skin != (Object)null)
			{
				Object.Destroy((Object)(object)_skin);
			}
		}
	}
	internal class GroanEffect : MonoBehaviour
	{
		public const string RpcName = "Offliner_Groan";

		private OfflinerAvatar _avatar;

		private GroanRate _rate;

		private float _timer;

		private void Awake()
		{
			_avatar = ((Component)this).GetComponent<OfflinerAvatar>();
			ZNetView component = ((Component)this).GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null)
			{
				component.Register("Offliner_Groan", (Action<long>)RPC_Groan);
			}
		}

		private void Update()
		{
			if (!_avatar.IsValid || !_avatar.NView.IsOwner())
			{
				return;
			}
			GroanRate groans = _avatar.Stage.Groans;
			if (groans != _rate)
			{
				_rate = groans;
				_timer = Progression.NextGroanDelaySeconds(groans, Random.value);
			}
			if (groans != GroanRate.None)
			{
				_timer -= Time.deltaTime;
				if (!(_timer > 0f))
				{
					_timer = Progression.NextGroanDelaySeconds(groans, Random.value);
					_avatar.NView.InvokeRPC(ZNetView.Everybody, "Offliner_Groan", Array.Empty<object>());
				}
			}
		}

		private void RPC_Groan(long sender)
		{
			//IL_0011: 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_002f: 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)
			EffectList idleSound = DraugrAssets.IdleSound;
			if (idleSound != null)
			{
				idleSound.Create(((Component)this).transform.position, ((Component)this).transform.rotation, ((Component)this).transform, 1f, -1, default(ZDOID));
			}
		}
	}
	internal class HeadGlow : MonoBehaviour
	{
		public static Color Color = new Color(0.45f, 1f, 0.35f);

		public static float Range = 0.6f;

		public static float Intensity = 3f;

		public static float UpOffset = 0.1f;

		public static int Version;

		private OfflinerAvatar _avatar;

		private GameObject _glow;

		private int _builtVersion;

		private void Awake()
		{
			_avatar = ((Component)this).GetComponent<OfflinerAvatar>();
		}

		private void LateUpdate()
		{
			bool flag = _avatar.IsValid && _avatar.Stage.Eyes && !_avatar.Stage.Draugr;
			if ((Object)(object)_glow != (Object)null && (!flag || _builtVersion != Version))
			{
				Object.Destroy((Object)(object)_glow);
				_glow = null;
			}
			if (flag && (Object)(object)_glow == (Object)null)
			{
				_glow = Build();
				_builtVersion = Version;
			}
		}

		private GameObject Build()
		{
			//IL_0036: 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_0048: 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_0064: 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_007d: 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_00b2: Expected O, but got Unknown
			Transform val = Priv.Head.Invoke((Character)(object)_avatar.Player);
			if ((Object)(object)val == (Object)null)
			{
				DraugrAssets.WarnOnce("glow", "Player head bone not found; head glow disabled.");
				return null;
			}
			GameObject val2 = new GameObject("Offliner_HeadGlow");
			val2.transform.SetParent(val, false);
			val2.transform.position = val.position + ((Component)_avatar.Player).transform.up * UpOffset;
			Light obj = val2.AddComponent<Light>();
			obj.type = (LightType)2;
			obj.color = Color;
			obj.range = Range;
			obj.intensity = Intensity;
			obj.renderMode = (LightRenderMode)1;
			return val2;
		}

		private void OnDestroy()
		{
			if ((Object)(object)_glow != (Object)null)
			{
				Object.Destroy((Object)(object)_glow);
			}
		}
	}
	internal class MistEffect : MonoBehaviour
	{
		public const string AuraPrefix = "Offliner_Aura_";

		private OfflinerAvatar _avatar;

		private readonly List<GameObject> _aura = new List<GameObject>();

		private SkinnedMeshRenderer _emitter;

		private bool _built;

		public static IEnumerable<GameObject> ParticlePrefabs()
		{
			return (from ps in Resources.FindObjectsOfTypeAll<ParticleSystem>()
				select ((Component)((Component)ps).transform.root).gameObject).Where(delegate(GameObject go)
			{
				//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)
				Scene scene = go.scene;
				return !((Scene)(ref scene)).IsValid();
			}).Distinct();
		}

		private void Awake()
		{
			_avatar = ((Component)this).GetComponent<OfflinerAvatar>();
		}

		private void LateUpdate()
		{
			if (!_avatar.IsValid || !_avatar.Stage.Mist || ((Character)_avatar.Player).IsDead())
			{
				if (_built)
				{
					Clear();
				}
				return;
			}
			SkinnedMeshRenderer val = ShownBody();
			if (!((Object)(object)val == (Object)null) && (!_built || (Object)(object)val != (Object)(object)_emitter))
			{
				Clear();
				Build(val);
			}
		}

		private SkinnedMeshRenderer ShownBody()
		{
			VisEquipment val = Priv.VisEquip.Invoke((Humanoid)(object)_avatar.Player);
			if ((Object)(object)val == (Object)null || (Object)(object)val.m_bodyModel == (Object)null)
			{
				return null;
			}
			Transform val2 = (((Object)(object)((Component)val.m_bodyModel).transform.parent != (Object)null) ? ((Component)val.m_bodyModel).transform.parent.Find("Offliner_Draugr") : null);
			SkinnedMeshRenderer val3 = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponentInChildren<SkinnedMeshRenderer>(true) : null);
			if (!((Object)(object)val3 != (Object)null))
			{
				return val.m_bodyModel;
			}
			return val3;
		}

		private void Build(SkinnedMeshRenderer body)
		{
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: 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_01ae: 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_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			_built = true;
			_emitter = body;
			GameObject prefab = DraugrAssets.Prefab;
			GameObject visual = DraugrAssets.Visual;
			VisEquipment val = Priv.VisEquip.Invoke((Humanoid)(object)_avatar.Player);
			GameObject val2 = Priv.Visual.Invoke((Character)(object)_avatar.Player);
			if ((Object)(object)prefab == (Object)null || (Object)(object)visual == (Object)null || (Object)(object)val == (Object)null || (Object)(object)val.m_bodyModel.rootBone == (Object)null || (Object)(object)val2 == (Object)null)
			{
				return;
			}
			Dictionary<string, Transform> dictionary = new Dictionary<string, Transform>();
			Transform[] componentsInChildren = ((Component)val.m_bodyModel.rootBone).GetComponentsInChildren<Transform>(true);
			foreach (Transform val3 in componentsInChildren)
			{
				if (!dictionary.ContainsKey(((Object)val3).name))
				{
					dictionary[((Object)val3).name] = val3;
				}
			}
			HashSet<string> playerBones = new HashSet<string>(dictionary.Keys);
			List<string> list = new List<string>();
			ParticleSystem[] componentsInChildren2 = prefab.GetComponentsInChildren<ParticleSystem>(true);
			foreach (ParticleSystem val4 in componentsInChildren2)
			{
				Transform parent = ((Component)val4).transform.parent;
				if ((Object)(object)parent != (Object)null && (Object)(object)((Component)parent).GetComponentInParent<ParticleSystem>(true) != (Object)null)
				{
					continue;
				}
				string text = (((Object)(object)parent != (Object)null) ? BoneMap.Resolve(ChainToRoot(parent), playerBones) : null);
				GameObject val5 = VisualClone.Create(((Component)val4).gameObject, (text != null) ? dictionary[text] : val2.transform);
				((Object)val5).name = "Offliner_Aura_" + ((Object)val4).name;
				if (text != null)
				{
					val5.transform.localPosition = ((Component)val4).transform.localPosition;
					val5.transform.localRotation = ((Component)val4).transform.localRotation;
					val5.transform.localScale = ((Component)val4).transform.localScale;
				}
				else
				{
					val5.transform.localPosition = visual.transform.InverseTransformPoint(((Component)val4).transform.position);
					val5.transform.localRotation = Quaternion.Inverse(visual.transform.rotation) * ((Component)val4).transform.rotation;
				}
				ParticleSystem[] componentsInChildren3 = val5.GetComponentsInChildren<ParticleSystem>(true);
				foreach (ParticleSystem obj in componentsInChildren3)
				{
					ShapeModule shape = obj.shape;
					if (((ShapeModule)(ref shape)).enabled && (Object)(object)((ShapeModule)(ref shape)).skinnedMeshRenderer != (Object)null)
					{
						((ShapeModule)(ref shape)).skinnedMeshRenderer = body;
					}
					obj.Play(true);
				}
				_aura.Add(val5);
				list.Add(((Object)val4).name + " on " + (text ?? "body"));
			}
			DraugrAssets.InfoOnce("aura", (list.Count == 0) ? ("'" + DraugrAssets.PrefabName + "' has no particle effects; no aura.") : string.Format("Draugr aura: {0} effect(s): {1}.", list.Count, string.Join(", ", list)));
		}

		private static IEnumerable<string> ChainToRoot(Transform bone)
		{
			Transform t = bone;
			while ((Object)(object)t != (Object)null)
			{
				yield return ((Object)t).name;
				t = t.parent;
			}
		}

		private void Clear()
		{
			foreach (GameObject item in _aura)
			{
				if ((Object)(object)item != (Object)null)
				{
					Object.Destroy((Object)(object)item);
				}
			}
			_aura.Clear();
			_emitter = null;
			_built = false;
		}

		private void OnDestroy()
		{
			Clear();
		}
	}
}