Decompiled source of Runic Barrier v1.0.0

plugins/RunicBarrier.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using SideLoader;
using UnityEngine;
using UnityEngine.Events;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("RunicBarrier")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("RunicBarrier")]
[assembly: AssemblyTitle("RunicBarrier")]
[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 RunicBarrier
{
	[BepInPlugin("com.wrango.runicbarrier", "Runic Barrier", "1.0.0")]
	public class RunicBarrierPlugin : BaseUnityPlugin
	{
		internal enum Tier
		{
			None,
			Normal,
			Amplified
		}

		public const string GUID = "com.wrango.runicbarrier";

		public const string NAME = "Runic Barrier";

		public const string VERSION = "1.0.0";

		internal static ManualLogSource Log;

		internal static RunicBarrierPlugin Instance;

		private string _mitigationSig;

		private static readonly bool DIAG = false;

		private const bool APPLY_MANA_REDUCTION = true;

		private const string IMPACT_SOUNDS = "CS_GolemShielded_ShieldImpact_01,CS_GolemShielded_ShieldImpact_02,CS_GolemShielded_ShieldImpact_03,CS_GolemShielded_ShieldImpact_04";

		private const float PITCH_MIN = 1f;

		private const float PITCH_MAX = 1f;

		private const float VOLUME_MIN = 1f;

		private const float VOLUME_MAX = 1f;

		private const ProjectilePrefabs SPARK_PROJECTILE = (ProjectilePrefabs)0;

		private const float SPARK_LIFESPAN = 0f;

		private const float SPARK_FORCE = 0f;

		private const float SPARK_SCALE = 1f;

		private const string SPARK_HIDE_EMITTERS = "ProjectileFX";

		private const BlastPrefabs SPARK_BLAST = (BlastPrefabs)63;

		private const float SPARK_BLAST_LIFESPAN = 5f;

		private const float SPARK_BLAST_SCALE = 0.07f;

		private Sounds[] _sounds = (Sounds[])(object)new Sounds[0];

		private int _lastIndex = -1;

		private readonly Dictionary<Sounds, int> _soundTally = new Dictionary<Sounds, int>();

		internal static int AbsorbFrame = -1;

		internal static int AbsorbVictimId;

		internal static float AbsorbTook;

		internal static bool LogHits;

		private static Harmony _harmony;

		private static int _cueFrame = -1;

		private bool _hurtboxLogged;

		private static int _awaitingPointFrame = -1;

		private static int _awaitingPointHit;

		private static string _awaitingPointSrc = "";

		private const float CUE_HOLD_SECONDS = 8f;

		private readonly Dictionary<int, UnityAction<Object, DamageList>> _subs = new Dictionary<int, UnityAction<Object, DamageList>>();

		private Character _localPlayer;

		private float _nextScan;

		private float _manaSpent;

		private float _healthLet;

		private float _negated;

		private int _hits;

		private int _observed;

		private bool _wardWasUp;

		private static FieldInfo _manaField;

		private static bool _manaFieldResolved;

		internal const string STATUS_ID = "RunicBarrier";

		internal const string STATUS_ID_AMPLIFIED = "RunicBarrierAmplified";

		private const float HEALTH_SHARE = 0.6f;

		private const float MANA_SHARE = 0.6f;

		private const float HEALTH_SHARE_AMPLIFIED = 0.5f;

		private const float MANA_SHARE_AMPLIFIED = 0.5f;

		private readonly Dictionary<int, Tier> _allyWard = new Dictionary<int, Tier>();

		private static bool ResolveManaField(CharacterStats stats)
		{
			if (_manaFieldResolved)
			{
				return _manaField != null;
			}
			_manaFieldResolved = true;
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			float currentMana = stats.CurrentMana;
			Type type = ((object)stats).GetType();
			List<string> list = new List<string>();
			FieldInfo[] fields = type.GetFields(bindingAttr);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (fieldInfo.FieldType != typeof(float))
				{
					continue;
				}
				float num;
				try
				{
					num = (float)fieldInfo.GetValue(stats);
				}
				catch (Exception)
				{
					continue;
				}
				float num2 = num - currentMana;
				if (num2 < 0f)
				{
					num2 = 0f - num2;
				}
				if (!(num2 > 0.0001f))
				{
					list.Add(fieldInfo.Name);
					if (fieldInfo.Name == "m_mana")
					{
						_manaField = fieldInfo;
					}
				}
			}
			if (_manaField == null && list.Count == 1)
			{
				_manaField = type.GetField(list[0], bindingAttr);
			}
			if (_manaField != null)
			{
				Log.LogMessage((object)(Stamp() + " [RunicBarrier] mana field = " + _manaField.Name + "  (candidates: " + string.Join(", ", list.ToArray()) + ")"));
			}
			else
			{
				Log.LogError((object)(Stamp() + " [RunicBarrier] COULD NOT RESOLVE the mana backing field. Candidates matching CurrentMana=" + currentMana.ToString("F2") + ": " + string.Join(", ", list.ToArray()) + ". The ward is disabled - it must never take damage it cannot charge for."));
			}
			return _manaField != null;
		}

		private static string Stamp()
		{
			return DateTime.Now.ToString("HH:mm:ss.fff");
		}

		internal void Awake()
		{
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			Log.LogMessage((object)(Stamp() + " [RunicBarrier 1.0.0] loaded, WARD model. split=" + 0.6f.ToString("0.##") + "/" + 0.6f.ToString("0.##") + " amplified=" + 0.5f.ToString("0.##") + "/" + 0.5f.ToString("0.##") + " (fixed) ApplyManaReduction=" + true + " Spark=" + ((object)(ProjectilePrefabs)0/*cast due to .constrained prefix*/).ToString()));
			LogHits = DIAG;
			InstallHitPointHook();
			ParseImpactSounds();
		}

		internal void Update()
		{
			if (Object.op_Implicit((Object)(object)_localPlayer) && _localPlayer.IsLocalPlayer)
			{
				TrackWardSession(_localPlayer);
			}
			if (Time.time < _nextScan)
			{
				return;
			}
			_nextScan = Time.time + 2f;
			VFXTrim.TryOnce();
			if ((Object)(object)CharacterManager.Instance == (Object)null)
			{
				return;
			}
			List<int> list = new List<int>();
			foreach (Character value in CharacterManager.Instance.Characters.Values)
			{
				if (!Object.op_Implicit((Object)(object)value) || value.IsAI)
				{
					continue;
				}
				int instanceID = ((Object)value).GetInstanceID();
				list.Add(instanceID);
				if (value.IsLocalPlayer)
				{
					_localPlayer = value;
				}
				if (value.IsLocalPlayer)
				{
					LogMitigation(value);
				}
				else
				{
					LogAllyWard(value, instanceID);
				}
				if (!_subs.ContainsKey(instanceID))
				{
					Character victim = value;
					UnityAction<Object, DamageList> val = delegate(Object src, DamageList dmg)
					{
						OnHit(victim, src, dmg);
					};
					value.OnHitPreResistance = (UnityAction<Object, DamageList>)(object)Delegate.Combine((Delegate?)(object)value.OnHitPreResistance, (Delegate?)(object)val);
					_subs.Add(instanceID, val);
					Log.LogMessage((object)(Stamp() + " [RunicBarrier] watching " + Describe(value)));
					LogHurtbox(value);
				}
			}
			List<int> list2 = new List<int>();
			foreach (int key in _subs.Keys)
			{
				if (!list.Contains(key))
				{
					list2.Add(key);
				}
			}
			foreach (int item in list2)
			{
				_subs.Remove(item);
			}
		}

		private void ParseImpactSounds()
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				List<Sounds> list = new List<Sounds>();
				List<string> list2 = new List<string>();
				string text = "CS_GolemShielded_ShieldImpact_01,CS_GolemShielded_ShieldImpact_02,CS_GolemShielded_ShieldImpact_03,CS_GolemShielded_ShieldImpact_04";
				if (!string.IsNullOrEmpty(text))
				{
					string[] array = text.Split(new char[1] { ',' });
					for (int i = 0; i < array.Length; i++)
					{
						string text2 = array[i].Trim();
						if (text2.Length == 0)
						{
							continue;
						}
						try
						{
							Sounds val = (Sounds)Enum.Parse(typeof(Sounds), text2, ignoreCase: true);
							if ((int)val != 0)
							{
								list.Add(val);
							}
						}
						catch (Exception)
						{
							list2.Add(text2);
						}
					}
				}
				_sounds = list.ToArray();
				if (list2.Count > 0)
				{
					Log.LogError((object)(Stamp() + " [RunicBarrier] these ImpactSounds are not valid sound names and were skipped: " + string.Join(", ", list2.ToArray()) + ". Copy them exactly from the ListSoundsMatching output."));
				}
				Log.LogMessage((object)(Stamp() + " [RunicBarrier] impact sounds: " + _sounds.Length + ((_sounds.Length == 0) ? " (silent)" : " in rotation")));
			}
			catch (Exception ex2)
			{
				Log.LogError((object)(Stamp() + " [RunicBarrier] could not parse ImpactSounds: " + ex2));
				_sounds = (Sounds[])(object)new Sounds[0];
			}
		}

		private unsafe string PlayImpactSound(Transform at)
		{
			//IL_0070: 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_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (_sounds.Length == 0 || (Object)(object)Global.AudioManager == (Object)null || !Object.op_Implicit((Object)(object)at))
				{
					return null;
				}
				int num;
				if (_sounds.Length > 1 && _lastIndex >= 0)
				{
					num = Random.Range(0, _sounds.Length - 1);
					if (num >= _lastIndex)
					{
						num++;
					}
				}
				else
				{
					num = Random.Range(0, _sounds.Length);
				}
				Sounds val = _sounds[num];
				_lastIndex = num;
				if ((int)val == 0)
				{
					return "(NONE in the list)";
				}
				_soundTally.TryGetValue(val, out var value);
				_soundTally[val] = value + 1;
				Global.AudioManager.PlaySoundAndFollow(val, at, 0f, 1f, 1f, 1f, 1f);
				return ((object)(*(Sounds*)(&val))/*cast due to .constrained prefix*/).ToString();
			}
			catch (Exception ex)
			{
				Log.LogError((object)(Stamp() + " [RunicBarrier] impact sound failed: " + ex));
				return "(threw)";
			}
		}

		internal static Tier TierOf(Character c)
		{
			if (!Object.op_Implicit((Object)(object)c))
			{
				return Tier.None;
			}
			StatusEffectManager statusEffectMngr = c.StatusEffectMngr;
			if ((Object)(object)statusEffectMngr != (Object)null)
			{
				if (statusEffectMngr.HasStatusEffect("RunicBarrierAmplified"))
				{
					return Tier.Amplified;
				}
				if (statusEffectMngr.HasStatusEffect("RunicBarrier"))
				{
					return Tier.Normal;
				}
			}
			return Tier.None;
		}

		private void SharesFor(Tier tier, out float hShare, out float mShare)
		{
			if (tier == Tier.Amplified)
			{
				hShare = 0.5f;
				mShare = 0.5f;
			}
			else
			{
				hShare = 0.6f;
				mShare = 0.6f;
			}
		}

		private void TrackWardSession(Character c)
		{
			try
			{
				if (Object.op_Implicit((Object)(object)c) && c.IsLocalPlayer)
				{
					bool flag = TierOf(c) != Tier.None;
					if (flag && !_wardWasUp)
					{
						Log.LogMessage((object)(Stamp() + " [RunicBarrier] ward session started"));
					}
					else if (!flag && _wardWasUp)
					{
						Log.LogMessage((object)(Stamp() + " [RunicBarrier] ward ended - dismissed, expired or collapsed; this edge does not say which"));
					}
					_wardWasUp = flag;
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)(Stamp() + " [RunicBarrier] ward session tracking threw: " + ex));
			}
		}

		private void LogMitigation(Character c)
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)c == (Object)null || (Object)(object)c.Stats == (Object)null)
				{
					return;
				}
				float[] damageProtection = c.Stats.DamageProtection;
				float[] damageResistance = c.Stats.DamageResistance;
				if (damageProtection == null || damageResistance == null)
				{
					Log.LogMessage((object)(Stamp() + " [RunicBarrier] mitigation: arrays unavailable"));
					return;
				}
				string text = "";
				for (int i = 0; i < damageProtection.Length; i++)
				{
					string text2 = ((i < 9) ? ((object)(Types)i/*cast due to .constrained prefix*/).ToString() : ("?" + i));
					text = text + " " + text2 + "=" + damageProtection[i].ToString("F2") + "/" + (damageResistance[i] * 100f).ToString("F0") + "%";
				}
				float num = c.Stats.GetFinalManaConsumption((Tag[])null, 100f) / 100f;
				float manaRegen = c.Stats.ManaRegen;
				string text3 = text + "|" + c.Stats.GetBarrier().ToString("F2") + "|" + num.ToString("F3") + "|" + manaRegen.ToString("F3");
				if (!(text3 == _mitigationSig))
				{
					bool flag = _mitigationSig != null;
					_mitigationSig = text3;
					Log.LogMessage((object)(Stamp() + " [RunicBarrier] mitigation of " + c.Name + (flag ? " CHANGED" : "") + " | flat/resist by type:" + text + " | Barrier=" + c.Stats.GetBarrier().ToString("F2") + " | manaMod x" + num.ToString("F3") + ((num > 1.001f) ? " (a PENALTY, not a reduction)" : "") + " | manaRegenStat " + manaRegen.ToString("F3") + "/s" + ((manaRegen < -0.001f) ? " (rate negative; food may still carry it positive)" : ((manaRegen < 0.001f) ? " (rate suspended)" : ""))));
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)(Stamp() + " [RunicBarrier] mitigation dump threw: " + ex));
			}
		}

		private float ManaBillBase(Character victim, DamageList dmg, float mShare, out float flatUsed)
		{
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Expected I4, but got Unknown
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected I4, but got Unknown
			flatUsed = 0f;
			if ((Object)(object)victim == (Object)null || (Object)(object)victim.Stats == (Object)null)
			{
				return dmg.TotalDamage * mShare;
			}
			float[] damageProtection = victim.Stats.DamageProtection;
			float[] damageResistance = victim.Stats.DamageResistance;
			if (damageProtection == null || damageResistance == null)
			{
				return dmg.TotalDamage * mShare;
			}
			float barrier = victim.Stats.GetBarrier();
			int num = -1;
			if (barrier > 0f)
			{
				float num2 = 0f;
				float num3 = 0f;
				for (int i = 0; i < dmg.Count; i++)
				{
					DamageType val = dmg[i];
					if ((int)val.Type != 0)
					{
						int num4 = (int)val.Type;
						if (num4 >= 0 && num4 < damageResistance.Length && (num < 0 || damageResistance[num4] < num2 || (damageResistance[num4] == num2 && val.Damage > num3)))
						{
							num = num4;
							num2 = damageResistance[num4];
							num3 = val.Damage;
						}
					}
				}
			}
			float num5 = 0f;
			for (int j = 0; j < dmg.Count; j++)
			{
				DamageType obj = dmg[j];
				int num6 = (int)obj.Type;
				float num7 = ((num6 >= 0 && num6 < damageProtection.Length) ? damageProtection[num6] : 0f);
				if (num6 == num)
				{
					num7 += barrier;
				}
				float num8 = obj.Damage * mShare;
				float num9 = num8 - num7;
				if (num9 < 0f)
				{
					num9 = 0f;
				}
				flatUsed += num8 - num9;
				num5 += num9;
			}
			return num5;
		}

		private void Collapse(Character victim)
		{
			try
			{
				if (Object.op_Implicit((Object)(object)victim) && !((Object)(object)victim.StatusEffectMngr == (Object)null))
				{
					bool flag = false;
					if (victim.StatusEffectMngr.HasStatusEffect("RunicBarrier"))
					{
						victim.StatusEffectMngr.CleanseStatusEffect("RunicBarrier");
						flag = true;
					}
					if (victim.StatusEffectMngr.HasStatusEffect("RunicBarrierAmplified"))
					{
						victim.StatusEffectMngr.CleanseStatusEffect("RunicBarrierAmplified");
						flag = true;
					}
					Log.LogMessage((object)(Stamp() + " [RunicBarrier] WARD COLLAPSED on " + victim.Name + " - out of Mana" + (flag ? ", status removed" : ", no status was present")));
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)(Stamp() + " [RunicBarrier] collapse threw: " + ex));
			}
		}

		internal static bool WardIsUp(Character c)
		{
			return TierOf(c) != Tier.None;
		}

		private void LogAllyWard(Character c, int id)
		{
			try
			{
				if (!((Object)(object)c == (Object)null))
				{
					Tier tier = TierOf(c);
					if (!_allyWard.TryGetValue(id, out var value) || value != tier)
					{
						bool flag = _allyWard.ContainsKey(id);
						_allyWard[id] = tier;
						Log.LogMessage((object)(Stamp() + " [RunicBarrier] ally " + c.Name + ": ward " + ((tier == Tier.None) ? "None" : tier.ToString()) + (flag ? " (changed - as THIS client sees it)" : " (first sighting)")));
					}
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)(Stamp() + " [RunicBarrier] ally ward watch threw: " + ex));
			}
		}

		private void LogObserved(Character victim, Object src, DamageList dmg)
		{
			try
			{
				string text = "";
				for (int i = 0; i < dmg.Count; i++)
				{
					DamageType val = dmg[i];
					if (i > 0)
					{
						text += "/";
					}
					text = text + ((object)Unsafe.As<Types, Types>(ref val.Type)/*cast due to .constrained prefix*/).ToString() + ":" + val.Damage.ToString("F1");
				}
				float before = (Object.op_Implicit((Object)(object)victim.Stats) ? victim.Stats.CurrentHealth : (-1f));
				_observed++;
				int observed = _observed;
				string text2 = Stamp() + " [RunicBarrier] OBSERVED #" + observed + " on " + (victim.Name ?? "?") + " (NOT ours - nothing touched) | src=" + (Object.op_Implicit(src) ? ((object)src).GetType().Name : "null") + " | entries=" + dmg.Count + " [" + text + "] raw=" + dmg.TotalDamage.ToString("F2") + " | health before=" + before.ToString("F2");
				Log.LogMessage((object)text2);
				((MonoBehaviour)this).StartCoroutine(ReportObservedHealth(victim, before, observed));
			}
			catch (Exception ex)
			{
				Log.LogError((object)(Stamp() + " [RunicBarrier] observer threw: " + ex));
			}
		}

		private IEnumerator ReportObservedHealth(Character victim, float before, int n)
		{
			yield return null;
			float afterOne = ((Object.op_Implicit((Object)(object)victim) && Object.op_Implicit((Object)(object)victim.Stats)) ? victim.Stats.CurrentHealth : (-1f));
			yield return (object)new WaitForSeconds(0.25f);
			float num = ((Object.op_Implicit((Object)(object)victim) && Object.op_Implicit((Object)(object)victim.Stats)) ? victim.Stats.CurrentHealth : (-1f));
			Log.LogMessage((object)(Stamp() + " [RunicBarrier] OBSERVED #" + n + " health " + before.ToString("F2") + " -> " + afterOne.ToString("F2") + " (1 frame) -> " + num.ToString("F2") + " (0.25s) | TOOK " + (before - num).ToString("F2") + " as this client sees it"));
		}

		private IEnumerator ReportOwnHealth(Character victim, float before, int hit)
		{
			yield return null;
			yield return (object)new WaitForSeconds(0.25f);
			float num = ((Object.op_Implicit((Object)(object)victim) && Object.op_Implicit((Object)(object)victim.Stats)) ? victim.Stats.CurrentHealth : (-1f));
			Log.LogMessage((object)(Stamp() + " [RunicBarrier] SPLIT #" + hit + " health " + before.ToString("F2") + " -> " + num.ToString("F2") + " (0.25s) | TOOK " + (before - num).ToString("F2") + " as OUR client sees it"));
		}

		private void LogSoundTally()
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			if (_soundTally.Count == 0)
			{
				return;
			}
			int num = 0;
			foreach (KeyValuePair<Sounds, int> item in _soundTally)
			{
				num += item.Value;
			}
			Log.LogMessage((object)(Stamp() + " [RunicBarrier] sound tally over " + num + " plays:"));
			foreach (KeyValuePair<Sounds, int> item2 in _soundTally)
			{
				Log.LogMessage((object)("    " + ((object)item2.Key/*cast due to .constrained prefix*/).ToString() + " x" + item2.Value + "  (" + (100f * (float)item2.Value / (float)num).ToString("F0") + "%)"));
			}
			if (_soundTally.Count < _sounds.Length)
			{
				Log.LogMessage((object)("    NOTE: only " + _soundTally.Count + " of " + _sounds.Length + " configured sounds were ever picked."));
			}
		}

		private void OnHit(Character victim, Object src, DamageList dmg)
		{
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!Object.op_Implicit((Object)(object)victim) || dmg == null)
				{
					return;
				}
				if (!victim.IsLocalPlayer)
				{
					if (DIAG)
					{
						LogObserved(victim, src, dmg);
					}
					return;
				}
				string text = (Object.op_Implicit(src) ? ((object)src).GetType().Name : "null");
				string text2 = "";
				for (int i = 0; i < dmg.Count; i++)
				{
					DamageType val = dmg[i];
					if (i > 0)
					{
						text2 += "/";
					}
					text2 = text2 + ((object)Unsafe.As<Types, Types>(ref val.Type)/*cast due to .constrained prefix*/).ToString() + ":" + val.Damage.ToString("F1");
				}
				string text3 = "entries=" + dmg.Count + " [" + text2 + "] raw=" + dmg.TotalDamage.ToString("F2");
				Tier tier = TierOf(victim);
				if (tier == Tier.None)
				{
					if (DIAG)
					{
						Log.LogMessage((object)(Stamp() + " [RunicBarrier] ward DOWN, hit passes whole src=" + text + " " + text3));
					}
					return;
				}
				float before = (Object.op_Implicit((Object)(object)victim.Stats) ? victim.Stats.CurrentHealth : (-1f));
				float totalDamage = dmg.TotalDamage;
				if (totalDamage <= 0f)
				{
					return;
				}
				SharesFor(tier, out var hShare, out var mShare);
				float num = Mathf.Max(0f, 1f - hShare - mShare);
				if (mShare <= 0f)
				{
					if (DIAG)
					{
						Log.LogMessage((object)(Stamp() + " [RunicBarrier] Mana share is 0, nothing to charge src=" + text + " " + text3));
					}
				}
				else
				{
					if (!ResolveManaField(victim.Stats))
					{
						return;
					}
					LogMitigation(victim);
					float flatUsed;
					float num2 = ManaBillBase(victim, dmg, mShare, out flatUsed);
					float num3 = num2;
					num3 = victim.Stats.GetFinalManaConsumption((Tag[])null, num2);
					float currentMana = victim.Stats.CurrentMana;
					float num4 = 1f;
					bool flag = false;
					if (num3 > currentMana)
					{
						num4 = ((num3 > 0f) ? Mathf.Clamp01(currentMana / num3) : 0f);
						flag = true;
					}
					float num5 = num3 * num4;
					float num6 = mShare * num4;
					float num7 = mShare * (1f - num4);
					float num8 = hShare + num7;
					List<DamageType> list = new List<DamageType>();
					for (int j = 0; j < dmg.Count; j++)
					{
						DamageType val2 = dmg[j];
						val2.Damage *= num8;
						if (val2.Damage <= 0.001f)
						{
							list.Add(val2);
						}
					}
					foreach (DamageType item in list)
					{
						dmg.Remove(item.Type);
					}
					_manaField.SetValue(victim.Stats, currentMana - num5);
					_hits++;
					_manaSpent += num5;
					_healthLet += totalDamage * num8;
					_negated += totalDamage * num;
					if (_awaitingPointFrame >= 0)
					{
						Log.LogWarning((object)(Stamp() + " [RunicBarrier] split #" + _awaitingPointHit + " (" + _awaitingPointSrc + ") never received a hit point - no impact sound and no spark for it."));
					}
					if (DIAG)
					{
						((MonoBehaviour)this).StartCoroutine(ReportOwnHealth(victim, before, _hits));
					}
					_awaitingPointFrame = Time.frameCount;
					_awaitingPointHit = _hits;
					_awaitingPointSrc = text;
					AbsorbFrame = Time.frameCount;
					AbsorbVictimId = ((Object)victim).GetInstanceID();
					AbsorbTook = totalDamage * num6;
					if (flag)
					{
						Collapse(victim);
					}
					Log.LogMessage((object)(Stamp() + " [RunicBarrier] " + (flag ? "SPLIT+COLLAPSE #" : "SPLIT #") + _hits + " src=" + text + " tier=" + tier.ToString() + " (" + hShare.ToString("0.##") + "/" + mShare.ToString("0.##") + " = " + (hShare + mShare).ToString("0.##") + "x raw) | raw=" + totalDamage.ToString("F2") + " -> health=" + (totalDamage * num8).ToString("F2") + " mana=" + (totalDamage * num6).ToString("F2") + " negated=" + (totalDamage * num).ToString("F2") + " | cost=" + num3.ToString("F2") + " (flat -" + flatUsed.ToString("F2") + ((num3 <= 0.001f) ? ", FREE" : "") + ") spent=" + num5.ToString("F2") + ((num3 < num2 - 0.01f) ? (" (reduced from " + num2.ToString("F2") + ")") : "") + " | mana " + currentMana.ToString("F2") + " -> " + victim.Stats.CurrentMana.ToString("F2") + " | " + text3 + " | list now=" + dmg.TotalDamage.ToString("F2") + (flag ? (" | WARD DOWN, " + (totalDamage * num7).ToString("F2") + " fell back to Health") : "") + " | totals mana=" + _manaSpent.ToString("F1") + " healthShare=" + _healthLet.ToString("F1") + " negated=" + _negated.ToString("F1")));
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)(Stamp() + " [RunicBarrier] handler threw: " + ex));
			}
		}

		private void InstallHitPointHook()
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Expected O, but got Unknown
			try
			{
				Type[] array = new Type[9]
				{
					typeof(Weapon),
					typeof(float),
					typeof(DamageList),
					typeof(Vector3),
					typeof(Vector3),
					typeof(float),
					typeof(float),
					typeof(Character),
					typeof(float)
				};
				MethodInfo methodInfo = AccessTools.Method(typeof(Character), "OnReceiveHit", array, (Type[])null);
				if (methodInfo == null)
				{
					Log.LogError((object)(Stamp() + " [RunicBarrier] OnReceiveHit not found with that signature - no hit point, so the spark cannot fire."));
					return;
				}
				_harmony = new Harmony("com.wrango.runicbarrier");
				_harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(RunicBarrierPlugin).GetMethod("OnReceiveHitPrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				_harmony.PatchAll(typeof(Projectile_Shoot_KeepAlive));
				Log.LogMessage((object)(Stamp() + " [RunicBarrier] OnReceiveHit hook installed."));
			}
			catch (Exception ex)
			{
				Log.LogError((object)(Stamp() + " [RunicBarrier] could not install the hook: " + ex));
			}
		}

		private static void OnReceiveHitPrefix(Character __instance, Weapon _weapon, float _damage, DamageList _damageList, Vector3 _hitDir, Vector3 _hitPoint, float _angle, float _angleDir, Character _dealerChar, float _knockBack)
		{
			//IL_00aa: 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_0229: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!Object.op_Implicit((Object)(object)__instance) || __instance.IsAI)
				{
					return;
				}
				bool flag = __instance.IsLocalPlayer && Time.frameCount == AbsorbFrame && ((Object)__instance).GetInstanceID() == AbsorbVictimId;
				bool flag2 = !__instance.IsLocalPlayer && WardIsUp(__instance);
				if (!flag && !flag2 && !LogHits)
				{
					return;
				}
				string text = null;
				string text2 = null;
				string text3 = null;
				if ((flag || flag2) && (Object)(object)Instance != (Object)null)
				{
					if (flag)
					{
						_awaitingPointFrame = -1;
					}
					if (Time.frameCount == _cueFrame)
					{
						text = "(suppressed, same frame)";
					}
					else
					{
						_cueFrame = Time.frameCount;
						GameObject val = Spark.CreateCue(__instance, _hitPoint, _hitDir, 8f);
						text2 = Instance.PlayImpactSound(val.transform);
						text = Spark.Fire(val, __instance, (ProjectilePrefabs)0, 0f, 0f, 1f, "ProjectileFX");
						text3 = SparkBlast.Fire(val, __instance, (BlastPrefabs)63, 5f, 0.07f, "ProjectileFX");
					}
				}
				Log.LogMessage((object)(Stamp() + " [RunicBarrier] OnReceiveHit" + (flag ? ("  *** same frame as a split taking " + AbsorbTook.ToString("F2") + " ***") : "") + (flag2 ? ("  *** ALLY " + (__instance.Name ?? "?") + ", ward up - cue only, no split on this client ***") : "") + ((text2 == null) ? "" : (" | sound=" + text2)) + ((text == null) ? "" : (" | spark=" + text)) + ((text3 == null) ? "" : (" | blast=" + text3)) + " | _damage=" + _damage.ToString("F2") + " | list=" + ((_damageList == null) ? "null" : (_damageList.Count + " entries total=" + _damageList.TotalDamage.ToString("F2"))) + " | " + Offset(__instance, _hitPoint) + " | _hitPoint=" + ((Vector3)(ref _hitPoint)).ToString("F2") + " | _hitDir=" + ((Vector3)(ref _hitDir)).ToString("F2") + " | _knockBack=" + _knockBack.ToString("F2") + " | dealer=" + (Object.op_Implicit((Object)(object)_dealerChar) ? _dealerChar.Name : "null")));
			}
			catch (Exception ex)
			{
				Log.LogError((object)(Stamp() + " [RunicBarrier] OnReceiveHit prefix threw: " + ex));
			}
		}

		private static string Offset(Character victim, Vector3 hitPoint)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)victim))
			{
				return "offset=(no character)";
			}
			Vector3 val = ((Component)victim).transform.InverseTransformPoint(hitPoint);
			Vector3 val2 = hitPoint - ((Component)victim).transform.position;
			float magnitude = ((Vector3)(ref val2)).magnitude;
			return "offset r=" + val.x.ToString("F2") + " u=" + val.y.ToString("F2") + " f=" + val.z.ToString("F2") + " dist=" + magnitude.ToString("F2");
		}

		private void LogHurtbox(Character c)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (_hurtboxLogged || !Object.op_Implicit((Object)(object)c))
				{
					return;
				}
				_hurtboxLogged = true;
				Collider[] componentsInChildren = ((Component)c).GetComponentsInChildren<Collider>(true);
				string[] obj = new string[7]
				{
					Stamp(),
					" [RunicBarrier] hurtbox of ",
					c.Name,
					": ",
					componentsInChildren.Length.ToString(),
					" collider(s), root at ",
					null
				};
				Vector3 val = ((Component)c).transform.position;
				obj[6] = ((Vector3)(ref val)).ToString("F2");
				string text = string.Concat(obj);
				foreach (Collider val2 in componentsInChildren)
				{
					if (Object.op_Implicit((Object)(object)val2))
					{
						Bounds bounds = val2.bounds;
						string[] obj2 = new string[12]
						{
							text,
							"\n    ",
							((object)val2).GetType().Name,
							" '",
							((Object)val2).name,
							"'",
							val2.enabled ? "" : " (disabled)",
							val2.isTrigger ? " (trigger)" : "",
							" | extents=",
							null,
							null,
							null
						};
						val = ((Bounds)(ref bounds)).extents;
						obj2[9] = ((Vector3)(ref val)).ToString("F2");
						obj2[10] = " | centre offset from root=";
						val = ((Component)c).transform.InverseTransformPoint(((Bounds)(ref bounds)).center);
						obj2[11] = ((Vector3)(ref val)).ToString("F2");
						text = string.Concat(obj2);
					}
				}
				Log.LogMessage((object)text);
			}
			catch (Exception ex)
			{
				Log.LogError((object)(Stamp() + " [RunicBarrier] hurtbox dump failed: " + ex));
			}
		}

		private static string Describe(Character c)
		{
			if (!Object.op_Implicit((Object)(object)c))
			{
				return "<null>";
			}
			return c.Name + "(local=" + c.IsLocalPlayer + ",id=" + ((Object)c).GetInstanceID() + ")";
		}

		internal void OnDestroy()
		{
			foreach (KeyValuePair<int, UnityAction<Object, DamageList>> sub in _subs)
			{
				if ((Object)(object)CharacterManager.Instance == (Object)null)
				{
					break;
				}
				foreach (Character value in CharacterManager.Instance.Characters.Values)
				{
					if (Object.op_Implicit((Object)(object)value) && ((Object)value).GetInstanceID() == sub.Key)
					{
						value.OnHitPreResistance = (UnityAction<Object, DamageList>)(object)Delegate.Remove((Delegate?)(object)value.OnHitPreResistance, (Delegate?)(object)sub.Value);
					}
				}
			}
			_subs.Clear();
			if (_harmony != null)
			{
				try
				{
					_harmony.UnpatchSelf();
				}
				catch (Exception)
				{
				}
				_harmony = null;
			}
			if (_awaitingPointFrame >= 0 && Log != null)
			{
				Log.LogWarning((object)(Stamp() + " [RunicBarrier] split #" + _awaitingPointHit + " (" + _awaitingPointSrc + ") never received a hit point - no impact sound and no spark for it."));
				_awaitingPointFrame = -1;
			}
			LogSoundTally();
			if (Log != null)
			{
				Log.LogMessage((object)(Stamp() + " [RunicBarrier] unloaded. hits=" + _hits + " mana=" + _manaSpent.ToString("F1") + " healthShare=" + _healthLet.ToString("F1") + " negated=" + _negated.ToString("F1")));
			}
		}
	}
	internal static class Spark
	{
		internal static GameObject CreateCue(Character victim, Vector3 point, Vector3 hitDir, float holdSeconds)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0023: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("RunicBarrierCue");
			val.transform.SetParent(((Component)victim).transform, false);
			val.transform.position = point;
			if (((Vector3)(ref hitDir)).sqrMagnitude > 0.0001f)
			{
				val.transform.rotation = Quaternion.LookRotation(-((Vector3)(ref hitDir)).normalized);
			}
			Object.Destroy((Object)(object)val, holdSeconds);
			return val;
		}

		internal unsafe static string Fire(GameObject host, Character victim, ProjectilePrefabs prefab, float lifespan, float force, float scale, string hideEmitters)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: 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_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((int)prefab == 0)
				{
					return null;
				}
				if (!Object.op_Implicit((Object)(object)victim) || !Object.op_Implicit((Object)(object)host))
				{
					return null;
				}
				ShootProjectile val = host.AddComponent<ShootProjectile>();
				((SL_Effect)new SL_ShootProjectile
				{
					SyncType = (SyncTypes)2,
					CastPosition = (CastPositionType)0,
					LocalPositionAdd = Vector3.zero,
					NoAim = true,
					TargetType = (TargetTypes)0,
					TransformName = "SparkTransform",
					BaseProjectile = prefab,
					InstantiatedAmount = 1,
					Lifespan = lifespan,
					LateShootTime = 0f,
					Unblockable = false,
					EffectsOnlyIfHitCharacter = false,
					EndMode = (EndLifeMode)0,
					DisableOnHit = true,
					IgnoreShooterCollision = true,
					TargetingMode = (TargetMode)0,
					TargetCountPerProjectile = 1,
					TargetRange = 0f,
					AutoTarget = false,
					AutoTargetMaxAngle = 360f,
					AutoTargetRange = 0f,
					ProjectileForce = force,
					DefenseLength = 0f,
					DefenseRange = 0f,
					TrailEnabled = false,
					TrailTime = 0f,
					LightIntensityFade = new Vector2(10f, 2f),
					PointOffset = Vector3.zero,
					AddDirection = Vector3.zero,
					AddRotationForce = Vector3.zero,
					YMagnitudeAffect = 0f,
					YMagnitudeForce = 0f,
					CameraAddYDirection = 0f,
					EffectBehaviour = (EditBehaviours)2,
					ProjectileEffects = (SL_EffectTransform[])(object)new SL_EffectTransform[0]
				}).ApplyToComponent<ShootProjectile>(val);
				((Shooter)val).Setup((Factions[])(object)new Factions[1], host.transform);
				Projectile_Shoot_KeepAlive.SparkPending = true;
				Projectile_Shoot_KeepAlive.PendingScale = scale;
				Projectile_Shoot_KeepAlive.PendingPoint = host.transform.position;
				Projectile_Shoot_KeepAlive.PendingCue = host.transform;
				Projectile_Shoot_KeepAlive.PendingHideEmitters = hideEmitters;
				Projectile_Shoot_KeepAlive.LastDrift = "";
				try
				{
					((Effect)val).Affect(victim);
				}
				finally
				{
					Projectile_Shoot_KeepAlive.SparkPending = false;
					Projectile_Shoot_KeepAlive.PendingCue = null;
				}
				string? text = ((object)(*(ProjectilePrefabs*)(&prefab))/*cast due to .constrained prefix*/).ToString();
				Vector3 position = host.transform.position;
				return text + " at " + ((Vector3)(ref position)).ToString("F1") + ((Projectile_Shoot_KeepAlive.LastDrift.Length > 0) ? (" " + Projectile_Shoot_KeepAlive.LastDrift) : " drift=(postfix did not run)");
			}
			catch (Exception ex)
			{
				RunicBarrierPlugin.Log.LogError((object)("[RunicBarrier] spark failed: " + ex));
				return "(threw)";
			}
		}

		internal static void MakeParticlesLocal(Component root)
		{
			//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)
			ParticleSystem[] componentsInChildren = root.GetComponentsInChildren<ParticleSystem>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				MainModule main = componentsInChildren[i].main;
				((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)0;
			}
		}

		internal static string HideEmitters(Component root, string names)
		{
			if (string.IsNullOrEmpty(names))
			{
				return "";
			}
			string[] array = names.Split(new char[1] { ',' });
			ParticleSystem[] componentsInChildren = root.GetComponentsInChildren<ParticleSystem>(true);
			string text = "";
			foreach (ParticleSystem val in componentsInChildren)
			{
				if (!Object.op_Implicit((Object)(object)val))
				{
					continue;
				}
				for (int j = 0; j < array.Length; j++)
				{
					string text2 = array[j].Trim();
					if (text2.Length != 0 && string.Equals(((Object)val).name, text2, StringComparison.OrdinalIgnoreCase))
					{
						val.Stop(true, (ParticleSystemStopBehavior)0);
						((Component)val).gameObject.SetActive(false);
						text = text + ((text.Length > 0) ? "," : "") + ((Object)val).name;
						break;
					}
				}
			}
			return text;
		}
	}
	[HarmonyPatch(typeof(Projectile), "Shoot")]
	public class Projectile_Shoot_KeepAlive
	{
		internal static bool SparkPending;

		internal static float PendingScale = 1f;

		internal static Vector3 PendingPoint;

		internal static Transform PendingCue;

		internal static string PendingHideEmitters = "";

		internal static string LastDrift = "";

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

		private static readonly FieldRef<Projectile, bool> FirstUpdate = AccessTools.FieldRefAccess<Projectile, bool>("m_firstUpdate");

		[HarmonyPostfix]
		public static void Postfix(Projectile __instance)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: 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_00c1: 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)
			if (!SparkPending || !Object.op_Implicit((Object)(object)__instance))
			{
				return;
			}
			FirstUpdate.Invoke(__instance) = false;
			if (!((Component)__instance).gameObject.activeSelf)
			{
				((Component)__instance).gameObject.SetActive(true);
			}
			try
			{
				ApplyScale(__instance, PendingScale);
				Describe(__instance, PendingScale);
				Vector3 position = ((Component)__instance).transform.position;
				Vector3 val = ((Component)__instance).transform.InverseTransformPoint(PendingPoint);
				Vector3 val2 = position - PendingPoint;
				string text = ((Vector3)(ref val2)).magnitude.ToString("F2");
				val2 = -val;
				LastDrift = "drift=" + text + " local=" + ((Vector3)(ref val2)).ToString("F2");
				((Component)__instance).transform.position = PendingPoint;
				position = PendingPoint;
				if (Object.op_Implicit((Object)(object)PendingCue))
				{
					((Component)__instance).gameObject.AddComponent<SparkFollow>().Cue = PendingCue;
					Spark.MakeParticlesLocal((Component)(object)__instance);
					string text2 = Spark.HideEmitters((Component)(object)__instance, PendingHideEmitters);
					if (text2.Length > 0)
					{
						LastDrift = LastDrift + " hid=" + text2;
					}
				}
				((MonoBehaviour)RunicBarrierPlugin.Instance).StartCoroutine(ReportTravel(__instance, PendingCue, ((Object)__instance).GetInstanceID()));
			}
			catch (Exception ex)
			{
				RunicBarrierPlugin.Log.LogError((object)("[RunicBarrier] spark scale failed: " + ex));
			}
		}

		private static IEnumerator ReportTravel(Projectile projectile, Transform cue, int id)
		{
			yield return null;
			string afterOne = Gap(projectile, cue);
			yield return null;
			yield return null;
			string text = Gap(projectile, cue);
			if (afterOne != "0.00" || text != "0.00")
			{
				RunicBarrierPlugin.Log.LogMessage((object)("[RunicBarrier] spark " + id + " sits " + afterOne + " from the cue after 1 frame, " + text + " after 3."));
			}
		}

		private static string Gap(Projectile projectile, Transform cue)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)projectile))
			{
				return "(gone)";
			}
			if (!Object.op_Implicit((Object)(object)cue))
			{
				return "(cue gone)";
			}
			Vector3 val = ((Component)projectile).transform.position - cue.position;
			return ((Vector3)(ref val)).magnitude.ToString("F2");
		}

		private static void ApplyScale(Projectile projectile, float scale)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			if (!(scale <= 0f) && !(Math.Abs(scale - 1f) <= 0.001f))
			{
				ParticleSystem[] componentsInChildren = ((Component)projectile).GetComponentsInChildren<ParticleSystem>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					MainModule main = componentsInChildren[i].main;
					((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)0;
				}
				((Component)projectile).transform.localScale = Vector3.one * scale;
			}
		}

		private static void Describe(Projectile projectile, float scale)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: 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_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: 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)
			string name = ((Object)((Component)projectile).gameObject).name;
			if (!Described.Add(name + "@" + scale.ToString("F3")))
			{
				return;
			}
			ParticleSystem[] componentsInChildren = ((Component)projectile).GetComponentsInChildren<ParticleSystem>(true);
			string[] obj = new string[8]
			{
				"[RunicBarrier] spark prefab '",
				name,
				"' at SparkScale ",
				scale.ToString("F2"),
				": ",
				componentsInChildren.Length.ToString(),
				" particle system(s), root scale now ",
				null
			};
			Vector3 val = ((Component)projectile).transform.localScale;
			obj[7] = ((Vector3)(ref val)).ToString("F2");
			string text = string.Concat(obj);
			foreach (ParticleSystem val2 in componentsInChildren)
			{
				MainModule main = val2.main;
				string[] obj2 = new string[15]
				{
					text,
					"\n    ",
					Path(((Component)val2).transform, ((Component)projectile).transform),
					" | scaling=",
					((object)((MainModule)(ref main)).scalingMode/*cast due to .constrained prefix*/).ToString(),
					" | space=",
					((object)((MainModule)(ref main)).simulationSpace/*cast due to .constrained prefix*/).ToString(),
					" | startSize=",
					null,
					null,
					null,
					null,
					null,
					null,
					null
				};
				MinMaxCurve startSize = ((MainModule)(ref main)).startSize;
				obj2[8] = ((MinMaxCurve)(ref startSize)).constant.ToString("F2");
				obj2[9] = " | localScale=";
				val = ((Component)val2).transform.localScale;
				obj2[10] = ((Vector3)(ref val)).ToString("F2");
				obj2[11] = " | localPos=";
				val = ((Component)val2).transform.localPosition;
				obj2[12] = ((Vector3)(ref val)).ToString("F2");
				obj2[13] = " | offsetFromRoot=";
				val = ((Component)projectile).transform.InverseTransformPoint(((Component)val2).transform.position);
				obj2[14] = ((Vector3)(ref val)).ToString("F2");
				text = string.Concat(obj2);
			}
			Renderer[] componentsInChildren2 = ((Component)projectile).GetComponentsInChildren<Renderer>(true);
			Light[] componentsInChildren3 = ((Component)projectile).GetComponentsInChildren<Light>(true);
			text = text + "\n    renderers=" + componentsInChildren2.Length + " lights=" + componentsInChildren3.Length;
			foreach (Renderer val3 in componentsInChildren2)
			{
				if (Object.op_Implicit((Object)(object)val3))
				{
					string[] obj3 = new string[7]
					{
						text,
						"\n    renderer '",
						Path(((Component)val3).transform, ((Component)projectile).transform),
						"' | localPos=",
						null,
						null,
						null
					};
					val = ((Component)val3).transform.localPosition;
					obj3[4] = ((Vector3)(ref val)).ToString("F2");
					obj3[5] = " | offsetFromRoot=";
					val = ((Component)projectile).transform.InverseTransformPoint(((Component)val3).transform.position);
					obj3[6] = ((Vector3)(ref val)).ToString("F2");
					text = string.Concat(obj3);
				}
			}
			RunicBarrierPlugin.Log.LogMessage((object)text);
		}

		private static string Path(Transform t, Transform root)
		{
			string text = ((Object)t).name;
			Transform parent = t.parent;
			while (Object.op_Implicit((Object)(object)parent) && (Object)(object)parent != (Object)(object)root)
			{
				text = ((Object)parent).name + "/" + text;
				parent = parent.parent;
			}
			return text;
		}
	}
	internal static class SparkBlast
	{
		internal unsafe static string Fire(GameObject host, Character victim, BlastPrefabs prefab, float lifespan, float scale, string hideEmitters)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: 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_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: 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_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: 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_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((int)prefab == 0)
				{
					return null;
				}
				if (!Object.op_Implicit((Object)(object)victim) || !Object.op_Implicit((Object)(object)host))
				{
					return null;
				}
				ShootBlast val = host.AddComponent<ShootBlast>();
				((SL_Effect)new SL_ShootBlast
				{
					SyncType = (SyncTypes)2,
					CastPosition = (CastPositionType)0,
					LocalPositionAdd = Vector3.zero,
					NoAim = true,
					TargetType = (TargetTypes)0,
					TransformName = "SparkBlastTransform",
					BaseBlast = prefab,
					Radius = 0.01f,
					RefreshTime = 0f,
					BlastLifespan = lifespan,
					InstantiatedAmount = 1,
					Interruptible = false,
					MaxHitTargetCount = 1,
					AffectHitTargetCenter = false,
					HitOnShoot = false,
					IgnoreShooter = true,
					IgnoreStop = false,
					NoTargetForwardMultiplier = 1f,
					ParentToShootTransform = true,
					UseTargetCharacterPositionType = false,
					DontPlayHitSound = false,
					FXIsWorld = false,
					PlaySounOnRefresh = false,
					DelayFirstShoot = 0f,
					PlayFXOnRefresh = false,
					EffectBehaviour = (EditBehaviours)2,
					BlastEffects = (SL_EffectTransform[])(object)new SL_EffectTransform[0]
				}).ApplyToComponent<ShootBlast>(val);
				((Shooter)val).Setup((Factions[])(object)new Factions[1], host.transform);
				((Effect)val).Affect(victim);
				Blast[] componentsInChildren = host.GetComponentsInChildren<Blast>(true);
				string text = "";
				foreach (Blast val2 in componentsInChildren)
				{
					if (!Object.op_Implicit((Object)(object)val2))
					{
						continue;
					}
					Spark.MakeParticlesLocal((Component)(object)val2);
					string text2 = Spark.HideEmitters((Component)(object)val2, hideEmitters);
					if (text2.Length > 0)
					{
						text = text + " hid=" + text2;
					}
					if (scale > 0f && Math.Abs(scale - 1f) > 0.001f)
					{
						ParticleSystem[] componentsInChildren2 = ((Component)val2).GetComponentsInChildren<ParticleSystem>(true);
						for (int j = 0; j < componentsInChildren2.Length; j++)
						{
							MainModule main = componentsInChildren2[j].main;
							((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)0;
						}
						((Component)val2).transform.localScale = Vector3.one * scale;
					}
				}
				if (componentsInChildren.Length == 0)
				{
					text = " (no Blast found under the cue - nothing sized or hidden)";
				}
				return ((object)(*(BlastPrefabs*)(&prefab))/*cast due to .constrained prefix*/).ToString() + " blast x" + componentsInChildren.Length + text;
			}
			catch (Exception ex)
			{
				RunicBarrierPlugin.Log.LogError((object)("[RunicBarrier] spark blast failed: " + ex));
				return "(threw)";
			}
		}
	}
	internal class SparkFollow : MonoBehaviour
	{
		internal Transform Cue;

		private void LateUpdate()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)Cue))
			{
				Object.Destroy((Object)(object)this);
			}
			else
			{
				((Component)this).transform.position = Cue.position;
			}
		}
	}
	internal static class VFXTrim
	{
		private static readonly string[] Statuses = new string[2] { "RunicBarrier", "RunicBarrierAmplified" };

		private const string AURA_KEEP = "Ember";

		private static readonly string[] AuraDrop = new string[2] { "SphereSmoke", "Cyl" };

		private static readonly bool LOOP_AURA = true;

		private static readonly float AURA_RATE_SCALE = 0.2f;

		private static readonly float AURA_BURST_SCALE = 0.1f;

		private static readonly float AURA_CYCLE_SECONDS = 3f;

		private static readonly float AURA_BURST_PROBABILITY = 0.6f;

		private static readonly bool AURA_LOCAL_SPACE = false;

		private static readonly bool RUNES_ENABLED = true;

		private const VFXPrefabs RUNE_SOURCE = (VFXPrefabs)52;

		private const string RUNE_CHILD = "Cloud/Runes";

		private const string RUNE_NAME = "RunicBarrierRunes";

		private static readonly float RUNE_HEIGHT = -0.18f;

		private static readonly float RUNE_RATE = 3f;

		private static readonly float RUNE_LIFETIME = 2f;

		private static readonly bool RUNE_LOCAL_SPACE = true;

		private static readonly float RUNE_SIZE_SCALE = 1f;

		private const int MAX_ATTEMPTS = 15;

		private static bool _statusesDone;

		private static int _attempts;

		private static bool _gaveUp;

		internal static void TryOnce()
		{
			if (!_gaveUp && !_statusesDone)
			{
				_attempts++;
				try
				{
					_statusesDone = DoStatuses();
				}
				catch (Exception ex)
				{
					RunicBarrierPlugin.Log.LogError((object)("[RunicBarrier] vfx trim threw: " + ex));
					_gaveUp = true;
					return;
				}
				if (!_statusesDone && _attempts >= 15)
				{
					_gaveUp = true;
					RunicBarrierPlugin.Log.LogWarning((object)("[RunicBarrier] vfx trim gave up after " + _attempts + " attempts - a status never resolved. An untrimmed copy still carries the dome."));
				}
			}
		}

		private static bool DoStatuses()
		{
			if (ResourcesPrefabManager.Instance == null)
			{
				return false;
			}
			bool result = true;
			for (int i = 0; i < Statuses.Length; i++)
			{
				StatusEffect statusEffectPrefab = ResourcesPrefabManager.Instance.GetStatusEffectPrefab(Statuses[i]);
				if (!Object.op_Implicit((Object)(object)statusEffectPrefab))
				{
					result = false;
				}
				else if (!Object.op_Implicit((Object)(object)statusEffectPrefab.FXPrefab))
				{
					RunicBarrierPlugin.Log.LogMessage((object)("[RunicBarrier] vfx trim, status '" + Statuses[i] + "': FXPrefab is NULL, FxInstantiation=" + ((object)Unsafe.As<FXInstantiationTypes, FXInstantiationTypes>(ref statusEffectPrefab.FxInstantiation)/*cast due to .constrained prefix*/).ToString() + " - the XML's VFXPrefab did not resolve to a prefab."));
				}
				else
				{
					Trim("status '" + Statuses[i] + "'", statusEffectPrefab.FXPrefab);
				}
			}
			return result;
		}

		private static void Trim(string label, Transform root)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0338: Unknown result type (might be due to invalid IL or missing references)
			//IL_0347: Unknown result type (might be due to invalid IL or missing references)
			//IL_034c: Unknown result type (might be due to invalid IL or missing references)
			string text = "[RunicBarrier] vfx trim, " + label + ": root '" + ((Object)root).name + "'";
			MinMaxGradient startColor = default(MinMaxGradient);
			((MinMaxGradient)(ref startColor))..ctor(Color.white);
			bool haveColour = false;
			ParticleSystemRenderer component = ((Component)root).GetComponent<ParticleSystemRenderer>();
			if (Object.op_Implicit((Object)(object)component))
			{
				((Renderer)component).enabled = false;
				text = text + "\n    <root> dome renderer DISABLED (was " + ((Object.op_Implicit((Object)(object)((Renderer)component).sharedMaterial) && Object.op_Implicit((Object)(object)((Renderer)component).sharedMaterial.shader)) ? ((Object)((Renderer)component).sharedMaterial.shader).name : "no shader") + ")";
			}
			else
			{
				text += "\n    <root> NO ParticleSystemRenderer - the dome was not where the 0.9.20 map put it, so it is still rendering.";
			}
			Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if (!Object.op_Implicit((Object)(object)val) || (Object)(object)val == (Object)(object)root)
				{
					continue;
				}
				if (Matches(((Object)val).name, AuraDrop))
				{
					((Component)val).gameObject.SetActive(false);
					text = text + "\n    " + ((Object)val).name + " DROPPED (flare; the burst already plays it)";
					continue;
				}
				if (((Object)val).name == "Ember")
				{
					ParticleSystem component2 = ((Component)val).GetComponent<ParticleSystem>();
					if (Object.op_Implicit((Object)(object)component2))
					{
						MainModule main = component2.main;
						if (LOOP_AURA)
						{
							((MainModule)(ref main)).loop = true;
						}
						float duration = ((MainModule)(ref main)).duration;
						if (AURA_CYCLE_SECONDS > 0f)
						{
							((MainModule)(ref main)).duration = AURA_CYCLE_SECONDS;
						}
						if (AURA_LOCAL_SPACE)
						{
							((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)0;
						}
						EmissionModule emission = component2.emission;
						float rateOverTimeMultiplier = ((EmissionModule)(ref emission)).rateOverTimeMultiplier;
						((EmissionModule)(ref emission)).rateOverTimeMultiplier = rateOverTimeMultiplier * AURA_RATE_SCALE;
						string[] obj = new string[25]
						{
							text,
							"\n    ",
							((Object)val).name,
							" KEPT, loop=",
							((MainModule)(ref main)).loop.ToString(),
							", space=",
							((object)((MainModule)(ref main)).simulationSpace/*cast due to .constrained prefix*/).ToString(),
							", rate ",
							rateOverTimeMultiplier.ToString("F1"),
							" -> ",
							((EmissionModule)(ref emission)).rateOverTimeMultiplier.ToString("F1"),
							" (x",
							null,
							null,
							null,
							null,
							null,
							null,
							null,
							null,
							null,
							null,
							null,
							null,
							null
						};
						float aURA_RATE_SCALE = AURA_RATE_SCALE;
						obj[12] = aURA_RATE_SCALE.ToString("0.##");
						obj[13] = "), lifetime=";
						MinMaxCurve startLifetime = ((MainModule)(ref main)).startLifetime;
						obj[14] = ((MinMaxCurve)(ref startLifetime)).constant.ToString("F2");
						obj[15] = " -> about ";
						float rateOverTimeMultiplier2 = ((EmissionModule)(ref emission)).rateOverTimeMultiplier;
						startLifetime = ((MainModule)(ref main)).startLifetime;
						obj[16] = (rateOverTimeMultiplier2 * ((MinMaxCurve)(ref startLifetime)).constant).ToString("F0");
						obj[17] = " in the air, max=";
						obj[18] = ((MainModule)(ref main)).maxParticles.ToString();
						obj[19] = ", cycle ";
						obj[20] = duration.ToString("F2");
						obj[21] = " -> ";
						obj[22] = ((MainModule)(ref main)).duration.ToString("F2");
						obj[23] = "s between swells, bursts=";
						obj[24] = ((EmissionModule)(ref emission)).burstCount.ToString();
						text = string.Concat(obj);
						text += ScaleBursts(emission);
						startColor = ((MainModule)(ref main)).startColor;
						haveColour = true;
						continue;
					}
				}
				text = text + "\n    " + ((Object)val).name + " kept as is" + (((Component)val).gameObject.activeSelf ? "" : " [INACTIVE]");
			}
			if (RUNES_ENABLED)
			{
				text += AttachRunes(root, haveColour, startColor);
			}
			RunicBarrierPlugin.Log.LogMessage((object)text);
		}

		private static string AttachRunes(Transform root, bool haveColour, MinMaxGradient emberColour)
		{
			//IL_0038: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: 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_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)root.Find("RunicBarrierRunes")))
			{
				return "\n    RunicBarrierRunes already present, not attached twice";
			}
			GameObject val;
			try
			{
				val = SL_PlayVFX.GetVfxSystem((VFXPrefabs)52);
			}
			catch (Exception)
			{
				val = null;
			}
			if ((Object)(object)val == (Object)null)
			{
				return "\n    runes NOT attached: " + ((object)(VFXPrefabs)52/*cast due to .constrained prefix*/).ToString() + " is not in SideLoader's cache";
			}
			Transform val2 = val.transform.Find("Cloud/Runes");
			if (!Object.op_Implicit((Object)(object)val2))
			{
				return "\n    runes NOT attached: no 'Cloud/Runes' under " + ((object)(VFXPrefabs)52/*cast due to .constrained prefix*/).ToString();
			}
			if (!Object.op_Implicit((Object)(object)((Component)val2).GetComponent<ParticleSystem>()))
			{
				return "\n    runes NOT attached: 'Cloud/Runes' has no ParticleSystem";
			}
			GameObject obj = Object.Instantiate<GameObject>(((Component)val2).gameObject);
			((Object)obj).name = "RunicBarrierRunes";
			obj.transform.SetParent(root, false);
			obj.transform.localPosition = new Vector3(0f, RUNE_HEIGHT, 0f);
			obj.transform.localRotation = Quaternion.identity;
			obj.transform.localScale = Vector3.one;
			obj.SetActive(true);
			ParticleSystem component = obj.GetComponent<ParticleSystem>();
			MainModule main = component.main;
			EmissionModule emission = component.emission;
			string text;
			if (haveColour)
			{
				((MainModule)(ref main)).startColor = emberColour;
				text = "startColor -> the aura's " + Describe(emberColour);
			}
			else
			{
				text = "startColor LEFT GREEN - Ember's colour was not captured";
			}
			((MainModule)(ref main)).loop = true;
			((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(RUNE_LIFETIME);
			if (RUNE_LOCAL_SPACE)
			{
				((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)0;
			}
			MinMaxCurve val3;
			if (Math.Abs(RUNE_SIZE_SCALE - 1f) > 0.001f)
			{
				val3 = ((MainModule)(ref main)).startSize;
				((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(((MinMaxCurve)(ref val3)).constant * RUNE_SIZE_SCALE);
			}
			((EmissionModule)(ref emission)).rateOverTime = new MinMaxCurve(RUNE_RATE);
			((EmissionModule)(ref emission)).burstCount = 0;
			string[] obj2 = new string[21]
			{
				"\n    RunicBarrierRunes ATTACHED from ",
				((object)(VFXPrefabs)52/*cast due to .constrained prefix*/).ToString(),
				"/Cloud/Runes\n        ",
				text,
				"\n        loop=",
				((MainModule)(ref main)).loop.ToString(),
				", space=",
				((object)((MainModule)(ref main)).simulationSpace/*cast due to .constrained prefix*/).ToString(),
				", rate=",
				((EmissionModule)(ref emission)).rateOverTimeMultiplier.ToString("F1"),
				", lifetime=",
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null
			};
			val3 = ((MainModule)(ref main)).startLifetime;
			obj2[11] = ((MinMaxCurve)(ref val3)).constant.ToString("F2");
			obj2[12] = " -> about ";
			obj2[13] = (RUNE_RATE * RUNE_LIFETIME).ToString("F0");
			obj2[14] = " in the air, startSize=";
			val3 = ((MainModule)(ref main)).startSize;
			obj2[15] = ((MinMaxCurve)(ref val3)).constant.ToString("F2");
			obj2[16] = ", bursts=";
			obj2[17] = ((EmissionModule)(ref emission)).burstCount.ToString();
			obj2[18] = ", height=";
			float rUNE_HEIGHT = RUNE_HEIGHT;
			obj2[19] = rUNE_HEIGHT.ToString("F2");
			obj2[20] = VerticalExtent(component);
			return string.Concat(obj2);
		}

		private static string VerticalExtent(ParticleSystem ps)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: 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_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			ShapeModule shape = ps.shape;
			VelocityOverLifetimeModule velocityOverLifetime = ps.velocityOverLifetime;
			ForceOverLifetimeModule forceOverLifetime = ps.forceOverLifetime;
			object obj;
			if (!((ShapeModule)(ref shape)).enabled)
			{
				obj = "disabled";
			}
			else
			{
				string[] obj2 = new string[9]
				{
					((object)((ShapeModule)(ref shape)).shapeType/*cast due to .constrained prefix*/).ToString(),
					" scale=",
					null,
					null,
					null,
					null,
					null,
					null,
					null
				};
				Vector3 val = ((ShapeModule)(ref shape)).scale;
				obj2[2] = ((Vector3)(ref val)).ToString("F2");
				obj2[3] = " pos=";
				val = ((ShapeModule)(ref shape)).position;
				obj2[4] = ((Vector3)(ref val)).ToString("F2");
				obj2[5] = " radius=";
				obj2[6] = ((ShapeModule)(ref shape)).radius.ToString("F2");
				obj2[7] = " thickness=";
				obj2[8] = ((ShapeModule)(ref shape)).radiusThickness.ToString("F2");
				obj = string.Concat(obj2);
			}
			string text = "\n        shape: " + (string?)obj;
			return text + "\n        drift: velocityOverLifetime=" + (((VelocityOverLifetimeModule)(ref velocityOverLifetime)).enabled ? ("ON y " + Curve(((VelocityOverLifetimeModule)(ref velocityOverLifetime)).y) + " space=" + ((object)((VelocityOverLifetimeModule)(ref velocityOverLifetime)).space/*cast due to .constrained prefix*/).ToString()) : "off") + ", forceOverLifetime=" + (((ForceOverLifetimeModule)(ref forceOverLifetime)).enabled ? ("ON y " + Curve(((ForceOverLifetimeModule)(ref forceOverLifetime)).y)) : "off");
		}

		private static string Curve(MinMaxCurve c)
		{
			//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_001e: Expected I4, but got Unknown
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			ParticleSystemCurveMode mode = ((MinMaxCurve)(ref c)).mode;
			return (int)mode switch
			{
				0 => ((MinMaxCurve)(ref c)).constant.ToString("F2") + " (Constant)", 
				3 => ((MinMaxCurve)(ref c)).constantMin.ToString("F2") + ".." + ((MinMaxCurve)(ref c)).constantMax.ToString("F2") + " (TwoConstants)", 
				1 => "CURVE x" + ((MinMaxCurve)(ref c)).curveMultiplier.ToString("F2") + ((((MinMaxCurve)(ref c)).curve != null) ? (" (" + ((MinMaxCurve)(ref c)).curve.keys.Length + " keys)") : ""), 
				2 => "TWO CURVES x" + ((MinMaxCurve)(ref c)).curveMultiplier.ToString("F2"), 
				_ => ((object)((MinMaxCurve)(ref c)).mode/*cast due to .constrained prefix*/).ToString(), 
			};
		}

		private static string Describe(MinMaxGradient g)
		{
			//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_001a: Expected I4, but got Unknown
			//IL_001e: 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_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			ParticleSystemGradientMode mode = ((MinMaxGradient)(ref g)).mode;
			return (int)mode switch
			{
				0 => Hex(((MinMaxGradient)(ref g)).color), 
				2 => "TwoColors " + Hex(((MinMaxGradient)(ref g)).colorMin) + " .. " + Hex(((MinMaxGradient)(ref g)).colorMax), 
				1 => "Gradient (" + ((((MinMaxGradient)(ref g)).gradient != null) ? (((MinMaxGradient)(ref g)).gradient.colorKeys.Length + " keys") : "null") + ")", 
				_ => ((object)((MinMaxGradient)(ref g)).mode/*cast due to .constrained prefix*/).ToString(), 
			};
		}

		private static string Hex(Color c)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			return "#" + Mathf.RoundToInt(Mathf.Clamp01(c.r) * 255f).ToString("X2") + Mathf.RoundToInt(Mathf.Clamp01(c.g) * 255f).ToString("X2") + Mathf.RoundToInt(Mathf.Clamp01(c.b) * 255f).ToString("X2") + " (" + c.r.ToString("F2") + "," + c.g.ToString("F2") + "," + c.b.ToString("F2") + ")";
		}

		private static string ScaleBursts(EmissionModule em)
		{
			//IL_0031: 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_003a: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			int burstCount = ((EmissionModule)(ref em)).burstCount;
			if (burstCount <= 0)
			{
				return "";
			}
			Burst[] array = (Burst[])(object)new Burst[burstCount];
			((EmissionModule)(ref em)).GetBursts(array);
			string text = "";
			for (int i = 0; i < burstCount; i++)
			{
				Burst val = array[i];
				MinMaxCurve count = ((Burst)(ref val)).count;
				float constantMax = ((MinMaxCurve)(ref count)).constantMax;
				((MinMaxCurve)(ref count)).constantMin = ((MinMaxCurve)(ref count)).constantMin * AURA_BURST_SCALE;
				((MinMaxCurve)(ref count)).constantMax = ((MinMaxCurve)(ref count)).constantMax * AURA_BURST_SCALE;
				((Burst)(ref val)).count = count;
				float probability = ((Burst)(ref val)).probability;
				((Burst)(ref val)).probability = AURA_BURST_PROBABILITY;
				((EmissionModule)(ref em)).SetBurst(i, val);
				string[] obj = new string[21]
				{
					text,
					"\n        burst ",
					i.ToString(),
					": count ",
					constantMax.ToString("F1"),
					" -> ",
					((MinMaxCurve)(ref count)).constantMax.ToString("F1"),
					" (x",
					null,
					null,
					null,
					null,
					null,
					null,
					null,
					null,
					null,
					null,
					null,
					null,
					null
				};
				float aURA_BURST_SCALE = AURA_BURST_SCALE;
				obj[8] = aURA_BURST_SCALE.ToString("0.##");
				obj[9] = ") mode=";
				obj[10] = ((object)((MinMaxCurve)(ref count)).mode/*cast due to .constrained prefix*/).ToString();
				obj[11] = ", probability ";
				obj[12] = probability.ToString("F2");
				obj[13] = " -> ";
				obj[14] = ((Burst)(ref val)).probability.ToString("F2");
				obj[15] = ", time=";
				obj[16] = ((Burst)(ref val)).time.ToString("F2");
				obj[17] = " cycles=";
				obj[18] = ((Burst)(ref val)).cycleCount.ToString();
				obj[19] = " repeatInterval=";
				obj[20] = ((Burst)(ref val)).repeatInterval.ToString("F2");
				text = string.Concat(obj);
			}
			return text;
		}

		private static bool Matches(string name, string[] names)
		{
			for (int i = 0; i < names.Length; i++)
			{
				if (string.Equals(name, names[i], StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}
	}
}