Decompiled source of Crawl Further v1.2.1

plugins/CrawlFurther/CrawlFurther.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using CrawlFurther.Art;
using CrawlFurther.Compat;
using CrawlFurther.Content.Bosses;
using CrawlFurther.Content.Ghosts;
using CrawlFurther.Content.Gods;
using CrawlFurther.Content.Gods.BelMora;
using CrawlFurther.Content.Gods.Jinx;
using CrawlFurther.Content.Gods.Kaurn;
using CrawlFurther.Content.Gods.Ossivar;
using CrawlFurther.Content.Gods.Sylvene;
using CrawlFurther.Content.Gods.Umbrael;
using CrawlFurther.Content.Gods.Vhorrul;
using CrawlFurther.Content.Gods.Ysveld;
using CrawlFurther.Content.Gods.Zhekra;
using CrawlFurther.Content.Heroes;
using CrawlFurther.Content.Items;
using CrawlFurther.Content.Library;
using CrawlFurther.Content.Objects;
using CrawlFurther.Content.Secrets;
using CrawlFurther.Content.Testing;
using CrawlFurther.Content.Tips;
using CrawlFurther.Content.Weapons;
using CrawlFurther.Diagnostics;
using CrawlFurther.Game;
using CrawlFurther.Ghosts;
using CrawlFurther.Gods;
using CrawlFurther.Heroes;
using CrawlFurther.Items;
using CrawlFurther.Monsters;
using CrawlFurther.Objects;
using CrawlFurther.Testing;
using CrawlFurther.UI;
using CrawlFurther.Util;
using HarmonyLib;
using InControl;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace CrawlFurther.Content
{
	public static class ContentChecks
	{
		public static readonly string[] GodNames = new string[9] { "Vhorrul", "Ossivar", "Sylvene", "Umbrael", "Bel'Mora", "Jinx", "Zhekra", "Kaurn", "Ysveld" };

		private static void Bad(string msg)
		{
			SelfTest.Bad(msg);
		}

		private static void Note(string msg)
		{
			SelfTest.Note(msg);
		}

		public static void AddSections()
		{
			SelfTest.AddSection(300, "evolution trees", (Action)CheckTrees);
			SelfTest.AddSection(400, "gods", (Action)CheckGods);
			SelfTest.AddSection(500, "shop items", (Action)CheckItems);
			SelfTest.AddSection(600, "weapons", (Action)CheckWeapons);
			SelfTest.AddSection(700, "ghost forms, bosses, origins", (Action)CheckOthers);
			SelfTest.AddSection(800, "slots, unlocks, custom gods", (Action)delegate
			{
				FrameworkChecks.SelfCheck(Bad);
				SlotChallenges.SelfCheck(Bad);
			});
			SelfTest.AddSection(900, "custom heroes", (Action)delegate
			{
				HeroCustom.SelfCheck(Bad);
			});
			SelfTest.AddSection(1000, "custom ghosts", (Action)delegate
			{
				GhostCustom.SelfCheck(Bad);
			});
			SelfTest.AddSection(1100, "ghost forms", (Action)delegate
			{
				GhostV11.SelfCheck(Bad);
			});
			SelfTest.AddSection(1500, "silver uniques", (Action)delegate
			{
				SilverPack.SelfCheck(Bad);
				MonsterSecrets.SelfCheck(Bad);
			});
			SelfTest.AddSection(1600, "secret statues", (Action)delegate
			{
				StatuePack.SelfCheck(Bad);
			});
			SelfTest.AddSection(1650, "monster challenges", (Action)delegate
			{
				MonsterChallenges.SelfCheck(Bad, Note);
			});
			SelfTest.AddSection(1700, "items wave 3", (Action)delegate
			{
				ItemPack3.SelfCheck(Bad);
			});
			SelfTest.AddSection(1800, "room objects A (and ObjectKit)", (Action)delegate
			{
				ObjectPack.SelfCheck(Bad);
			});
			SelfTest.AddSection(1900, "room objects B (fun and secret)", (Action)delegate
			{
				ObjectPack2.SelfCheck(Bad);
			});
			SelfTest.AddSection(2200, "ghost slots (Ascension, Thralls)", (Action)delegate
			{
				GhostSlots.SelfCheck(Bad);
			});
			SelfTest.AddSection(2300, "silver variants", (Action)delegate
			{
				SilverVariants.SelfCheck(Bad);
			});
		}

		private static SpawnGroup StatueGroup()
		{
			//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)
			SpawnGroup[] array = Resources.FindObjectsOfTypeAll<SpawnGroup>();
			foreach (SpawnGroup val in array)
			{
				if (((Object)((Component)val).gameObject).name == "EnemyGroupStatue")
				{
					Scene scene = ((Component)val).gameObject.scene;
					if (!((Scene)(ref scene)).IsValid())
					{
						return val;
					}
				}
			}
			return null;
		}

		private static string Name(Player p)
		{
			if (!((Object)(object)p == (Object)null))
			{
				return ((Object)((Component)p).gameObject).name;
			}
			return "null";
		}

		public static void CheckTrees()
		{
			HashSet<Player> hashSet = new HashSet<Player>(MonsterFactory.Built.Values);
			HashSet<Player> hashSet2 = new HashSet<Player>();
			SpawnGroup val = StatueGroup();
			List<SpawnItem> list = (((Object)(object)val != (Object)null) ? R.Get<List<SpawnItem>>((object)val, "m_items") : null);
			if (list == null)
			{
				Bad("statue group EnemyGroupStatue not found");
			}
			foreach (string builtName in DeityFactory.BuiltNames)
			{
				if (Array.IndexOf(GodNames, builtName) < 0)
				{
					continue;
				}
				Deity deity = SystemDeity.GetDeity(builtName);
				if (deity == null)
				{
					Bad("god " + builtName + " was built but is not in the god list");
					continue;
				}
				List<List<Player>> list2 = new List<List<Player>>
				{
					new List<Player>()
				};
				GameObject[] array = (GameObject[])(((object)deity.GetStartingMonsters()) ?? ((object)new GameObject[0]));
				foreach (GameObject val2 in array)
				{
					Player val3 = (((Object)(object)val2 != (Object)null) ? val2.GetComponent<Player>() : null);
					if ((Object)(object)val3 == (Object)null)
					{
						Bad(builtName + ": a starting monster is missing");
					}
					else
					{
						list2[0].Add(val3);
					}
				}
				Dictionary<string, Player> dictionary = new Dictionary<string, Player>();
				Dictionary<Player, Player> dictionary2 = new Dictionary<Player, Player>();
				for (int j = 0; j < 2; j++)
				{
					List<Player> list3 = new List<Player>();
					foreach (Player item in list2[j])
					{
						Player[] array2 = (Player[])(((object)item.GetEvolveTo()) ?? ((object)new Player[0]));
						List<Player> list4 = new List<Player>();
						Player[] array3 = array2;
						foreach (Player val4 in array3)
						{
							if ((Object)(object)val4 != (Object)null && !list4.Contains(val4))
							{
								list4.Add(val4);
							}
						}
						if (array2.Length != 2 || list4.Count != 2)
						{
							Bad(builtName + ": " + Name(item) + " (T" + (j + 1) + ") offers " + array2.Length + " evolutions (" + list4.Count + " distinct), must be exactly 2");
						}
						foreach (Player item2 in list4)
						{
							if (!hashSet.Contains(item2))
							{
								Bad(builtName + ": " + Name(item) + " evolves into " + Name(item2) + ", which is not a mod monster");
							}
							if (dictionary2.TryGetValue(item2, out var value))
							{
								Bad(builtName + ": " + Name(item2) + " is offered by both " + Name(value) + " and " + Name(item) + " (evolutions must not be shared)");
							}
							else
							{
								dictionary2[item2] = item;
							}
							if (!list3.Contains(item2))
							{
								list3.Add(item2);
							}
						}
						if (list4.Count == 2)
						{
							string text = Name(list4[0]);
							string text2 = Name(list4[1]);
							string text3 = ((string.CompareOrdinal(text, text2) < 0) ? (text + "|" + text2) : (text2 + "|" + text));
							if (dictionary.TryGetValue(text3, out var value2))
							{
								Bad(builtName + ": " + Name(item) + " and " + Name(value2) + " offer the same pair (" + text3 + ")");
							}
							else
							{
								dictionary[text3] = item;
							}
						}
					}
					list2.Add(list3);
				}
				int[] array4 = new int[3] { 3, 6, 12 };
				float[] array5 = new float[3] { 0f, 2.5f, 4.5f };
				for (int k = 0; k < 3; k++)
				{
					if (list2[k].Count != array4[k])
					{
						Bad(builtName + ": T" + (k + 1) + " has " + list2[k].Count + " monsters, the tree rule wants " + array4[k]);
					}
					foreach (Player item3 in list2[k])
					{
						hashSet2.Add(item3);
						for (int l = 0; l < 3; l++)
						{
							if (l != k && list2[l].Contains(item3))
							{
								Bad(builtName + ": " + Name(item3) + " sits in two tiers");
							}
						}
						float num = R.Get<float>((object)item3, "m_evolveCost");
						if (k > 0 && Mathf.Abs(num - array5[k]) > 0.01f)
						{
							Bad(builtName + ": " + Name(item3) + " (T" + (k + 1) + ") costs " + num + ", expected " + array5[k]);
						}
					}
				}
				foreach (Player p in list2[2])
				{
					Player[] evolveTo = p.GetEvolveTo();
					if (evolveTo != null && evolveTo.Length != 0)
					{
						Bad(builtName + ": final " + Name(p) + " still evolves (" + evolveTo.Length + ")");
					}
					exSpriteAnimClip animationStatue = p.GetAnimationStatue();
					if ((Object)(object)animationStatue == (Object)null || !((Object)animationStatue).name.StartsWith("ModStatue_"))
					{
						Bad(builtName + ": final " + Name(p) + " has no carved statue (" + (((Object)(object)animationStatue == (Object)null) ? "none" : ((Object)animationStatue).name) + ")");
					}
					if (list != null && !list.Exists((SpawnItem val6) => val6 != null && (Object)(object)val6.m_object == (Object)(object)((Component)p).gameObject))
					{
						Bad(builtName + ": final " + Name(p) + " is not in the statue group");
					}
				}
				Note(builtName + ": T1 " + Names(list2[0]) + " | T2 " + Names(list2[1]) + " | T3 " + Names(list2[2]));
			}
			GoldSecretPack.CheckTree(Bad, Note, hashSet2, list);
			foreach (KeyValuePair<string, int> item4 in MonsterFactory.Tier)
			{
				if (item4.Value < 2)
				{
					continue;
				}
				Player val5 = null;
				foreach (Player item5 in hashSet)
				{
					if ((Object)(object)item5 != (Object)null && ((Object)((Component)item5).gameObject).name == item4.Key)
					{
						val5 = item5;
						break;
					}
				}
				if (!SilverUniques.Ids.Contains(item4.Key) && !SecretStatues.Is(item4.Key) && (Object)(object)val5 != (Object)null && !hashSet2.Contains(val5))
				{
					Bad(item4.Key + " is an evolved tier but no god's tree reaches it");
				}
			}
		}

		private static string Names(List<Player> l)
		{
			List<string> list = new List<string>();
			foreach (Player item in l)
			{
				list.Add(Name(item));
			}
			return string.Join(", ", list.ToArray());
		}

		public static void CheckGods()
		{
			List<Deity> deities = SystemDeity.GetDeities();
			string[] godNames = GodNames;
			foreach (string text in godNames)
			{
				bool flag = false;
				if (deities != null)
				{
					foreach (Deity item in deities)
					{
						if (item != null && item.GetName() == text)
						{
							flag = true;
						}
					}
				}
				if (!flag)
				{
					Bad("god " + text + " is not in the god list");
				}
				else
				{
					Note("god " + text + " ok");
				}
			}
			int num = 0;
			foreach (string builtName in DeityFactory.BuiltNames)
			{
				if (Array.IndexOf(GodNames, builtName) >= 0)
				{
					num++;
				}
			}
			if (num != GodNames.Length)
			{
				Bad(num + " Crawl: Further gods registered, expected " + GodNames.Length);
			}
			int num2 = 0;
			if (deities != null)
			{
				foreach (string builtName2 in DeityFactory.BuiltNames)
				{
					int num3 = 0;
					foreach (Deity item2 in deities)
					{
						if (item2 != null && item2.GetName() == builtName2)
						{
							num3++;
						}
					}
					if (num3 > 1)
					{
						num2++;
					}
				}
			}
			if (num2 > 0)
			{
				Bad(num2 + " mod god(s) appear more than once in the god list");
			}
		}

		private static void CheckBubble(string who, exSpriteAnimClip bubble)
		{
			if ((Object)(object)bubble == (Object)null || bubble.frameInfos == null || bubble.frameInfos.Count == 0)
			{
				Bad(who + " has no shop bubble clip");
			}
			else if (SpriteSheets.ByAtlas(bubble.frameInfos[0].atlas) == null)
			{
				Bad(who + " shop bubble is vanilla art (" + ((Object)bubble).name + ")");
			}
		}

		private static void CheckPedestal(string who, string key, SpriteSheet pedestals)
		{
			if (pedestals != null && (key == null || !pedestals.Has(key)))
			{
				Bad(who + " has no shop pedestal frame '" + key + "' in ShopPedestals");
			}
		}

		public static void CheckItems()
		{
			SpriteSheet val = SpriteSheets.Get("ShopPedestals");
			if (val == null)
			{
				Bad("art/ShopPedestals missing: every mod item shows a stand-in on its pedestal");
			}
			HashSet<string> hashSet = new HashSet<string>();
			foreach (ItemDef item in ItemPack.Items)
			{
				if (!hashSet.Add(item.id))
				{
					Bad("item " + item.id + " is queued twice");
					continue;
				}
				if (!ItemPack.Built.TryGetValue(item.id, out var value) || (Object)(object)value == (Object)null)
				{
					Bad("item " + item.id + " failed to build");
					continue;
				}
				Note("item " + value.m_displayName + " cost " + value.m_cost);
				CheckBubble("item " + item.id, R.Get<exSpriteAnimClip>((object)value, "m_animPurchasableBubble"));
				CheckPedestal("item " + item.id, ShopPedestal.KeyFor((IPurchasable)(object)value), val);
			}
		}

		public static void CheckWeapons()
		{
			SpriteSheet pedestals = SpriteSheets.Get("ShopPedestals");
			foreach (WeaponDef def in WeaponPack.Defs)
			{
				if (!WeaponPack.Built.TryGetValue(def.id, out var value) || (Object)(object)value == (Object)null)
				{
					Bad("weapon " + def.id + " failed to build");
					continue;
				}
				Note("weapon " + value.m_weaponName + " cost " + value.m_cost);
				CheckBubble("weapon " + def.id, value.m_animationPurchasableBubble);
				CheckPedestal("weapon " + def.id, "Wpn" + def.id, pedestals);
			}
			if (WeaponPack.Built.Count < WeaponPack.Defs.Count)
			{
				Note(WeaponPack.Defs.Count - WeaponPack.Built.Count + " weapon(s) missing");
			}
		}

		public static void CheckOthers()
		{
			foreach (GhostFormEntry form in GhostPack.Forms)
			{
				SpriteSheet val = SpriteSheets.Get(((GhostFormDef)form).portraitArt);
				if (val == null || !val.Has("Idle"))
				{
					Bad("ghost form " + ((GhostFormDef)form).name + " portrait missing");
				}
			}
			Player[] array = (Player[])(object)new Player[6]
			{
				GhostPack.Mote,
				GhostPack.Spitter,
				GhostPack.Gel,
				GhostPack.Brute,
				GhostPack.Titan,
				GhostPack.King
			};
			for (int i = 0; i < array.Length; i++)
			{
				if ((Object)(object)array[i] == (Object)null)
				{
					Bad("a ghost-form blob monster failed to build");
				}
			}
			GameObject[] array2 = (GameObject[])(object)new GameObject[4]
			{
				GhostPack.KingSlam,
				GhostPack.KingQuake,
				GhostPack.KingDrop,
				GhostPack.KingDropPool
			};
			for (int i = 0; i < array2.Length; i++)
			{
				if ((Object)(object)array2[i] == (Object)null)
				{
					Bad("a King Blob effect failed to build");
				}
			}
			GhostBlobs.SelfCheck((Action<string>)Bad);
			BlobChallenges.SelfCheck(Bad);
			Note("bosses built: " + BossFactory.Built.Count + (BossPack.Enabled ? "" : " (switched off: Bosses.Enabled = false)"));
			foreach (Boss item in BossFactory.Built)
			{
				Note("  " + item.GetDisplayName());
			}
			if (BossPack.Enabled && BossFactory.Built.Count < 2)
			{
				Bad("only " + BossFactory.Built.Count + " of 2 mod bosses built");
			}
			if (!BossPack.Enabled && BossFactory.Built.Count > 0)
			{
				Bad("bosses are switched off but " + BossFactory.Built.Count + " were built");
			}
			foreach (OriginDef item2 in HeroClasses.All)
			{
				SpriteSheet val2 = SpriteSheets.Get(item2.portraitArt);
				if (val2 == null || !val2.Has("Idle"))
				{
					Bad("origin " + item2.id + " portrait missing");
				}
			}
		}
	}
	public static class ContentSetup
	{
		public const string PedestalSheet = "ShopPedestals";

		public const string BossTopic = "bosses";

		public static void Install()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_004c: Expected O, but got Unknown
			Branding.Set(new BrandingDef
			{
				name = "Crawl: Further",
				version = "1.2.1",
				wordmark = "BrandFurther",
				spark = "BrandSpark",
				menuPip = "BrandPip",
				menuMote = "BrandMote"
			});
			ModMusic.AddFolder(Path.Combine(Plugin.ModDir, "music"));
			TierRules.StarterDamage = 1.3f;
			TierRules.StarterMinHealth = 4f;
			ContinueGame.Enabled = ((BaseUnityPlugin)Plugin.I).Config.Bind<bool>("Game", "ContinueAfterWin", true, "When the hero beats the boss, offer to keep playing with two more tries at the boss.").Value;
			ShopPedestal.AddSheet("ShopPedestals");
			string[] array = new string[6] { "HeroWanderer", "HeroWanderer_P1", "HeroWanderer_P2", "HeroWanderer_P3", "HeroWanderer_P4", "GhostWisp" };
			for (int i = 0; i < array.Length; i++)
			{
				ModGem.Exclude(array[i]);
			}
			foreach (GhostFormEntry form in GhostPack.Forms)
			{
				GhostForms.Register((GhostFormDef)(object)form);
			}
			GhostForms.FormOf = GhostPack.DefOf;
			OriginList.Register();
			OriginColours.Register();
			Statues.Sheets.Add("ModStatues");
			AddTips();
			FurtherVault.Register();
			SlotChallenges.Register();
			BlobChallenges.Register();
			MonsterEvents.PlayerAwake += HeroItemHooks.PlayerAwake;
			ItemRegistry.AddDamageHook((Func<Health, DamageInfo, GameObject, bool>)HeroItemHooks.Damage);
			MonsterEvents.AttackSpawned += HeroItemHooks.EffectSpawned;
			ImpactThemes.Register();
			Unlocks.EctoRefunding = () => GhostV11.Refunding;
			HeroClasses.CustomHeroes = (ICustomHeroes)(object)new CustomHeroSlots();
			SlotGods.AddEntries = GodSlots.AddItems;
			SlotGods.HideExtras = GodSlots.HideExtras;
			SlotGods.Redraw = GodSlots.Invalidate;
			SlotGods.TierOf = (Deity d) => (SlotTier)(((??)CustomGod.Of(d)?.tier) ?? 0);
			SlotGods.PageGodsOf = IdolGodNames;
			SlotGods.PerkGodOf = (Deity d) => CustomGod.Of(d)?.PerkGod;
			Statues.Exclude = (string id) => SilverUniques.Ids.Contains(id) || GoldSecret.TreeIds.Contains(id) || SecretStatues.Is(id);
			Further.AddPack("Vhorrul", (Action)VhorrulPack.Register);
			Further.AddPack("Ossivar", (Action)OssivarPack.Register);
			Further.AddPack("Sylvene", (Action)SylvenePack.Register);
			Further.AddPack("Umbrael", (Action)UmbraelPack.Register);
			Further.AddPack("Bel'Mora", (Action)BelMoraPack.Register);
			Further.AddPack("Jinx", (Action)JinxPack.Register);
			Further.AddPack("Zhekra", (Action)ZhekraPack.Register);
			Further.AddPack("Kaurn", (Action)KaurnPack.Register);
			Further.AddPack("Ysveld", (Action)YsveldPack.Register);
			Further.AddPack("Silver", (Action)SilverPack.Register);
			Further.AddPack("Gold Secret", (Action)GoldSecretPack.Register);
			Further.AddPack("Secret Statues", (Action)StatuePack.Register);
			Further.AddPack("Ghosts", (Action)GhostPack.Register);
			Further.AddPack("Bosses", (Action)BossPack.Register);
			Further.AddPack("Items", (Action)ItemPack.Register);
			Further.AddPack("Items2", (Action)ItemPack2.Register);
			Further.AddPack("Items3", (Action)ItemPack3.Register);
			Further.AddPack("Weapons", (Action)WeaponPack.Register);
			Further.AddPack("Objects", (Action)ObjectPack.Register);
			Further.AddPack("Objects B", (Action)ObjectPack2.Register);
			Further.AddPack("Monster secrets", (Action)MonsterSecrets.Register);
			ContentChecks.AddSections();
		}

		private static void AddTips()
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			bool enabled = BossPack.Enabled;
			foreach (KeyValuePair<string, MonsterTip> tip in MonsterTipsData.Tips)
			{
				MonsterTipsData.Group.TryGetValue(tip.Key, out var value);
				if (enabled || !(value == "bosses"))
				{
					TipRegistry.Add(tip.Key, tip.Value, value);
				}
			}
			foreach (KeyValuePair<string, string> item in MonsterTipsData.Alias)
			{
				TipRegistry.AddAlias(item.Key, item.Value);
			}
			foreach (string item2 in MonsterTipsData.VaultOrder)
			{
				if (enabled || !MonsterTipsData.Group.TryGetValue(item2, out var value2) || !(value2 == "bosses"))
				{
					TipRegistry.AddVaultLine(item2, MonsterTipsData.Vault[item2].Key, MonsterTipsData.Vault[item2].Value);
				}
			}
			PauseTopic[] topics = PauseTipsData.Topics;
			foreach (PauseTopic val in topics)
			{
				if (enabled || val.id != "bosses")
				{
					TipRegistry.AddTopic(val);
				}
			}
			TipRegistry.TopicOrder.AddRange(new string[5] { "status", "icons", "ghosts", "slots", "unlocks" });
			if (enabled)
			{
				TipRegistry.TopicOrder.Add("bosses");
			}
			TipRegistry.GhostFormTopic = "ghosts";
			MonsterTips.GhostKey = delegate(Player body)
			{
				GhostFormEntry ghostFormEntry = GhostPack.DefOf(body.GetPlayerData());
				return (ghostFormEntry == null || GhostForms.IsDefault((GhostFormDef)(object)ghostFormEntry)) ? null : ("ModGhost" + ((GhostFormDef)ghostFormEntry).id);
			};
		}

		private static List<string> IdolGodNames(Deity d)
		{
			CustomGod.Record record = CustomGod.Of(d);
			if (record == null)
			{
				return null;
			}
			List<string> list = new List<string> { record.perk };
			foreach (string starter in record.starters)
			{
				foreach (CustomGod.Starter item in CustomGod.Starters())
				{
					if (((Object)((Component)item.p).gameObject).name == starter)
					{
						list.Add(item.god.GetName());
					}
				}
			}
			return list;
		}
	}
	[BepInPlugin("com.firefightermate.crawlfurther", "Crawl: Further", "1.2.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string GUID = "com.firefightermate.crawlfurther";

		public const string NAME = "Crawl: Further";

		public const string VERSION = "1.2.1";

		public static Plugin I;

		internal static ManualLogSource Log;

		internal static string ModDir;

		private float m_bannerTimer = 12f;

		private static bool s_started;

		private static FurtherMod s_mod;

		private static readonly string[] PatchOrder = new string[34]
		{
			"Patch_Items3PlayerAwake", "Patch_Items3HeroChange", "Patch_Items3Kill", "Patch_Items3Damage", "Patch_SilverAwake", "Patch_HeroKill", "Patch_UmbraelHits", "Patch_JinxHeroHits", "Patch_VhorrulHits", "Patch_GhostSlotsNewRun",
			"Patch_GhostSlotDamage", "Patch_HexBoltHits", "Patch_SylveneHeroHits", "Patch_GoldDamage", "Patch_GoldSecretAwake", "Patch_StatueDamageOut", "Patch_StatueDamageIn", "Patch_StatueAwake", "Patch_WeaponRuntimeAwake", "Patch_WeaponHeroHit",
			"Patch_WeaponHandsMaterial", "Patch_ItemDamageTag", "Patch_OssHits", "Patch_ZhkHeroHits", "Patch_ZhkHeroStruck", "Patch_ZhekraMantisExecute", "Patch_ZhekraAwake", "Patch_GleanerValue", "Patch_GleanerGathered", "Patch_KaurnAwake",
			"Patch_BelMoraHits", "Patch_SilverVariantFrames", "Patch_CustomGodInUse", "Patch_CustomPerkEcho"
		};

		private static int s_bossPick;

		private static string s_note;

		private static float s_noteTime;

		private GUIStyle m_lineStyle;

		private readonly GUIContent m_line = new GUIContent();

		private void Awake()
		{
			I = this;
			Log = ((BaseUnityPlugin)this).Logger;
			((MonoBehaviour)this).useGUILayout = false;
			ModDir = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
			s_mod = Further.AddMod((BaseUnityPlugin)(object)this, (Action)OnGameReady);
			Log.LogInfo((object)("Crawl: Further awake. Unity " + Application.unityVersion + ", dir " + ModDir));
		}

		private void Update()
		{
			if (m_bannerTimer > 0f)
			{
				m_bannerTimer -= Time.unscaledDeltaTime;
			}
			if (s_started)
			{
				GameTick();
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void OnGameReady()
		{
			s_mod.PatchAll(PatchOrder);
			SheetScales.Register();
			ContentSetup.Install();
			if (TestMode.On)
			{
				ContentTestActions.Register();
			}
			s_started = true;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private void GameTick()
		{
			if (Input.GetKeyDown((KeyCode)291))
			{
				CycleBoss();
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void CycleBoss()
		{
			List<Boss> built = BossFactory.Built;
			if (built.Count != 0)
			{
				s_bossPick = (s_bossPick + 1) % (built.Count + 1);
				BossFactory.Forced = ((s_bossPick == 0) ? null : built[s_bossPick - 1]);
				s_note = "Next boss: " + (((Object)(object)BossFactory.Forced == (Object)null) ? "random" : BossFactory.Forced.GetDisplayName());
				s_noteTime = 4f;
				Log.LogInfo((object)s_note);
			}
		}

		private void OnGUI()
		{
			//IL_0035: 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_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_0087: 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_0151: Unknown result type (might be due to invalid IL or missing references)
			bool flag = s_noteTime > 0f;
			bool flag2 = m_bannerTimer > 0f;
			if (flag || flag2)
			{
				if (m_lineStyle == null)
				{
					m_lineStyle = new GUIStyle(GUI.skin.label)
					{
						wordWrap = true,
						clipping = (TextClipping)0
					};
				}
				float y = 6f;
				float w = Mathf.Min(900f, (float)Screen.width - 16f);
				if (flag2)
				{
					GUI.color = new Color(1f, 0.85f, 0.4f, Mathf.Clamp01(m_bannerTimer));
					y = Line("Crawl: Further 1.2.1 loaded: " + (s_started ? StatusText() : "starting") + ((s_started && AnyModBoss()) ? "  (F10: force a mod boss)" : ""), y, w);
				}
				if (flag)
				{
					s_noteTime -= Time.unscaledDeltaTime;
					GUI.color = new Color(0.8f, 0.9f, 1f, Mathf.Clamp01(s_noteTime));
					y = Line("(Crawl: Further) " + s_note, y, w);
				}
				string text = ((flag2 && s_started) ? TestBanner() : null);
				if (text != null)
				{
					GUI.color = new Color(1f, 0.85f, 0.4f, Mathf.Clamp01(m_bannerTimer));
					Line(text, y, w);
				}
			}
		}

		private float Line(string text, float y, float w)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			m_line.text = text;
			float num = Mathf.Max(22f, m_lineStyle.CalcHeight(m_line, w));
			GUI.Label(new Rect(8f, y, w, num), m_line, m_lineStyle);
			return y + num;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool AnyModBoss()
		{
			return BossFactory.Built.Count > 0;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static string TestBanner()
		{
			return TestMode.Banner;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static string StatusText()
		{
			return Further.Status;
		}
	}
	internal static class SheetScales
	{
		public static void Register()
		{
			Dictionary<string, float> bySheet = ArtScale.BySheet;
			bySheet["BlobMote"] = 0.92f;
			bySheet["BlobSpitter"] = 0.8f;
			bySheet["BlobGel"] = 0.8f;
			bySheet["BlobBrute"] = 0.57f;
			bySheet["BlobTitan"] = 0.58f;
			bySheet["BlobKing"] = 0.5f;
		}
	}
}
namespace CrawlFurther.Content.Weapons
{
	public static class WeaponFx
	{
		public static GameObject HookJab;

		public static GameObject Hook;

		public static GameObject ChainLink;

		public static GameObject GlaiveSlash;

		public static GameObject Glaive;

		public static GameObject RiftSlashA;

		public static GameObject RiftSlashB;

		public static GameObject RiftMark;

		public static GameObject RiftSnap;

		public static GameObject DiceSwing;

		public static GameObject Jackpot;

		public static readonly GameObject[] Dice = (GameObject[])(object)new GameObject[6];

		public static GameObject TideCleave;

		public static GameObject TideCrash;

		public static GameObject Wave;

		public static GameObject Splash;

		public static GameObject LeechStab;

		public static GameObject LeechSlash;

		public static GameObject Bead;

		public static GameObject LeechHeal;

		public static GameObject BriarArrow;

		public static GameObject ThornPatch;

		public static GameObject BellHit;

		public static GameObject BellRing;

		public static GameObject BellToll;

		public static GameObject LanternSwing;

		public static GameObject SoulBolt;

		public static GameObject SoulFire;

		public static GameObject Wisp;

		public static GameObject ArcBolt;

		public static GameObject Arc;

		public static GameObject Spark;

		public static GameObject FrostSlash;

		public static GameObject FrostChill;

		public static GameObject FrostChill2;

		public static GameObject FrostShatter;

		public static GameObject MercySlash;

		public static GameObject MercyX;

		public static GameObject ReapA;

		public static GameObject ReapB;

		public static GameObject ReapSoul;

		public static GameObject StarSlam;

		public static GameObject StarWell;

		public static GameObject HydraArrow;

		public static GameObject HydraShard;

		public static GameObject HydraSplit;

		public static GameObject GuardBash;

		public static GameObject GuardRing;

		public static GameObject GuardBlock;

		public static GameObject HeartBolt;

		public static GameObject HeartPierce;

		public static GameObject KrisStab;

		public static GameObject KrisBack;

		public static GameObject BlightSwing;

		public static GameObject BlightBolt;

		public static GameObject BlightCloud;

		public static GameObject BlightSpore;

		public static GameObject OrrerySwing;

		public static GameObject OrreryBolt;

		public static GameObject OrreryStar;

		public static GameObject GrudgeStone;

		public static GameObject GrudgeBrand;

		public static GameObject MidasCoin;

		public static GameObject MidasGold;

		public static GameObject LanceThrust;

		public static GameObject LanceCharge;

		public static GameObject LashBody;

		public static GameObject LashTip;

		public static GameObject Kunai;

		public static GameObject KunaiSlash;

		public static GameObject KunaiMark;

		public static GameObject KunaiPop;

		public const int LayerWall = 9;

		public const int LayerMonster = 14;

		public static readonly Dictionary<string, GameObject> ImpactHit = new Dictionary<string, GameObject>();

		public static readonly Dictionary<string, GameObject> ImpactWall = new Dictionary<string, GameObject>();

		public static readonly GameObject[] ReapStacks = (GameObject[])(object)new GameObject[5];

		public static readonly exSpriteAnimClip[] MidasTiers = (exSpriteAnimClip[])(object)new exSpriteAnimClip[3];

		public static GameObject LanceReady;

		private static readonly string[] ImpactIds = new string[12]
		{
			"Gravehook", "Moonglaive", "Tidebreaker", "Wickstaff", "Arcbolt", "HydraBow", "Heartseeker", "Blightstaff", "Orrery", "Grudgestone",
			"Midas", "Kunai"
		};

		internal static void OnSpawn<T>(GameObject tmpl, Action<T> init) where T : Component
		{
			if ((Object)(object)tmpl == (Object)null)
			{
				return;
			}
			FxFactory.OnSpawn.TryGetValue(tmpl, out var prev);
			FxFactory.OnSpawn[tmpl] = delegate(GameObject i)
			{
				if (prev != null)
				{
					prev(i);
				}
				T obj = i.GetComponent<T>() ?? i.AddComponent<T>();
				if (init != null)
				{
					init(obj);
				}
			};
		}

		internal static void Anchor(GameObject go, Anchor a, Vector2 offset)
		{
			//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)
			if (!((Object)(object)go == (Object)null))
			{
				exSprite component = go.GetComponent<exSprite>();
				if ((Object)(object)component != (Object)null)
				{
					((exPlane)component).anchor = a;
					((exPlane)component).offset = offset;
				}
			}
		}

		private static void ScaleColliders(GameObject go, float k)
		{
			//IL_0053: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)go == (Object)null || Mathf.Abs(k - 1f) < 0.01f)
			{
				return;
			}
			CapsuleCollider[] components = go.GetComponents<CapsuleCollider>();
			foreach (CapsuleCollider val in components)
			{
				val.radius *= k;
				if (val.direction != 2)
				{
					val.height *= k;
				}
				val.center = new Vector3(val.center.x * k, val.center.y * k, val.center.z);
			}
			BoxCollider[] components2 = go.GetComponents<BoxCollider>();
			foreach (BoxCollider val2 in components2)
			{
				val2.size = new Vector3(val2.size.x * k, val2.size.y * k, val2.size.z);
				val2.center = new Vector3(val2.center.x * k, val2.center.y * k, val2.center.z);
			}
		}

		internal static void Box(GameObject go, float w, float h, float cx = 0f, float cy = 0f)
		{
			//IL_001d: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)go == (Object)null))
			{
				BoxCollider[] components = go.GetComponents<BoxCollider>();
				foreach (BoxCollider val in components)
				{
					val.size = new Vector3(w, h, val.size.z);
					val.center = new Vector3(cx, cy, val.center.z);
				}
			}
		}

		internal static GameObject Swipe(string name, string vanilla, string art, string anim, float damage, float knock, Vector2 hitCentre, float colliderScale = 1f, Status status = null, float statusChance = 0f)
		{
			//IL_0036: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			SpriteSheet val = SpriteSheets.Get(art);
			GameObject val2 = FxFactory.Clone(vanilla, name);
			if ((Object)(object)val2 == (Object)null || val == null)
			{
				return val2;
			}
			FxFactory.StripChildren(val2, new string[0]);
			exSpriteAnimClip val3 = new ClipBuilder(val, anim, name + "Clip").Once().Ev(0, "AnimDamageOn").Ev(2, "AnimDamageOff")
				.Build();
			FxFactory.Reskin(val2, val3, val);
			Anchor(val2, (Anchor)4, hitCentre * colliderScale);
			FxFactory.SetEffect(val2, true, 0f, 0f, 0f, (GameObject)null, (GameObject)null, (bool?)null, (float?)null, (bool?)null);
			FxFactory.SetDamage(val2, damage, -1f, knock, status, statusChance, -1f, (bool?)false, (bool?)null, true);
			ScaleColliders(val2, colliderScale);
			FxKit.NoTint(val2);
			return val2;
		}

		internal static GameObject Shot(string name, string vanilla, string art, string anim, float speed, float life, float damage, float knock, bool destroyOnHit = true, float accel = 0f, float speedMax = 0f)
		{
			bool flag = destroyOnHit;
			return FxKit.Projectile(name, vanilla, art, anim, speed, life, damage, knock, (Status)null, 1f, accel, speedMax, true, flag);
		}

		internal static GameObject Zone(string name, ClipBuilder cb, SpriteSheet sh, float damage, float rate, float knock, int on, int off, Status status = null, float statusChance = 0f, bool attached = false)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = FxFactory.Clone("DFX_Axe_InvisibleHit", name);
			if ((Object)(object)val == (Object)null || sh == null)
			{
				return val;
			}
			FxFactory.StripChildren(val, new string[0]);
			cb.Ev(on, "AnimDamageOn").Ev(off, "AnimDamageOff");
			FxFactory.Reskin(val, cb.Build(), sh);
			Anchor(val, (Anchor)4, Vector2.zero);
			if (attached)
			{
				FxFactory.SetEffect(val, true, 0f, 0f, 0f, (GameObject)null, (GameObject)null, (bool?)null, (float?)null, (bool?)null);
			}
			else
			{
				bool? flag = false;
				bool? flag2 = false;
				FxFactory.SetEffect(val, true, 0f, 0f, 0f, (GameObject)null, (GameObject)null, flag, (float?)null, flag2);
			}
			FxFactory.SetDamage(val, damage, rate, knock, status, statusChance, -1f, (bool?)false, (bool?)null, true);
			FxKit.NoTint(val);
			return val;
		}

		internal static GameObject Vis(string name, string art, string anim, bool loop = false, float life = 0f, Anchor a = (Anchor)4)
		{
			//IL_0012: 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)
			GameObject obj = FxKit.Visual(name, art, anim, loop, life, new float[0]);
			Anchor(obj, a, Vector2.zero);
			return obj;
		}

		public static void Build()
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_0376: Unknown result type (might be due to invalid IL or missing references)
			//IL_042b: Unknown result type (might be due to invalid IL or missing references)
			//IL_049e: 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_059d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0618: Unknown result type (might be due to invalid IL or missing references)
			//IL_065a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0710: Unknown result type (might be due to invalid IL or missing references)
			//IL_0836: Unknown result type (might be due to invalid IL or missing references)
			//IL_0892: Unknown result type (might be due to invalid IL or missing references)
			//IL_08ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_0915: Unknown result type (might be due to invalid IL or missing references)
			//IL_0995: Unknown result type (might be due to invalid IL or missing references)
			//IL_09c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b0d: Unknown result type (might be due to invalid IL or missing references)
			Status status = FxFactory.GetStatus("StatusDizzy");
			Status status2 = FxFactory.GetStatus("StatusStuckToFloor");
			Status status3 = FxFactory.GetStatus("StatusBleeding");
			HookJab = Swipe("ModWpnHookJab", "SpearSwipe", "FxWpnGravehook", "Jab", 1.05f, 0.5f, new Vector2(1.7f, -2.1f));
			Hook = Shot("ModWpnHook", "SpearProjectile", "FxWpnGravehook", "Hook", 340f, 0.5f, 1f, 0f, destroyOnHit: true, 0.04f, 0.1f);
			if ((Object)(object)Hook != (Object)null)
			{
				FxFactory.SetContacts(Hook, (bool?)true, (GameObject)null, false);
			}
			WeaponFx.OnSpawn<WpnTetherFx>(Hook, (Action<WpnTetherFx>)null);
			ChainLink = Vis("ModWpnChainLink", "FxWpnGravehook", "Chain", loop: false, 0f, (Anchor)4);
			GlaiveSlash = Swipe("ModWpnGlaiveSlash", "1HandedSwordSwipe1", "FxWpnMoonglaive", "Slash", 0.9f, 0.6f, new Vector2(8.4f, 0.4f));
			Glaive = Shot("ModWpnGlaive", "SpearProjectile", "FxWpnMoonglaive", "Glaive", 0f, 2.4f, 0.85f, 0.3f, destroyOnHit: false);
			if ((Object)(object)Glaive != (Object)null)
			{
				FxFactory.SetMotion(Glaive, 0f, 0f, 0f, (GameObject)null, 50f, 0f, (bool?)null, -1f, false, -1f);
				FxFactory.SetDamage(Glaive, 0.85f, 0.35f, 0.3f, (Status)null, -1f, -1f, (bool?)true, (bool?)null, true);
				GameObject glaive = Glaive;
				bool? flag = false;
				bool? flag2 = false;
				FxFactory.SetEffect(glaive, false, 2.4f, 0f, 0f, (GameObject)null, (GameObject)null, flag, (float?)null, flag2);
				Box(Glaive, 14f, 14f);
				Anchor(Glaive, (Anchor)4, Vector2.zero);
			}
			WeaponFx.OnSpawn<WpnGlaiveFx>(Glaive, (Action<WpnGlaiveFx>)delegate(WpnGlaiveFx g)
			{
				g.Reset();
			});
			RiftSlashA = Swipe("ModWpnRiftSlashA", "1HandedSwordSwipe2", "FxWpnRiftblade", "SlashA", 0.9f, 0.5f, new Vector2(8.4f, -0.8f));
			RiftSlashB = Swipe("ModWpnRiftSlashB", "DamageHeroSwipeSkewed", "FxWpnRiftblade", "SlashB", 0.9f, 0.5f, new Vector2(5.5f, 1.3f));
			WeaponFx.OnSpawn<WpnRiftFx>(RiftSlashA, (Action<WpnRiftFx>)null);
			WeaponFx.OnSpawn<WpnRiftFx>(RiftSlashB, (Action<WpnRiftFx>)null);
			RiftMark = Vis("ModWpnRiftMark", "FxWpnRiftblade", "Mark", loop: true, 1.1f, (Anchor)4);
			RiftSnap = Vis("ModWpnRiftSnap", "FxWpnRiftblade", "Snap", loop: false, 0f, (Anchor)4);
			DiceSwing = Swipe("ModWpnDiceSwing", "1HandedSwordSwipe2", "FxWpnSnakeEyes", "Swing", 1f, 0.9f, new Vector2(8.4f, -0.8f));
			WeaponFx.OnSpawn<WpnDiceFx>(DiceSwing, (Action<WpnDiceFx>)delegate(WpnDiceFx d)
			{
				d.baseDamage = 1f;
			});
			for (int num = 0; num < 6; num++)
			{
				Dice[num] = Vis("ModWpnDie" + (num + 1), "FxWpnSnakeEyes", "Die" + (num + 1), loop: false, 0f, (Anchor)4);
			}
			SpriteSheet val = SpriteSheets.Get("FxWpnSnakeEyes");
			Jackpot = Zone("ModWpnJackpot", new ClipBuilder(val, "Jackpot", "ModWpnJackpotClip").Once(), val, 0.8f, 0f, 2.2f, 0, 3);
			Box(Jackpot, 34f, 26f);
			TideCleave = Swipe("ModWpnTideCleave", "DamageHeroSwipeSkewed", "FxWpnTidebreaker", "Cleave", 1f, 0.8f, new Vector2(5.5f, 1.3f), 1.2f);
			TideCrash = Swipe("ModWpnTideCrash", "DamageHeroSwipeSkewed", "FxWpnTidebreaker", "Crash", 1.2f, 1f, new Vector2(5.5f, 1.3f), 1.25f);
			Wave = Shot("ModWpnWave", "SpearProjectile", "FxWpnTidebreaker", "Wave", 150f, 0.65f, 0.4f, 0f, destroyOnHit: false, 0.04f, 0.1f);
			if ((Object)(object)Wave != (Object)null)
			{
				FxFactory.SetDamage(Wave, 0.4f, 0.3f, 0f, (Status)null, -1f, -1f, (bool?)true, (bool?)null, true);
				Box(Wave, 14f, 26f);
				Anchor(Wave, (Anchor)4, Vector2.zero);
			}
			WeaponFx.OnSpawn<WpnWaveFx>(Wave, (Action<WpnWaveFx>)delegate(WpnWaveFx w)
			{
				w.Reset();
			});
			Splash = Vis("ModWpnSplash", "FxWpnTidebreaker", "Splash", loop: false, 0f, (Anchor)4);
			LeechStab = Swipe("ModWpnLeechStab", "DaggerDashthrough", "FxWpnLeechfang", "Stab", 0.75f, 0.4f, new Vector2(6.9f, -1.9f), 1f, status3, 0.15f);
			LeechSlash = Swipe("ModWpnLeechSlash", "1HandedSwordSwipe1", "FxWpnLeechfang", "Slash", 0.75f, 0.5f, new Vector2(8.4f, 0.4f), 1f, status3, 0.15f);
			WeaponFx.OnSpawn<WpnLeechFx>(LeechStab, (Action<WpnLeechFx>)null);
			WeaponFx.OnSpawn<WpnLeechFx>(LeechSlash, (Action<WpnLeechFx>)null);
			Bead = Vis("ModWpnBloodBead", "FxWpnLeechfang", "Bead", loop: true, 1.5f, (Anchor)4);
			WeaponFx.OnSpawn<WpnBeadFx>(Bead, (Action<WpnBeadFx>)delegate(WpnBeadFx b)
			{
				b.Reset();
			});
			LeechHeal = Vis("ModWpnLeechHeal", "FxWpnLeechfang", "Heal", loop: false, 0f, (Anchor)4);
			SpriteSheet val2 = SpriteSheets.Get("FxWpnBriarbow");
			ThornPatch = Zone("ModWpnThornPatch", new ClipBuilder(val2, "Grow", "ModWpnThornPatchClip").Once().Then("Life", 5).Then("Wilt", 1), val2, 0.2f, 0.5f, 0f, 4, -4, status2, 0.5f);
			Box(ThornPatch, 30f, 16f);
			BriarArrow = Shot("ModWpnBriarArrow", "DFX_HeroArrow", "FxWpnBriarbow", "Arrow", 380f, 0.5f, 0.95f, 0.5f);
			if ((Object)(object)BriarArrow != (Object)null)
			{
				GameObject briarArrow = BriarArrow;
				GameObject thornPatch = ThornPatch;
				FxFactory.SetContacts(briarArrow, (bool?)null, thornPatch, false);
				GameObject briarArrow2 = BriarArrow;
				GameObject thornPatch2 = ThornPatch;
				bool? flag2 = true;
				FxFactory.SetEffect(briarArrow2, false, 0.5f, 0f, 0f, thornPatch2, (GameObject)null, (bool?)null, (float?)null, flag2);
			}
			SpriteSheet val3 = SpriteSheets.Get("FxWpnDirgeMaul");
			BellHit = Zone("ModWpnBellHit", new ClipBuilder(val3, "Clang", "ModWpnBellHitClip").Once(), val3, 1f, 0f, 1f, 0, 2, null, 0f, attached: true);
			Box(BellHit, 29.5f, 20.9f, 13f);
			Anchor(BellHit, (Anchor)4, new Vector2(13f, 0f));
			BellRing = Zone("ModWpnBellRing", new ClipBuilder(val3, "Ring", "ModWpnBellRingClip").Once(), val3, 0.35f, 0f, 0.7f, 0, 4, status, 1f);
			Box(BellRing, 52f, 32f);
			WeaponFx.OnSpawn<WpnBellFx>(BellRing, (Action<WpnBellFx>)null);
			BellToll = Zone("ModWpnBellToll", new ClipBuilder(val3, "Toll", "ModWpnBellTollClip").Once(), val3, 0.35f, 0f, 0.9f, 0, 4, status, 1f);
			Box(BellToll, 76f, 46f);
			SpriteSheet val4 = SpriteSheets.Get("FxWpnWickstaff");
			LanternSwing = Swipe("ModWpnLanternSwing", "MagicStaffSwipe", "FxWpnWickstaff", "Swing", 0.2f, 0.8f, new Vector2(5.2f, -1.3f));
			SoulFire = Zone("ModWpnSoulFire", new ClipBuilder(val4, "Fire", "ModWpnSoulFireClip").Once().Repeat(6), val4, 0.12f, 0.4f, 0f, 0, -1);
			Box(SoulFire, 22f, 12f);
			WeaponFx.OnSpawn<WpnSoulFireFx>(SoulFire, (Action<WpnSoulFireFx>)delegate(WpnSoulFireFx f)
			{
				f.Reset();
			});
			Wisp = Shot("ModWpnWisp", "DFX_HeroArrow", "FxWpnWickstaff", "Wisp", 0f, 1.6f, 0.5f, 0.3f);
			if ((Object)(object)Wisp != (Object)null)
			{
				FxFactory.StripChildren(Wisp, new string[0]);
				FxFactory.SetMotion(Wisp, 0f, 0f, 0f, (GameObject)null, 50f, 0f, (bool?)null, -1f, false, -1f);
				GameObject wisp = Wisp;
				bool? flag3 = false;
				bool? flag2 = true;
				FxFactory.SetEffect(wisp, false, 1.6f, 0f, 0f, (GameObject)null, (GameObject)null, flag3, (float?)null, flag2);
				Anchor(Wisp, (Anchor)4, Vector2.zero);
				Box(Wisp, 8f, 8f);
			}
			WeaponFx.OnSpawn<WpnSeekFx>(Wisp, (Action<WpnSeekFx>)delegate(WpnSeekFx s)
			{
				s.Reset();
			});
			SoulBolt = Shot("ModWpnSoulBolt", "DFX_HeroArrow", "FxWpnWickstaff", "Bolt", 170f, 0.85f, 0.6f, 0.3f);
			if ((Object)(object)SoulBolt != (Object)null)
			{
				GameObject soulBolt = SoulBolt;
				GameObject thornPatch = SoulFire;
				FxFactory.SetContacts(soulBolt, (bool?)null, thornPatch, false);
				GameObject soulBolt2 = SoulBolt;
				GameObject soulFire = SoulFire;
				bool? flag2 = true;
				FxFactory.SetEffect(soulBolt2, false, 0.85f, 0f, 0f, soulFire, (GameObject)null, (bool?)null, (float?)null, flag2);
			}
			ArcBolt = Shot("ModWpnArcBolt", "DFX_HeroArrow", "FxWpnArcbolt", "Bolt", 420f, 0.6f, 0.8f, 0.4f);
			WeaponFx.OnSpawn<WpnChainFx>(ArcBolt, (Action<WpnChainFx>)delegate(WpnChainFx c)
			{
				c.Reset();
			});
			Arc = Vis("ModWpnArc", "FxWpnArcbolt", "Arc", loop: false, 0f, (Anchor)3);
			Spark = Vis("ModWpnSpark", "FxWpnArcbolt", "Spark", loop: false, 0f, (Anchor)4);
			Build2();
			BuildV08();
			Plugin.Log.LogInfo((object)"Weapon FX templates built");
		}

		private static void Pierce(GameObject go)
		{
			DamageEffect val = (((Object)(object)go != (Object)null) ? go.GetComponent<DamageEffect>() : null);
			if ((Object)(object)val == (Object)null || val.m_contactData == null)
			{
				return;
			}
			foreach (ContactData contactDatum in val.m_contactData)
			{
				if (contactDatum != null)
				{
					contactDatum.m_destroyOnHit = (((LayerMask)(ref contactDatum.m_layerMask)).value & 0x200) != 0;
				}
			}
		}

		private static GameObject VisRot(string name, string art, string anim)
		{
			GameObject val = Vis(name, art, anim, loop: false, 0f, (Anchor)4);
			if ((Object)(object)val != (Object)null)
			{
				bool? flag = true;
				bool? flag2 = true;
				FxFactory.SetEffect(val, true, 0f, 0f, 0f, (GameObject)null, (GameObject)null, flag, (float?)null, flag2);
			}
			return val;
		}

		private static void Build2()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0441: Unknown result type (might be due to invalid IL or missing references)
			//IL_055e: Unknown result type (might be due to invalid IL or missing references)
			//IL_05cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_0732: Unknown result type (might be due to invalid IL or missing references)
			//IL_0936: Unknown result type (might be due to invalid IL or missing references)
			//IL_099c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a1a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ad6: Unknown result type (might be due to invalid IL or missing references)
			Status status = FxFactory.GetStatus("StatusLavaSteveGoo");
			Status status2 = FxFactory.GetStatus("StatusDizzy");
			FrostSlash = Swipe("ModWpnFrostSlash", "1HandedSwordSwipe1", "FxWpnFrostbrand", "Slash", 1f, 0.6f, new Vector2(8.4f, 0.4f), 1f, status, 0.35f);
			WeaponFx.OnSpawn<WpnFrostFx>(FrostSlash, (Action<WpnFrostFx>)null);
			FrostChill = Vis("ModWpnFrostChill", "FxWpnFrostbrand", "Chill", loop: true, 2.7f, (Anchor)4);
			FrostChill2 = Vis("ModWpnFrostChill2", "FxWpnFrostbrand", "Chill2", loop: true, 2.7f, (Anchor)4);
			SpriteSheet val = SpriteSheets.Get("FxWpnFrostbrand");
			FrostShatter = Zone("ModWpnFrostShatter", new ClipBuilder(val, "Shatter", "ModWpnFrostShatterClip").Once(), val, 0.85f, 0f, 0.8f, 0, 2);
			Box(FrostShatter, 48f, 30f);
			MercySlash = Swipe("ModWpnMercySlash", "1HandedSwordSwipe2", "FxWpnMercyblade", "Slash", 1f, 0.6f, new Vector2(8.4f, -0.8f));
			WeaponFx.OnSpawn<WpnMercyFx>(MercySlash, (Action<WpnMercyFx>)null);
			MercyX = Vis("ModWpnMercyX", "FxWpnMercyblade", "Mercy", loop: false, 0f, (Anchor)4);
			ReapA = Swipe("ModWpnReapA", "DamageHeroSwipeSkewed", "FxWpnReaper", "Reap", 1f, 0.8f, new Vector2(5.5f, 1.3f), 1.25f);
			ReapB = Swipe("ModWpnReapB", "DamageHeroSwipeSkewed", "FxWpnReaper", "Reap2", 1f, 0.9f, new Vector2(5.5f, 1.3f), 1.25f);
			WeaponFx.OnSpawn<WpnReapFx>(ReapA, (Action<WpnReapFx>)null);
			WeaponFx.OnSpawn<WpnReapFx>(ReapB, (Action<WpnReapFx>)null);
			ReapSoul = Vis("ModWpnReapSoul", "FxWpnReaper", "Soul", loop: true, 1.5f, (Anchor)4);
			WeaponFx.OnSpawn<WpnBeadFx>(ReapSoul, (Action<WpnBeadFx>)delegate(WpnBeadFx b)
			{
				b.Reset();
			});
			SpriteSheet val2 = SpriteSheets.Get("FxWpnStarfall");
			StarSlam = Zone("ModWpnStarSlam", new ClipBuilder(val2, "Slam", "ModWpnStarSlamClip").Once(), val2, 1f, 0f, 1f, 0, 2, null, 0f, attached: true);
			Box(StarSlam, 29.5f, 20.9f, 13f);
			Anchor(StarSlam, (Anchor)4, new Vector2(13f, 0f));
			StarWell = Zone("ModWpnStarWell", new ClipBuilder(val2, "Well", "ModWpnStarWellClip").Once(), val2, 0.45f, 0f, 1.2f, 6, -1);
			Box(StarWell, 40f, 26f);
			WeaponFx.OnSpawn<WpnGravityFx>(StarWell, (Action<WpnGravityFx>)delegate(WpnGravityFx g)
			{
				g.Reset();
			});
			HydraShard = Shot("ModWpnHydraShard", "DFX_HeroArrow", "FxWpnHydraBow", "Shard", 380f, 0.35f, 0.55f, 0.3f);
			HydraArrow = Shot("ModWpnHydraArrow", "DFX_HeroArrow", "FxWpnHydraBow", "Arrow", 380f, 0.6f, 1.1f, 0.5f);
			WeaponFx.OnSpawn<WpnSplitFx>(HydraArrow, (Action<WpnSplitFx>)delegate(WpnSplitFx a)
			{
				a.Reset();
			});
			HydraSplit = VisRot("ModWpnHydraSplit", "FxWpnHydraBow", "Split");
			GuardBash = Swipe("ModWpnGuardBash", "1HandedSwordSwipe2", "FxWpnBulwark", "Bash", 1f, 1f, new Vector2(8.4f, -0.8f));
			WeaponFx.OnSpawn<WpnGuardFx>(GuardBash, (Action<WpnGuardFx>)null);
			GuardRing = Vis("ModWpnGuardRing", "FxWpnBulwark", "Guard", loop: true, 5.5f, (Anchor)4);
			GuardBlock = Vis("ModWpnGuardBlock", "FxWpnBulwark", "Block", loop: false, 0f, (Anchor)4);
			HeartBolt = Shot("ModWpnHeartBolt", "DFX_HeroArrowCrossbow", "FxWpnHeartseeker", "Bolt", 500f, 0.6f, 1.8f, 0.8f);
			Pierce(HeartBolt);
			WeaponFx.OnSpawn<WpnPierceFx>(HeartBolt, (Action<WpnPierceFx>)delegate(WpnPierceFx p)
			{
				p.Reset();
			});
			HeartPierce = Vis("ModWpnHeartPierce", "FxWpnHeartseeker", "Pierce", loop: false, 0f, (Anchor)4);
			KrisStab = Swipe("ModWpnKrisStab", "DaggerDashthrough", "FxWpnKris", "Stab", 1f, 0.5f, new Vector2(6.9f, -1.9f));
			WeaponFx.OnSpawn<WpnKrisFx>(KrisStab, (Action<WpnKrisFx>)null);
			KrisBack = Vis("ModWpnKrisBack", "FxWpnKris", "Backstab", loop: false, 0f, (Anchor)4);
			BlightSwing = Swipe("ModWpnBlightSwing", "MagicStaffSwipe", "FxWpnBlightstaff", "Swing", 0.2f, 0.8f, new Vector2(5.2f, -1.3f));
			BlightBolt = Shot("ModWpnBlightBolt", "DFX_HeroArrow", "FxWpnBlightstaff", "Bolt", 170f, 0.85f, 0.45f, 0.3f);
			WeaponFx.OnSpawn<WpnBlightBoltFx>(BlightBolt, (Action<WpnBlightBoltFx>)null);
			BlightCloud = Vis("ModWpnBlightCloud", "FxWpnBlightstaff", "Cloud", loop: true, 2.3f, (Anchor)4);
			BlightSpore = Vis("ModWpnBlightSpore", "FxWpnBlightstaff", "Spore", loop: true, 1.5f, (Anchor)4);
			WeaponFx.OnSpawn<WpnBeadFx>(BlightSpore, (Action<WpnBeadFx>)delegate(WpnBeadFx b)
			{
				b.Reset();
			});
			SpriteSheet val3 = SpriteSheets.Get("FxWpnOrrery");
			OrrerySwing = Swipe("ModWpnOrrerySwing", "MagicStaffSwipe", "FxWpnOrrery", "Swing", 0.2f, 0.8f, new Vector2(5.2f, -1.3f));
			OrreryBolt = Shot("ModWpnOrreryBolt", "DFX_HeroArrow", "FxWpnOrrery", "Bolt", 260f, 0.6f, 0.45f, 0.3f);
			OrreryStar = Zone("ModWpnOrreryStar", new ClipBuilder(val3, "Star", "ModWpnOrreryStarClip").Once().Repeat(16), val3, 0.2f, 0.5f, 0.4f, 0, -1);
			Box(OrreryStar, 9f, 9f);
			WeaponFx.OnSpawn<WpnOrbitFx>(OrreryStar, (Action<WpnOrbitFx>)delegate(WpnOrbitFx o)
			{
				o.Reset();
			});
			GrudgeStone = FxKit.Projectile("ModWpnGrudgeStone", "SlingProjectile", "FxWpnGrudgestone", "Stone", 0f, 0.75f, 0.95f, 0.5f, (Status)null, 1f, 0f, 0f, false, false);
			if ((Object)(object)GrudgeStone != (Object)null)
			{
				FxFactory.SetMotion(GrudgeStone, 0f, 0f, 0f, (GameObject)null, 50f, 0f, (bool?)null, -1f, false, -1f);
			}
			WeaponFx.OnSpawn<WpnGrudgeFx>(GrudgeStone, (Action<WpnGrudgeFx>)delegate(WpnGrudgeFx g)
			{
				g.Reset();
			});
			GrudgeBrand = Vis("ModWpnGrudgeBrand", "FxWpnGrudgestone", "Grudge", loop: true, 8.5f, (Anchor)4);
			MidasCoin = FxKit.Projectile("ModWpnMidasCoin", "SlingProjectile", "FxWpnMidas", "Coin", 210f, 0.9f, 0.55f, 0.5f, (Status)null, 1f, 0.28f, 0.1f, false, false);
			WeaponFx.OnSpawn<WpnMidasFx>(MidasCoin, (Action<WpnMidasFx>)delegate(WpnMidasFx m)
			{
				m.Reset();
			});
			MidasGold = Vis("ModWpnMidasGold", "FxWpnMidas", "Gold", loop: false, 0f, (Anchor)4);
			LanceThrust = Swipe("ModWpnLanceThrust", "SpearSwipe", "FxWpnLance", "Thrust", 1f, 0.8f, new Vector2(1.7f, -2.1f));
			WeaponFx.OnSpawn<WpnChargeFx>(LanceThrust, (Action<WpnChargeFx>)null);
			LanceCharge = VisRot("ModWpnLanceCharge", "FxWpnLance", "Charge");
			LashBody = Swipe("ModWpnLashBody", "SpearSwipe", "FxWpnLash", "Lash", 0.45f, 0.3f, new Vector2(19f, 0f));
			Box(LashBody, 26f, 8f, 19f);
			WeaponFx.OnSpawn<WpnLashFx>(LashBody, (Action<WpnLashFx>)delegate(WpnLashFx l)
			{
				l.Reset();
			});
			SpriteSheet val4 = SpriteSheets.Get("FxWpnLash");
			LashTip = Zone("ModWpnLashTip", new ClipBuilder(val4, "Crack", "ModWpnLashTipClip").Once(), val4, 1.2f, 0f, 1.1f, 0, 2, status2, 0.25f);
			Box(LashTip, 14f, 12f);
			Kunai = Shot("ModWpnKunai", "KnivesProjectile", "FxWpnKunai", "Kunai", 320f, 0.4f, 0.8f, 0.3f);
			WeaponFx.OnSpawn<WpnKunaiFx>(Kunai, (Action<WpnKunaiFx>)null);
			KunaiSlash = Swipe("ModWpnKunaiSlash", "1HandedSwordSwipe1", "FxWpnKunai", "Slash", 0.9f, 0.6f, new Vector2(8.4f, 0.4f));
			WeaponFx.OnSpawn<WpnHuntSlashFx>(KunaiSlash, (Action<WpnHuntSlashFx>)null);
			KunaiMark = Vis("ModWpnKunaiMark", "FxWpnKunai", "Mark", loop: true, 3.2f, (Anchor)4);
			KunaiPop = Vis("ModWpnKunaiPop", "FxWpnKunai", "Pop", loop: false, 0f, (Anchor)4);
		}

		public static GameObject ImpHit(string id)
		{
			if (!ImpactHit.TryGetValue(id, out var value))
			{
				return null;
			}
			return value;
		}

		public static GameObject ImpWall(string id)
		{
			if (!ImpactWall.TryGetValue(id, out var value))
			{
				return null;
			}
			return value;
		}

		private static void Impacts(GameObject proj, string id, bool wallContact = true)
		{
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: 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_00f0: 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_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Expected O, but got Unknown
			DamageEffect val = (((Object)(object)proj != (Object)null) ? proj.GetComponent<DamageEffect>() : null);
			if ((Object)(object)val == (Object)null || val.m_contactData == null)
			{
				return;
			}
			GameObject spawnOnHit = ImpHit(id);
			GameObject val2 = (wallContact ? ImpWall(id) : null);
			List<ContactData> list = new List<ContactData>();
			foreach (ContactData contactDatum in val.m_contactData)
			{
				if (contactDatum == null || ((Object)(object)contactDatum.m_spawnOnHit != (Object)null && ((Object)contactDatum.m_spawnOnHit).name.StartsWith("ModWpn", StringComparison.Ordinal) && !ImpactOwn(contactDatum.m_spawnOnHit)))
				{
					continue;
				}
				int value = ((LayerMask)(ref contactDatum.m_layerMask)).value;
				if ((value & 0x4000) != 0 && (value & 0x200) != 0)
				{
					contactDatum.m_layerMask = LayerMask.op_Implicit(value & -513);
					contactDatum.m_spawnOnHit = spawnOnHit;
					if ((Object)(object)val2 != (Object)null)
					{
						list.Add(new ContactData
						{
							m_layerMask = LayerMask.op_Implicit(512),
							m_destroyOnHit = contactDatum.m_destroyOnHit,
							m_spawnOnHit = val2,
							m_spawnDirection = contactDatum.m_spawnDirection,
							m_knockbackDirection = contactDatum.m_knockbackDirection,
							m_spawnAtMiddle = contactDatum.m_spawnAtMiddle,
							m_hitCorpses = contactDatum.m_hitCorpses,
							m_hitFriendly = contactDatum.m_hitFriendly
						});
					}
				}
				else if ((value & 0x4000) != 0)
				{
					contactDatum.m_spawnOnHit = spawnOnHit;
				}
				else if ((value & 0x200) != 0)
				{
					contactDatum.m_spawnOnHit = val2;
				}
				else
				{
					contactDatum.m_spawnOnHit = null;
				}
			}
			val.m_contactData.AddRange(list);
			val.m_spawnOnHit = spawnOnHit;
		}

		private static bool ImpactOwn(GameObject go)
		{
			foreach (KeyValuePair<string, GameObject> item in ImpactHit)
			{
				if ((Object)(object)item.Value == (Object)(object)go)
				{
					return true;
				}
			}
			foreach (KeyValuePair<string, GameObject> item2 in ImpactWall)
			{
				if ((Object)(object)item2.Value == (Object)(object)go)
				{
					return true;
				}
			}
			return false;
		}

		private static void SlingShadow(GameObject proj, string sheetId)
		{
			Transform val = (((Object)(object)proj != (Object)null) ? proj.transform.Find("Shadow") : null);
			SpriteSheet val2 = SpriteSheets.Get(sheetId);
			if ((Object)(object)val == (Object)null || val2 == null || !val2.Has("Shadow"))
			{
				Plugin.Log.LogWarning((object)("Weapon shadow: missing for " + sheetId));
				return;
			}
			exSprite component = ((Component)val).GetComponent<exSprite>();
			if (!((Object)(object)component == (Object)null))
			{
				component.SetSprite(val2.atlas, val2.Anim("Shadow").frames[0], false);
				Renderer component2 = ((Component)val).GetComponent<Renderer>();
				if ((Object)(object)component2 != (Object)null && (Object)(object)val2.atlas.material != (Object)null)
				{
					component2.sharedMaterial = val2.atlas.material;
				}
				exSpriteAnimation component3 = ((Component)val).GetComponent<exSpriteAnimation>();
				if ((Object)(object)component3 != (Object)null)
				{
					((Behaviour)component3).enabled = false;
				}
			}
		}

		private static GameObject WallPuff(string name, SpriteSheet sh, string vanilla)
		{
			//IL_0031: 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_0069: 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_00c6: Expected O, but got Unknown
			GameObject val = FxFactory.Clone(vanilla, name);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			FxFactory.StripChildren(val, new string[0]);
			FxFactory.Reskin(val, new ClipBuilder(sh, "Wall", name + "Clip").Once().Build(), sh);
			exSprite component = val.GetComponent<exSprite>();
			if ((Object)(object)component != (Object)null)
			{
				((exPlane)component).anchor = (Anchor)4;
				((exPlane)component).offset = Vector2.zero;
				component.color = Color.white;
			}
			FxFactory.SetEffect(val, true, 0f, 0f, 0f, (GameObject)null, (GameObject)null, (bool?)true, (float?)0f, (bool?)false);
			Effect component2 = val.GetComponent<Effect>();
			if ((Object)(object)component2 != (Object)null)
			{
				R.Set((object)component2, "m_startAngle", (object)new MinMaxRange(0f));
				R.Set((object)component2, "m_fadeOutTime", (object)0f);
			}
			FxFactory.SetMotion(val, 0f, 0f, 0f, (GameObject)null, 50f, 0f, (bool?)null, -1f, false, -1f);
			FxKit.NoTint(val);
			DepthHandler component3 = val.GetComponent<DepthHandler>();
			if ((Object)(object)component3 != (Object)null)
			{
				component3.m_heightOffset = -4f;
			}
			return val;
		}

		private static void BuildV08()
		{
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			string[] impactIds = ImpactIds;
			foreach (string text in impactIds)
			{
				string text2 = "FxWpn" + text + "Impact";
				SpriteSheet val = SpriteSheets.Get(text2);
				if (val == null)
				{
					Plugin.Log.LogWarning((object)("Weapon impact: missing sheet " + text2));
					continue;
				}
				GameObject val2 = VisRot("ModWpn" + text + "Hit", text2, "Hit");
				DepthHandler val3 = (((Object)(object)val2 != (Object)null) ? val2.GetComponent<DepthHandler>() : null);
				if ((Object)(object)val3 != (Object)null)
				{
					val3.m_heightOffset = -22f;
				}
				ImpactHit[text] = val2;
				object obj;
				switch (text)
				{
				default:
					obj = "ContactGenericSmall";
					break;
				case "Kunai":
				case "Moonglaive":
				case "Grudgestone":
					obj = "ContactGenericWall";
					break;
				}
				string vanilla = (string)obj;
				if (val.Has("Wall"))
				{
					ImpactWall[text] = WallPuff("ModWpn" + text + "Wall", val, vanilla);
				}
			}
			Impacts(Hook, "Gravehook");
			Impacts(Glaive, "Moonglaive", wallContact: false);
			Impacts(Wave, "Tidebreaker");
			Impacts(Wisp, "Wickstaff");
			Impacts(ArcBolt, "Arcbolt");
			Impacts(HydraArrow, "HydraBow");
			Impacts(HydraShard, "HydraBow");
			Impacts(HeartBolt, "Heartseeker");
			Impacts(BlightBolt, "Blightstaff");
			Impacts(OrreryBolt, "Orrery");
			Impacts(GrudgeStone, "Grudgestone", wallContact: false);
			Impacts(MidasCoin, "Midas");
			Impacts(Kunai, "Kunai");
			SlingShadow(GrudgeStone, "FxWpnGrudgestone");
			SlingShadow(MidasCoin, "FxWpnMidas");
			for (int j = 0; j < ReapStacks.Length; j++)
			{
				ReapStacks[j] = Vis("ModWpnReapStacks" + (j + 1), "FxWpnReaperStacks", "Stacks" + (j + 1), loop: true, 0f, (Anchor)4);
			}
			LanceReady = Vis("ModWpnLanceReady", "FxWpnLance", "Ready", loop: true, 0f, (Anchor)4);
			SpriteSheet val4 = SpriteSheets.Get("FxWpnMidas");
			string[] array = new string[3] { "Coin", "Coin2", "Coin3" };
			if (val4 == null)
			{
				return;
			}
			for (int k = 0; k < array.Length; k++)
			{
				if (val4.Has(array[k]))
				{
					MidasTiers[k] = new ClipBuilder(val4, array[k], "ModWpnMidas" + array[k] + "Clip").Loop().Build();
				}
			}
		}
	}
	public static class WeaponPack
	{
		public static readonly List<WeaponDef> Defs;

		public static readonly List<WeaponDef> Defs2;

		public static Dictionary<string, Weapon> Built => ItemRegistry.Weapons;

		private static DamageEffectData Melee(GameObject o, float ox, float oy, float upX = 0f, float dnX = 0f, bool destroyOnAnimEnd = false, float angle = 0f)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_003f: 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_004b: Expected O, but got Unknown
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			return new DamageEffectData
			{
				m_angle = new MinMaxRange(angle),
				m_object = o,
				m_attach = true,
				m_destroyOnAnimEnd = destroyOnAnimEnd,
				m_detatchOnAnimEnd = !destroyOnAnimEnd,
				m_offsetX = new MinMaxRange(ox),
				m_offsetY = new MinMaxRange(oy),
				m_offsetAimUp = new Vector2(upX, 0f),
				m_offsetAimDown = new Vector2(dnX, 0f),
				m_rotateOffsetX = true
			};
		}

		private static DamageEffectData Fire(GameObject o, float ox, float oy, Vector2 up = default(Vector2), Vector2 dn = default(Vector2))
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: 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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_0026: 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_0032: Expected O, but got Unknown
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: 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_0049: Expected O, but got Unknown
			return new DamageEffectData
			{
				m_object = o,
				m_attach = false,
				m_destroyOnAnimEnd = false,
				m_offsetX = new MinMaxRange(ox),
				m_offsetY = new MinMaxRange(oy),
				m_offsetAimUp = up,
				m_offsetAimDown = dn,
				m_rotateOffsetX = true
			};
		}

		private static List<DamageEffectData> L(params DamageEffectData[] e)
		{
			return new List<DamageEffectData>(e);
		}

		public static void Register()
		{
			WeaponFx.Build();
			Defs.AddRange(Defs2);
			foreach (WeaponDef def in Defs)
			{
				try
				{
					Build(def);
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)("Weapon " + def.id + " failed: " + ex));
				}
			}
			try
			{
				WeaponLooks.Register();
			}
			catch (Exception ex2)
			{
				Plugin.Log.LogError((object)("Weapon in-hand colours failed: " + ex2));
			}
			Plugin.Log.LogInfo((object)("Weapons built: " + Built.Count + "/" + Defs.Count));
		}

		private static void Build(WeaponDef def)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			WeaponHands.Set hands = WeaponHands.For(def.id);
			def.heroFrames = (HeroFrameMap)delegate(exAtlas atlas, int index, out exAtlas outAtlas, out int outIndex)
			{
				WeaponHands.Remap(atlas, index, hands, out outAtlas, out outIndex);
			};
			int unmapped = WeaponHands.Unmapped;
			ItemRegistry.Register(def);
			if (WeaponHands.Unmapped > unmapped)
			{
				Plugin.Log.LogWarning((object)(def.id + ": " + (WeaponHands.Unmapped - unmapped) + " hero frames have no in-hand redraw (vanilla weapon shows)"));
			}
		}

		static WeaponPack()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected O, but got Unknown
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Expected O, but got Unknown
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Expected O, but got Unknown
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Expected O, but got Unknown
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Expected O, but got Unknown
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Expected O, but got Unknown
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Expected O, but got Unknown
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Expected O, but got Unknown
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: Expected O, but got Unknown
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0316: Expected O, but got Unknown
			//IL_031d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Expected O, but got Unknown
			//IL_03c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ca: Expected O, but got Unknown
			//IL_03f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fc: Expected O, but got Unknown
			//IL_0403: Unknown result type (might be due to invalid IL or missing references)
			//IL_0409: Expected O, but got Unknown
			//IL_04a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b0: Expected O, but got Unknown
			//IL_04d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e2: Expected O, but got Unknown
			//IL_051c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0526: Expected O, but got Unknown
			//IL_052d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0533: Expected O, but got Unknown
			//IL_05d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05da: Expected O, but got Unknown
			//IL_0602: Unknown result type (might be due to invalid IL or missing references)
			//IL_060c: Expected O, but got Unknown
			//IL_0634: Unknown result type (might be due to invalid IL or missing references)
			//IL_063e: Expected O, but got Unknown
			//IL_0645: Unknown result type (might be due to invalid IL or missing references)
			//IL_064b: Expected O, but got Unknown
			//IL_06e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f2: Expected O, but got Unknown
			//IL_06f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ff: Expected O, but got Unknown
			//IL_07ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_07b7: Expected O, but got Unknown
			//IL_07be: Unknown result type (might be due to invalid IL or missing references)
			//IL_07c4: Expected O, but got Unknown
			//IL_0872: Unknown result type (might be due to invalid IL or missing references)
			//IL_087c: Expected O, but got Unknown
			//IL_0883: Unknown result type (might be due to invalid IL or missing references)
			//IL_0889: Expected O, but got Unknown
			//IL_0926: Unknown result type (might be due to invalid IL or missing references)
			//IL_0930: Expected O, but got Unknown
			//IL_0958: Unknown result type (might be due to invalid IL or missing references)
			//IL_0962: Expected O, but got Unknown
			//IL_0975: Unknown result type (might be due to invalid IL or missing references)
			//IL_097b: Expected O, but got Unknown
			//IL_0a18: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a22: Expected O, but got Unknown
			//IL_0a4a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a54: Expected O, but got Unknown
			//IL_0a7c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a86: Expected O, but got Unknown
			//IL_0a8d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a93: Expected O, but got Unknown
			//IL_0b30: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b3a: Expected O, but got Unknown
			//IL_0b62: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b6c: Expected O, but got Unknown
			//IL_0b94: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b9e: Expected O, but got Unknown
			//IL_0ba5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bab: Expected O, but got Unknown
			//IL_0c48: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c52: Expected O, but got Unknown
			//IL_0c7a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c84: Expected O, but got Unknown
			//IL_0cbd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cc7: Expected O, but got Unknown
			//IL_0cce: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cd4: Expected O, but got Unknown
			//IL_0d82: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d8c: Expected O, but got Unknown
			//IL_0d93: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d99: Expected O, but got Unknown
			//IL_0e36: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e40: Expected O, but got Unknown
			//IL_0e47: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e4d: Expected O, but got Unknown
			//IL_0eea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ef4: Expected O, but got Unknown
			//IL_0f1c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f26: Expected O, but got Unknown
			//IL_0f2d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f33: Expected O, but got Unknown
			//IL_0fd0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0fda: Expected O, but got Unknown
			//IL_0fe1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0fe7: Expected O, but got Unknown
			//IL_1084: Unknown result type (might be due to invalid IL or missing references)
			//IL_108e: Expected O, but got Unknown
			//IL_10b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_10c0: Expected O, but got Unknown
			//IL_10e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_10f2: Expected O, but got Unknown
			//IL_10f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_10ff: Expected O, but got Unknown
			//IL_11ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_11b7: Expected O, but got Unknown
			//IL_11be: Unknown result type (might be due to invalid IL or missing references)
			//IL_11c4: Expected O, but got Unknown
			//IL_1283: Unknown result type (might be due to invalid IL or missing references)
			//IL_128d: Expected O, but got Unknown
			//IL_1294: Unknown result type (might be due to invalid IL or missing references)
			//IL_129a: Expected O, but got Unknown
			//IL_1326: Unknown result type (might be due to invalid IL or missing references)
			//IL_1330: Expected O, but got Unknown
			//IL_1358: Unknown result type (might be due to invalid IL or missing references)
			//IL_1362: Expected O, but got Unknown
			//IL_1369: Unknown result type (might be due to invalid IL or missing references)
			//IL_136f: Expected O, but got Unknown
			//IL_13fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_1405: Expected O, but got Unknown
			//IL_142d: Unknown result type (might be due to invalid IL or missing references)
			//IL_1437: Expected O, but got Unknown
			//IL_143e: Unknown result type (might be due to invalid IL or missing references)
			//IL_1444: Expected O, but got Unknown
			//IL_14e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_14eb: Expected O, but got Unknown
			//IL_1513: Unknown result type (might be due to invalid IL or missing references)
			//IL_151d: Expected O, but got Unknown
			//IL_1524: Unknown result type (might be due to invalid IL or missing references)
			//IL_152a: Expected O, but got Unknown
			//IL_15c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_15d1: Expected O, but got Unknown
			//IL_15f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_1603: Expected O, but got Unknown
			//IL_162b: Unknown result type (might be due to invalid IL or missing references)
			//IL_1635: Expected O, but got Unknown
			//IL_163c: Unknown result type (might be due to invalid IL or missing references)
			//IL_1642: Expected O, but got Unknown
			//IL_16df: Unknown result type (might be due to invalid IL or missing references)
			//IL_16e9: Expected O, but got Unknown
			//IL_1711: Unknown result type (might be due to invalid IL or missing references)
			//IL_171b: Expected O, but got Unknown
			//IL_1743: Unknown result type (might be due to invalid IL or missing references)
			//IL_174d: Expected O, but got Unknown
			List<WeaponDef> list = new List<WeaponDef>();
			List<WeaponDef> list2 = list;
			WeaponDef val = new WeaponDef();
			val.id = "Gravehook";
			val.name = "Gravehook";
			val.family = "Tether";
			val.baseWeapon = "WeaponSpear";
			val.baseCombo = 1;
			val.cost = 85f;
			val.damageMult = 0.95f;
			val.comboCooldown = 0.4f;
			val.description = "Jab, then hook a monster and drag it to you";
			val.effects = () => L(Melee(WeaponFx.HookJab, 14f, 2f, 3f, 3f), Fire(WeaponFx.Hook, 0f, -2f));
			val.attacks.Add(new WeaponAttack(0, 0.33f, 1f, new object[2] { "a1", 0 }));
			val.attacks.Add(new WeaponAttack(1, 0.4f, 0.95f, new object[2] { "a1", 0 }));
			val.attacks.Add(new WeaponAttack(5, 0.55f, 1.1f, new object[2] { "a0", 1 }));
			list2.Add(val);
			List<WeaponDef> list3 = list;
			val = new WeaponDef();
			val.id = "Moonglaive";
			val.name = "Moonglaive";
			val.family = "Returning";
			val.baseWeapon = "WeaponThrowingKnives";
			val.baseCombo = 0;
			val.cost = 70f;
			val.damageMult = 1f;
			val.comboCooldown = 0.3f;
			val.description = "Slash, then throw a glaive that comes back to you";
			val.effects = () => L(Melee(WeaponFx.GlaiveSlash, 0f, -1f, 2f, 2f), Fire(WeaponFx.Glaive, 6f, -2f));
			val.attacks.Add(new WeaponAttack(0, 0.35f, 1f, new object[2] { "a1", 0 }));
			val.attacks.Add(new WeaponAttack(1, 0.45f, 1f, new object[2] { "a0", 1 }));
			list3.Add(val);
			List<WeaponDef> list4 = list;
			val = new WeaponDef();
			val.id = "Riftblade";
			val.name = "Riftblade";
			val.family = "Rift";
			val.baseWeapon = "Weapon1HandedSword";
			val.baseCombo = 1;
			val.cost = 60f;
			val.damageMult = 0.75f;
			val.comboCooldown = 0.35f;
			val.description = "Quick cuts open a rift that snaps shut on your foes";
			val.effects = () => L(Melee(WeaponFx.RiftSlashA, 0f, 0f, 3f, 2f), Melee(WeaponFx.RiftSlashB, 0f, 0f, 4f, 3f));
			val.attacks.Add(new WeaponAttack(0, 0.3f, 0.9f, new object[2] { "a1", 0 }));
			val.attacks.Add(new WeaponAttack(1, 0.34f, 0.9f, new object[2] { "a0", 1 }));
			val.attacks.Add(new WeaponAttack(2, 0.36f, 0.95f, new object[2] { "a1", 0 }));
			list4.Add(val);
			List<WeaponDef> list5 = list;
			val = new WeaponDef();
			val.id = "SnakeEyes";
			val.name = "Snake-Eyes";
			val.family = "Chance";
			val.baseWeapon = "WeaponClub";
			val.baseCombo = 0;
			val.cost = 45f;
			val.damageMult = 1.1f;
			val.comboCooldown = 0.25f;
			val.description = "Every blow rolls a die. Roll high to hit hard";
			val.effects = () => L(Melee(WeaponFx.DiceSwing, 0f, -1f, 3f, 6f));
			val.attacks.Add(new WeaponAttack(0, 0.55f, 1f, new object[2] { "a1", 0 }));
			val.attacks.Add(new WeaponAttack(2, 0.45f, 1f, new object[2] { "a0", 0 }));
			list5.Add(val);
			List<WeaponDef> list6 = list;
			val = new WeaponDef();
			val.id = "Tidebreaker";
			val.name = "Tidebreaker";
			val.family = "Tide";
			val.baseWeapon = "Weapon2HandedSword";
			val.baseCombo = 1;
			val.cost = 90f;
			val.damageMult = 0.92f;
			val.comboCooldown = 0.35f;
			val.description = "Every third swing sends a wave that sweeps monsters away";
			val.effects = () => L(Melee(WeaponFx.TideCleave, 4f, 0f), Melee(WeaponFx.TideCrash, 0f, 1f), Fire(WeaponFx.Wave, 10f, -4f));
			val.attacks.Add(new WeaponAttack(4, 0.32f, 1f, new object[2] { "a1", 0 }));
			val.attacks.Add(new WeaponAttack(2, 0.39f, 1f, new object[2] { "a1", 0 }));
			val.attacks.Add(new WeaponAttack(9, 0.45f, 1.05f, new object[4] { "a12", 1, "a16", 2 }));
			list6.Add(val);
			List<WeaponDef> list7 = list;
			val = new WeaponDef();
			val.id = "Leechfang";
			val.name = "Leechfang";
			val.family = "Siphon";
			val.baseWeapon = "WeaponDagger";
			val.baseCombo = 2;
			val.cost = 55f;
			val.damageMult = 0.95f;
			val.comboCooldown = 0.2f;
			val.description = "Fast stabs that bleed foes and heal you";
			val.effects = () => L(Melee(WeaponFx.LeechStab, 5f, 0f, 5f, 5f), Melee(WeaponFx.LeechSlash, 0f, 0f, 5f, 2f));
			val.attacks.Add(new WeaponAttack(2, 0.29f, 1f, new object[2] { "a0", 1 }));
			val.attacks.Add(new WeaponAttack(3, 0.29f, 1f, new object[2] { "a2", 0 }));
			val.attacks.Add(new WeaponAttack(4, 0.3f, 1f, new object[2] { "a3", 1 }));
			list7.Add(val);
			List<WeaponDef> list8 = list;
			val = new WeaponDef();
			val.id = "Briarbow";
			val.name = "Briarbow";
			val.family = "Seed";
			val.baseWeapon = "WeaponBow";
			val.baseCombo = 0;
			val.cost = 65f;
			val.damageMult = 1f;
			val.comboCooldown = 0f;
			val.description = "Arrows plant thorny briars where they land";
			val.effects = () => L(Fire(WeaponFx.BriarArrow, 0f, -2f));
			val.attacks.Add(new WeaponAttack(0, 1f, 1f, new object[2] { "a0", 0 }));
			list8.Add(val);
			List<WeaponDef> list9 = list;
			val = new WeaponDef();
			val.id = "DirgeMaul";
			val.name = "Dirge Maul";
			val.family = "Bell";
			val.baseWeapon = "WeaponBattleAxe";
			val.baseCombo = 0;
			val.cost = 80f;
			val.damageMult = 1.55f;
			val.comboCooldown = 0f;
			val.description = "Each slam rings a bell that stuns nearby monsters";
			val.effects = () => L(Melee(WeaponFx.BellHit, 2f, -9f, 0f, 0f, destroyOnAnimEnd: true), Fire(WeaponFx.BellRing, 18f, -10f, new Vector2(0f, -8f), new Vector2(0f, 8f)));
			val.attacks.Add(new WeaponAttack(0, 1.1f, 1f, new object[4] { "a3", 0, "a2", 1 }));
			list9.Add(val);
			List<WeaponDef> list10 = list;
			val = new WeaponDef();
			val.id = "Wickstaff";
			val.name = "Wickstaff";
			val.family = "Lantern";
			val.baseWeapon = "WeaponMagicStaff";
			val.baseCombo = -1;
			val.cost = 85f;
			val.damageMult = 1f;
			val.comboCooldown = 0f;
			val.description = "Lantern bolts leave soul fire that spawns seeking wisps";
			val.effects = () => L(Melee(WeaponFx.LanternSwing, 0f, 1f), Fire(WeaponFx.SoulBolt, 4f, -2f));
			val.attacks.Add(new WeaponAttack(0, 1.1f, 1f, new object[4] { "a0", 0, "mprj", 1 }));
			list10.Add(val);
			List<WeaponDef> list11 = list;
			val = new WeaponDef();
			val.id = "Arcbolt";
			val.name = "Arcbolt";
			val.family = "Storm";
			val.baseWeapon = "WeaponCrossbow";
			val.baseCombo = 1;
			val.cost = 75f;
			val.damageMult = 1f;
			val.comboCooldown = 0.5f;
			val.description = "Bolts that arc lightning between foes";
			val.effects = () => L(Fire(WeaponFx.ArcBolt, 5f, 0f));
			val.attacks.Add(new WeaponAttack(0, 0.6f, 1f, new object[2] { "a1", 0 }));
			val.attacks.Add(new WeaponAttack(1, 0.6f, 1f, new object[2] { "a1", 0 }));
			list11.Add(val);
			Defs = list;
			list = new List<WeaponDef>();
			List<WeaponDef> list12 = list;
			val = new WeaponDef();
			val.id = "Frostbrand";
			val.name = "Frostbrand";
			val.family = "Frost";
			val.baseWeapon = "Weapon1HandedSword";
			val.baseCombo = 1;
			val.cost = 60f;
			val.damageMult = 0.7f;
			val.comboCooldown = 0.3f;
			val.description = "Chilling cuts that slow, then shatter frozen foes";
			val.effects = () => L(Melee(WeaponFx.FrostSlash, 0f, 0f, 3f, 2f));
			val.attacks.Add(new WeaponAttack(3, 0.46f, 1f, new object[2] { "a3", 0 }));
			val.attacks.Add(new WeaponAttack(4, 0.28f, 1f, new object[2] { "a2", 0 }));
			val.attacks.Add(new WeaponAttack(5, 0.2f, 1f, new object[2] { "a3", 0 }));
			list12.Add(val);
			List<WeaponDef> list13 = list;
			val = new WeaponDef();
			val.id = "Mercyblade";
			val.name = "Mercyblade";
			val.family = "Execute";
			val.baseWeapon = "Weapon1HandedSword";
			val.baseCombo = 0;
			val.cost = 50f;
			val.damageMult = 0.75f;
			val.comboCooldown = 0.3f;
			val.description = "Strikes twice against badly hurt foes";
			val.effects = () => L(Melee(WeaponFx.MercySlash, 0f, 0f, 4f, 3f));
			val.attacks.Add(new WeaponAttack(0, 0.33f, 1f, new object[2] { "a1", 0 }));
			val.attacks.Add(new WeaponAttack(1, 0.38f, 1f, new object[2] { "a0", 0 }));
			val.attacks.Add(new WeaponAttack(2, 0.36f, 1f, new object[2] { "a1", 0 }));
			list13.Add(val);
			List<WeaponDef> list14 = list;
			val = new WeaponDef();
			val.id = "Reaper";
			val.name = "Reaper";
			val.family = "Harvest";
			val.baseWeapon = "Weapon2HandedSword";
			val.baseCombo = 2;
			val.cost = 90f;
			val.damageMult = 0.8f;
			val.comboCooldown = 0.35f;
			val.description = "Each kill sharpens the scythe, until you are hit";
			val.effects = () => L(Melee(WeaponFx.ReapA, 4f, 0f), Melee(WeaponFx.ReapB, 0f, 1f, 0f, 0f, destroyOnAnimEnd: false, 15f), Melee(WeaponFx.ReapB, 0f, 1f, 0f, 0f, destroyOnAnimEnd: false, -15f));
			val.attacks.Add(new WeaponAttack(4, 0.3f, 1f, new object[2] { "a1", 0 }));
			val.attacks.Add(new WeaponAttack(1, 0.32f, 1f, new object[2] { "a1", 0 }));
			val.attacks.Add(new WeaponAttack(6, 0.48f, 1f, new object[4] { "a9", 1, "a10", 2 }));
			list14.Add(val);
			List<WeaponDef> list15 = list;
			val = new WeaponDef();
			val.id = "Starfall";
			val.name = "Starfall Maul";
			val.family = "Gravity";
			val.baseWeapon = "WeaponBattleAxe";
			val.baseCombo = 0;
			val.cost = 85f;
			val.damageMult = 1.45f;
			val.comboCooldown = 0f;
			val.description = "Slams open a star well that drags foes in";
			val.effects = () => L(Melee(WeaponFx.StarSlam, 2f, -9f, 0f, 0f, destroyOnAnimEnd: true), Fire(WeaponFx.StarWell, 18f, -10f, new Vector2(0f, -8f), new Vector2(0f, 8f)));
			val.attacks.Add(new WeaponAttack(0, 1.1f, 1f, new object[4] { "a3", 0, "a2", 1 }));
			list15.Add(val);
			List<WeaponDef> list16 = list;
			val = new WeaponDef();
			val.id = "HydraBow";
			val.name = "Hydra Bow";
			val.family = "Split";
			val.baseWeapon = "WeaponBow";
			val.baseCombo = 0;
			val.cost = 70f;
			val.damageMult = 1f;
			val.comboCooldown = 0f;
			val.description = "Arrows that split into three fangs";
			val.effects = () => L(Fire(WeaponFx.HydraArrow, 0f, -2f));
			val.attacks.Add(new WeaponAttack(0, 1f, 1f, new object[2] { "a0", 0 }));
			list16.Add(val);
			List<WeaponDef> list17 = list;
			val = new WeaponDef();
			val.id = "Bulwark";
			val.name = "Bulwark Mace";
			val.family = "Guard";
			val.baseWeapon = "WeaponClub";
			val.baseCombo = 0;
			val.cost = 50f;
			val.damageMult = 1.15f;
			val.comboCooldown = 0.3f;
			val.description = "Every third hit raises a ward that blocks a blow";
			val.effects = () => L(Melee(WeaponFx.GuardBash, 0f, -1f, 3f, 6f));
			val.attacks.Add(new WeaponAttack(1, 0.39f, 1f, new object[2] { "a1", 0 }));
			val.attacks.Add(new WeaponAttack(6, 0.46f, 1f, new object[2] { "a1", 0 }));
			list17.Add(val);
			List<WeaponDef> list18 = list;
			val = new WeaponDef();
			val.id = "Heartseeker";
			val.name = "Heartseeker";
			val.family = "Pierce";
			val.baseWeapon = "WeaponCrossbow";
			val.baseCombo = 0;
			val.cost = 70f;
			val.damageMult = 1f;
			val.comboCooldown = 1.3f;
			val.description = "Heavy bolts that pierce through foes, hitting harder as they go";
			val.effects = () => L(Fire(WeaponFx.HeartBolt, 5f, 0f));
			val.attacks.Add(new WeaponAttack(3, 0.7f, 1f, new object[2] { "a0", 0 }));
			list18.Add(val);
			List<WeaponDef> list19 = list;
			val = new WeaponDef();
			val.id = "Kris";
			val.name = "Shadow Kris";
			val.family = "Backstab";
			val.baseWeapon = "WeaponDagger";
			val.baseCombo = 0;
			val.cost = 50f;
			val.damageMult = 0.7f;
			val.comboCooldown = 0.2f;
			val.description = "Quick stabs that hit harder from behind";
			val.effects = () => L(Melee(WeaponFx.KrisStab, 5f, 0f, 5f, 5f));
			val.attacks.Add(new WeaponAttack(0, 0.27f, 1f, new object[2] { "a1", 0 }));
			val.attacks.Add(new WeaponAttack(1, 0.32f, 1f, new object[2] { "a1", 0 }));
			val.attacks.Add(new WeaponAttack(2, 0.31f, 1f, new object[2] { "a0", 0 }));
			list19.Add(val);
			List<WeaponDef> list20 = list;
			val = new WeaponDef();
			val.id = "Blightstaff";
			val.name = "Blightstaff";
			val.family = "Contagion";
			val.baseWeapon = "WeaponMagicStaff";
			val.baseCombo = -1;
			val.cost = 80f;
			val.damageMult = 1f;
			val.comboCooldown = 0f;
			val.description = "Plague bolts that spread sickness from foe to foe";
			val.effects = () => L(Melee(WeaponFx.BlightSwing, 0f, 1f), Fire(WeaponFx.BlightBolt, 4f, -2f));
			val.attacks.Add(new WeaponAttack(0, 1.1f, 1f, new object[4] { "a0", 0, "mprj", 1 }));
			list20.Add(val);
			List<WeaponDef> list21 = list;
			val = new WeaponDef();
			val.id = "Orrery";
			val.name = "Orrery Staff";
			val.family = "Orbit";
			val.baseWeapon = "WeaponMagicStaff";
			val.baseCombo = -1;
			val.cost = 80f;
			val.damageMult = 1f;
			val.comboCooldown = 0f;
			val.description = "Shoots star bolts and gathers stars that circle you";
			val.effects = () => L(Melee(WeaponFx.OrrerySwing, 0f, 1f), Fire(WeaponFx.OrreryBolt, 4f, -2f), Fire(WeaponFx.OrreryStar, 0f, -2f));
			val.attacks.Add(new WeaponAttack(0, 1.1f, 1f, new object[6] { "a0", 0, "mprj", 1, "msmn1", 2 }));
			list21.Add(val);
			List<WeaponDef> list22 = list;
			val = new WeaponDef();
			val.id = "Grudgestone";
			val.name = "Grudgestone";
			val.family = "Vendetta";
			val.baseWeapon = "WeaponSling";
			val.baseCombo = 0;
			val.cost = 35f;
			val.damageMult = 1f;
			val.comboCooldown = 0f;
			val.description = "Stones seek out the last monster that hurt you";
			val.effects = () => L(Fire(WeaponFx.GrudgeStone, 0f, -9f));
			val.attacks.Add(new WeaponAttack(0, 0.3f, 1f, new object[0]));
			val.attacks.Add(new WeaponAttack(1, 0.86f, 1f, new object[2] { "a0", 0 }));
			list22.Add(val);
			List<WeaponDef> list23 = list;
			val = new WeaponDef();
			val.id = "Midas";
			val.name = "Midas Sling";
			val.family = "Wealth";
			val.baseWeapon = "WeaponSling";
			val.baseCombo = 0;
			val.cost = 40f;
			val.damageMult = 1f;
			val.comboCooldown = 0f;
			val.description = "Throws coins that hit harder the richer you are";
			val.effects = () => L(Fire(WeaponFx.MidasCoin, 0f, -9f));
			val.attacks.Add(new WeaponAttack(0, 0.3f, 1f, new object[0]));
			val.attacks.Add(new WeaponAttack(1, 0.86f, 1f, new object[2] { "a0", 0 }));
			list23.Add(val);
			List<WeaponDef> list24 = list;
			val = new WeaponDef();
			val.id = "Lance";
			val.name = "Charger Lance";
			val.family = "Momentum";
			val.baseWeapon = "WeaponSpear";
			val.baseCombo = 0;
			val.cost = 80f;
			val.damageMult = 1f;
			val.comboCooldown = 0.3f;
			val.description = "Run, then charge to bowl monsters over";
			val.effects = () => L(Melee(WeaponFx.LanceThrust, 14f, 2f, 3f, 3f));
			val.attacks.Add(new WeaponAttack(0, 0.35f, 1f, new object[2] { "a1", 0 }));
			val.attacks.Add(new WeaponAttack(1, 0.46f, 1f, new object[2] { "a1", 0 }));
			list24.Add(val);
			List<WeaponDef> list25 = list;
			val = new WeaponDef();
			val.id = "Lash";
			val.name = "Viper Lash";
			val.family = "Sweet spot";
			val.baseWeapon = "WeaponThrowingKnives";
			val.baseCombo = 0;
			val.cost = 65f;
			val.damageMult = 1f;
			val.comboCooldown = 0.3f;
			val.description = "A long whip. Its tip cracks hardest";
			val.effects = () => L(Melee(WeaponFx.LashBody, 0f, -1f, 2f, 2f));
			val.attacks.Add(new WeaponAttack(0, 0.35f, 1f, new object[2] { "a1", 0 }));
			val.attacks.Add(new WeaponAttack(2, 0.35f, 1f, new object[2] { "a0", 0 }));
			val.attacks.Add(new WeaponAttack(3, 0.45f, 1f, new object[2] { "a2", 0 }));
			list25.Add(val);
			List<WeaponDef> list26 = list;
			val = new WeaponDef();
			val.id = "Kunai";
			val.name = "Hunter's Kunai";
			val.family = "Mark";
			val.baseWeapon = "WeaponThrowingKnives";
			val.baseCombo = 1;
			val.cost = 65f;
			val.damageMult = 1f;
			val.comboCooldown = 0.4f;
			val.description = "Throw a kunai to mark a foe, then slash it for extra damage";
			val.effects = () => L(Fire(WeaponFx.Kunai, 0f, -2f), Melee(WeaponFx.KunaiSlash, 0f, -1f, 2f, 2f));
			val.attacks.Add(new WeaponAttack(1, 0.35f, 1f, new object[2] { "a0", 0 }));
			val.attacks.Add(new WeaponAttack(3, 0.45f, 1f, new object[2] { "a2", 1 }));
			val.attacks.Add(new WeaponAttack(4, 0.25f, 1f, new object[2] { "a3", 1 }));
			list26.Add(val);
			Defs2 = list;
		}
	}
	public class WeaponRuntime : MonoBehaviour
	{
		public int leechHits;

		public int bellSlams;

		public int reapStacks;

		public int guardHits;

		public float guardUntil;

		public float runTime;

		public float idleTime;

		public float grudgeTime;

		public GameObject grudge;

		public GameObject guardFx;

		private GameObject m_grudgeShown;

		public ValueModifierStack guardMod;

		public readonly List<GameObject> stars = new List<GameObject>();

		private PlayerMovement m_move;

		private GameObject m_readyFx;

		private int m_reapShown;

		private static StatusOverlayDef[] s_reapInd;

		private static StatusOverlayDef s_grudgeInd;

		public bool GuardUp => Time.time <= guardUntil;

		private static void BuildInd()
		{
			if (s_reapInd == null)
			{
				s_reapInd = (StatusOverlayDef[])(object)new StatusOverlayDef[5];
				for (int i = 0; i < s_reapInd.Length; i++)
				{
					s_reapInd[i] = ModStatus.Indicator("ModIndWpnReap" + (i + 1), "FxWpnReaperStacks", "Stacks" + (i + 1), 0f, (OverlayAt)0, false);
				}
				s_grudgeInd = ModStatus.Indicator("ModIndWpnGrudge", "FxWpnGrudgestone", "Grudge", -6f, (OverlayAt)0, false);
			}
		}

		private void BrandGrudge(GameObject on)
		{
			BuildInd();
			if (!((Object)(object)m_grudgeShown == (Object)(object)on))
			{
				if ((Object)(object)m_grudgeShown != (Object)null)
				{
					ModInd.Set(m_grudgeShown, s_grudgeInd, false, 0f);
				}
				m_grudgeShown = on;
				if ((Object)(object)on != (Object)null)
				{
					ModInd.Set(on, s_grudgeInd, true, 0f);
				}
			}
		}

		public string HeldId()
		{
			PlayerData heroPlayerData = SystemPlayers.GetHeroPlayerData();
			if (heroPlayerData == null || (Object)(object)heroPlayerData.GameObject != (Object)(object)((Component)this).gameObject || heroPlayerData.GameData == null)
			{
				return null;
			}
			Weapon val = heroPlayerData.GameData.GetWeaponData()?.m_weapon;
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			string name = ((Object)((Component)val).gameObject).name;
			if (!name.StartsWith("ModWeapon", StringComparison.Ordinal))
			{
				return null;
			}
			return name.Substring(9);
		}

		public static void EnsureOnHero(Component c)
		{
			GameObject val = ModUtil.Hero();
			if (!((Object)(object)val == (Object)null) && !((Object)(object)c == (Object)null) && (!((Object)(object)c.gameObject != (Object)(object)val) || c.transform.IsChildOf(val.transform)) && (Object)(object)val.GetComponent<WeaponRuntime>() == (Object)null)
			{
				val.AddComponent<WeaponRuntime>();
			}
		}

		private void UpdateIndicators()
		{
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			string text = HeldId();
			int num = ((text == "Reaper") ? Mathf.Clamp(reapStacks, 0, 5) : 0);
			if (num != m_reapShown || num > 0)
			{
				BuildInd();
				ModInd.Count(((Component)this).gameObject, s_reapInd, num);
				m_reapShown = num;
			}
			bool flag = text == "Lance" && runTime >= 0.5f;
			if (flag && (Object)(object)WeaponFx.LanceReady != (Object)null && !WpnFollowFx.Follows(m_readyFx, ((Component)this).gameObject))
			{
				m_readyFx = WpnFollowFx.Attach(WeaponFx.LanceReady, ((Component)this).gameObject, new Vector2(0f, 1f));
			}
			else if (!flag && (Object)(object)m_readyFx != (Object)null)
			{
				WpnFollowFx.Drop(m_readyFx, ((Component)this).gameObject);
				m_readyFx = null;
			}
			if ((Object)(object)m_grudgeShown != (Object)null && text != "Grudgestone")
			{
				BrandGrudge(null);
			}
		}

		private void Update()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)m_move == (Object)null)
			{
				m_move = ((Component)this).GetComponent<PlayerMovement>();
			}
			if ((Object)(object)m_move != (Object)null)
			{
				Vector2 velocity = m_move.GetVelocity();
				if (((Vector2)(ref velocity)).magnitude >= m_move.GetSpeedMax() * 0.6f)
				{
					runTime += Time.deltaTime;
					idleTime = 0f;
				}
				else if ((idleTime += Time.deltaTime) > 0.3f)
				{
					runTime = 0f;
				}
			}
			if ((Object)(object)guardFx != (Object)null && (Time.time > guardUntil || !guardFx.activeInHierarchy))
			{
				if (guardFx.activeInHierarchy)
				{
					SystemPool.Despawn(guardFx);
				}
				guardFx = null;
			}
			if ((Object)(object)grudge != (Object)null && (Time.time - grudgeTime > 8f || !WpnUtil.Alive(grudge)))
			{
				ClearGrudge();
			}
			UpdateIndicators();
		}

		public void RaiseGuard(ValueModifierStack mod)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			guardUntil = Time.time + 5f;
			guardMod = mod;
			guardFx = WpnFollowFx.Refresh(guardFx, WeaponFx.GuardRing, ((Component)this).gameObject, new Vector2(0f, 8f));
		}

		public void Block(GameObject attacker)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: U

plugins/CrawlFurther/CrawlFurther.Core.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using CrawlFurther.Art;
using CrawlFurther.Compat;
using CrawlFurther.Diagnostics;
using CrawlFurther.Game;
using CrawlFurther.Ghosts;
using CrawlFurther.Gods;
using CrawlFurther.Heroes;
using CrawlFurther.Items;
using CrawlFurther.Monsters;
using CrawlFurther.Objects;
using CrawlFurther.Testing;
using CrawlFurther.UI;
using CrawlFurther.Util;
using HarmonyLib;
using InControl;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace CrawlFurther
{
	internal static class ContentManager
	{
		internal static string Status = "waiting for game systems";

		private static int s_tries;

		private static readonly List<KeyValuePair<string, Action>> s_packs = new List<KeyValuePair<string, Action>>();

		internal static readonly List<string> FailedPacks = new List<string>();

		internal static bool Registered { get; private set; }

		internal static void AddPack(string name, Action register)
		{
			s_packs.Add(new KeyValuePair<string, Action>(name, register));
		}

		internal static void Tick()
		{
			if (Registered || !Singleton<SystemDeity>.HasInstance() || !Singleton<Constants>.HasInstance() || !Singleton<SystemUnlocks>.HasInstance() || SystemDeity.GetDeities() == null || ++s_tries % 30 != 0)
			{
				return;
			}
			if (!MonsterFactory.TryIndexVanilla())
			{
				if (s_tries % 300 == 0)
				{
					FurtherCore.Log.LogInfo((object)"Monster prefabs not loaded yet...");
				}
				return;
			}
			Registered = true;
			KeyValuePair<string, Action>[] array = s_packs.ToArray();
			int num = 0;
			List<string> failedPacks = FailedPacks;
			failedPacks.Clear();
			KeyValuePair<string, Action>[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				KeyValuePair<string, Action> keyValuePair = array2[i];
				try
				{
					keyValuePair.Value();
					num++;
					FurtherCore.Log.LogInfo((object)("Pack registered: " + keyValuePair.Key));
				}
				catch (Exception ex)
				{
					failedPacks.Add(keyValuePair.Key);
					FurtherCore.Log.LogError((object)("Pack " + keyValuePair.Key + " failed: " + ex));
				}
			}
			try
			{
				Strike.KeepAllScales();
			}
			catch (Exception ex2)
			{
				FurtherCore.Log.LogError((object)("KeepAllScales: " + ex2));
			}
			try
			{
				LibraryEntries.Register();
			}
			catch (Exception ex3)
			{
				FurtherCore.Log.LogError((object)("Library entries: " + ex3));
			}
			try
			{
				Statues.Register();
			}
			catch (Exception ex4)
			{
				FurtherCore.Log.LogError((object)("Statues: " + ex4));
			}
			try
			{
				ModInd.Build();
			}
			catch (Exception ex5)
			{
				FurtherCore.Log.LogError((object)("Indicators: " + ex5));
			}
			Status = num + "/" + array.Length + " packs, " + MonsterFactory.Built.Count + " monsters" + ((failedPacks.Count > 0) ? ("  FAILED: " + string.Join(", ", failedPacks.ToArray())) : "");
			FurtherCore.Log.LogInfo((object)Status);
			GameEvents.RaiseGameReady();
			try
			{
				SelfTest.Run();
			}
			catch (Exception ex6)
			{
				FurtherCore.Log.LogError((object)("Self-test crashed: " + ex6));
			}
		}
	}
	[HarmonyPatch(typeof(SystemGame), "OnStartGame")]
	internal static class Patch_EventRunStart
	{
		private static void Postfix()
		{
			ContinueGame.Reset();
			GameEvents.RaiseRunStart();
		}
	}
	[HarmonyPatch(typeof(SystemPlayers), "OnLevelStart")]
	internal static class Patch_EventFloorStart
	{
		private static void Postfix()
		{
			GameEvents.RaiseFloorStart();
		}
	}
	[HarmonyPatch(typeof(SystemLevel), "OnEnteredRoom")]
	internal static class Patch_EventRoomChanged
	{
		private static void Postfix(Room room)
		{
			if (GameEvents.HasRoomChanged)
			{
				GameEvents.RaiseRoomChanged(room);
			}
		}
	}
	[HarmonyPatch(typeof(SystemLevel), "OnMonsterSpawned")]
	internal static class Patch_EventMonsterSpawned
	{
		private static void Postfix(GameObject monster)
		{
			if (GameEvents.HasMonsterSpawned && !((Object)(object)monster == (Object)null))
			{
				Player component = monster.GetComponent<Player>();
				if ((Object)(object)component != (Object)null)
				{
					GameEvents.RaiseMonsterSpawned(component);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Health), "Damage", new Type[]
	{
		typeof(DamageInfo),
		typeof(bool)
	})]
	internal static class Patch_EventHeroDamaged
	{
		private static void Postfix(Health __instance, DamageInfo damage, bool __result)
		{
			if (__result && GameEvents.HasHeroDamaged && (Object)(object)((Component)__instance).gameObject == (Object)(object)ModUtil.Hero())
			{
				GameEvents.RaiseHeroDamaged(damage);
			}
		}
	}
	public static class Further
	{
		private static readonly Dictionary<string, ConfigFile> s_configs = new Dictionary<string, ConfigFile>(StringComparer.OrdinalIgnoreCase);

		public static bool IsReady => ContentManager.Registered;

		public static string Status => ContentManager.Status;

		public static FurtherMod AddMod(BaseUnityPlugin plugin, Action start)
		{
			FurtherMod furtherMod = new FurtherMod(plugin, start);
			FurtherCore.Register(furtherMod);
			return furtherMod;
		}

		public static void AddPack(string name, Action register)
		{
			ContentManager.AddPack(name, register);
		}

		public static ConfigFile Config(string fileName)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			//IL_0048: Expected O, but got Unknown
			if (!fileName.EndsWith(".cfg", StringComparison.OrdinalIgnoreCase))
			{
				fileName += ".cfg";
			}
			if (!s_configs.TryGetValue(fileName, out var value))
			{
				Dictionary<string, ConfigFile> dictionary = s_configs;
				string key = fileName;
				ConfigFile val = new ConfigFile(Path.Combine(Paths.ConfigPath, fileName), true);
				value = val;
				dictionary[key] = val;
			}
			return value;
		}
	}
	[BepInPlugin("com.firefightermate.crawlfurther.core", "Crawl Further Core", "1.2.1")]
	public class FurtherCore : BaseUnityPlugin
	{
		public const string GUID = "com.firefightermate.crawlfurther.core";

		public const string NAME = "Crawl Further Core";

		public const string VERSION = "1.2.1";

		internal static ManualLogSource Log;

		internal static string ModDir;

		internal static readonly List<string> FailedStarts = new List<string>();

		internal static readonly List<string> FailedPatches = new List<string>();

		private static readonly List<FurtherMod> s_mods = new List<FurtherMod>();

		private bool m_started;

		private int m_frames;

		private static readonly string[] PatchOrder = new string[40]
		{
			"Patch_StrikeSpawnOffset", "Patch_ObjectsGameStart", "Patch_ObjectsHeroChange", "Patch_ObjectsTrapEnter", "Patch_TipsInitAsPlayer", "Patch_TipsTrap", "Patch_StatusAdd", "Patch_StatusRemove", "Patch_UnlockEcto", "Patch_HeroGearInitAsPlayer",
			"Patch_PlayerAwake", "Patch_HealthDamage", "Patch_SpawnEffectEcho", "Patch_PlayerDataSetDeity", "Patch_HeroLooksSetDeity", "Patch_HeroLooksInitAsPlayer", "Patch_HeroLooksRemoveStatus", "Patch_MenuRefresh", "Patch_BrandTitle", "Patch_LibraryCellAction",
			"Patch_LibraryItemText", "Patch_VaultUpdateItem", "Patch_LibraryChallengeStart", "Patch_LibraryChallengeSummary", "Patch_ChallengeNoAchievements", "Patch_VaultCellAction", "Patch_VaultPortraitGem", "Patch_EvolvePanelFonts", "Patch_TestWipeKeys", "Patch_TestPanelMouse",
			"Patch_TestUnlocked", "Patch_TestNoVaultFinds", "Patch_TestNoChallengeScores", "Patch_TestFreezeAI", "Patch_TestFreezeAIMove", "Patch_TestFreezeAIAttack", "Patch_TestFreezeBot", "Patch_TestFreezeBotMove", "Patch_OnlineRehello", "Patch_HeroHandover"
		};

		internal static IEnumerable<Assembly> Assemblies
		{
			get
			{
				yield return typeof(FurtherCore).Assembly;
				foreach (FurtherMod s_mod in s_mods)
				{
					yield return s_mod.Assembly;
				}
			}
		}

		internal static void Register(FurtherMod mod)
		{
			s_mods.Add(mod);
		}

		internal static bool IsOurHarmonyId(string id)
		{
			if (id == "com.firefightermate.crawlfurther.core")
			{
				return true;
			}
			foreach (FurtherMod s_mod in s_mods)
			{
				if (s_mod.Id == id)
				{
					return true;
				}
			}
			return false;
		}

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			((MonoBehaviour)this).useGUILayout = false;
			ModDir = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
			Log.LogInfo((object)("Crawl Further Core awake. Unity " + Application.unityVersion + ", dir " + ModDir));
		}

		private void Update()
		{
			if (!m_started)
			{
				if (++m_frames >= 10)
				{
					m_started = true;
					StartGameHooks();
				}
			}
			else
			{
				GameTick();
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private void StartGameHooks()
		{
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Expected O, but got Unknown
			SpriteSheets.AddFolder(ModDir);
			TestMode.Start();
			FailedStarts.Clear();
			foreach (FurtherMod s_mod in s_mods)
			{
				SpriteSheets.AddFolder(s_mod.Dir);
				try
				{
					if (s_mod.Start != null)
					{
						s_mod.Start();
					}
				}
				catch (Exception ex)
				{
					FailedStarts.Add(s_mod.Id + ": " + ex.GetType().Name + " " + ex.Message);
					Log.LogError((object)("Starting " + s_mod.Id + " failed: " + ex));
				}
			}
			PatchAll(typeof(FurtherCore).Assembly, new Harmony("com.firefightermate.crawlfurther.core"), PatchOrder, Log);
		}

		internal static void PatchAll(Assembly assembly, Harmony harmony, IList<string> order, ManualLogSource log)
		{
			List<Type> list = new List<Type>();
			Type[] types = assembly.GetTypes();
			foreach (Type type in types)
			{
				if (type.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Length != 0)
				{
					list.Add(type);
				}
			}
			Func<Type, int> rank = delegate(Type t)
			{
				int num3 = ((order != null) ? order.IndexOf(t.Name) : (-1));
				return (num3 >= 0) ? num3 : int.MaxValue;
			};
			list.Sort(delegate(Type a, Type b)
			{
				int num3 = rank(a);
				int num4 = rank(b);
				return (num3 == num4) ? string.CompareOrdinal(a.FullName, b.FullName) : num3.CompareTo(num4);
			});
			int num = 0;
			int num2 = 0;
			foreach (Type item in list)
			{
				try
				{
					harmony.CreateClassProcessor(item).Patch();
					num++;
				}
				catch (Exception ex)
				{
					num2++;
					log.LogError((object)("Patch " + item.Name + " failed: " + ex.Message));
					FailedPatches.Add(assembly.GetName().Name + ": " + item.Name + ": " + ex.Message);
				}
			}
			log.LogInfo((object)("Harmony patches applied (" + assembly.GetName().Name + "): " + num + " ok, " + num2 + " failed"));
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private void GameTick()
		{
			ContentManager.Tick();
			DevKeys.Tick();
		}
	}
	public sealed class FurtherMod
	{
		private Harmony m_harmony;

		internal Action Start;

		public string Id { get; private set; }

		public string Name { get; private set; }

		public string Dir { get; private set; }

		public Assembly Assembly { get; private set; }

		public ManualLogSource Log { get; private set; }

		public ConfigFile Config { get; private set; }

		public Harmony Harmony
		{
			get
			{
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: Expected O, but got Unknown
				//IL_001d: Expected O, but got Unknown
				Harmony obj = m_harmony;
				if (obj == null)
				{
					Harmony val = new Harmony(Id);
					Harmony val2 = val;
					m_harmony = val;
					obj = val2;
				}
				return obj;
			}
		}

		internal FurtherMod(BaseUnityPlugin plugin, Action start)
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			BepInPlugin metadata = MetadataHelper.GetMetadata((object)plugin);
			Id = metadata.GUID;
			Name = metadata.Name;
			Assembly = ((object)plugin).GetType().Assembly;
			Dir = Path.GetDirectoryName(Assembly.Location);
			Log = (ManualLogSource)AccessTools.Property(typeof(BaseUnityPlugin), "Logger").GetValue(plugin, null);
			Config = plugin.Config;
			Start = start;
		}

		public void PatchAll(params string[] order)
		{
			FurtherCore.PatchAll(Assembly, Harmony, order, Log);
		}
	}
	public static class GameEvents
	{
		internal static bool HasRoomChanged => GameEvents.RoomChanged != null;

		internal static bool HasMonsterSpawned => GameEvents.MonsterSpawned != null;

		internal static bool HasHeroDamaged => GameEvents.HeroDamaged != null;

		public static event Action GameReady;

		public static event Action RunStart;

		public static event Action FloorStart;

		public static event Action<Room> RoomChanged;

		public static event Action<Player> MonsterSpawned;

		public static event Action<DamageInfo> HeroDamaged;

		public static event Action<int> GameContinued;

		internal static void RaiseGameReady()
		{
			Raise(GameEvents.GameReady, "GameReady");
		}

		internal static void RaiseRunStart()
		{
			Raise(GameEvents.RunStart, "RunStart");
		}

		internal static void RaiseFloorStart()
		{
			Raise(GameEvents.FloorStart, "FloorStart");
		}

		internal static void RaiseRoomChanged(Room room)
		{
			Raise(GameEvents.RoomChanged, room, "RoomChanged");
		}

		internal static void RaiseMonsterSpawned(Player p)
		{
			Raise(GameEvents.MonsterSpawned, p, "MonsterSpawned");
		}

		internal static void RaiseHeroDamaged(DamageInfo d)
		{
			Raise(GameEvents.HeroDamaged, d, "HeroDamaged");
		}

		internal static void RaiseGameContinued(int n)
		{
			Raise(GameEvents.GameContinued, n, "GameContinued");
		}

		private static void Raise(Action handlers, string name)
		{
			if (handlers == null)
			{
				return;
			}
			Delegate[] invocationList = handlers.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				Action action = (Action)invocationList[i];
				try
				{
					action();
				}
				catch (Exception ex)
				{
					FurtherCore.Log.LogError((object)(name + " handler " + Describe(action) + " failed: " + ex));
				}
			}
		}

		private static void Raise<T>(Action<T> handlers, T arg, string name)
		{
			if (handlers == null)
			{
				return;
			}
			Delegate[] invocationList = handlers.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				Action<T> action = (Action<T>)invocationList[i];
				try
				{
					action(arg);
				}
				catch (Exception ex)
				{
					FurtherCore.Log.LogError((object)(name + " handler " + Describe(action) + " failed: " + ex));
				}
			}
		}

		private static string Describe(Delegate d)
		{
			if ((object)d.Method.DeclaringType != null)
			{
				return d.Method.DeclaringType.FullName + "." + d.Method.Name;
			}
			return d.Method.Name;
		}
	}
}
namespace CrawlFurther.Util
{
	public static class MiniJson
	{
		public static object Parse(string s)
		{
			int i = 0;
			return Value(s, ref i);
		}

		public static string Write(object value, bool indent = true)
		{
			StringBuilder stringBuilder = new StringBuilder();
			Write(stringBuilder, value, indent, 0);
			return stringBuilder.ToString();
		}

		private static void Ws(string s, ref int i)
		{
			while (i < s.Length && char.IsWhiteSpace(s[i]))
			{
				i++;
			}
		}

		private static bool At(string s, int i, string word)
		{
			return string.CompareOrdinal(s, i, word, 0, word.Length) == 0;
		}

		private static object Value(string s, ref int i)
		{
			Ws(s, ref i);
			if (i >= s.Length)
			{
				throw new FormatException("unexpected end of JSON");
			}
			char c = s[i];
			switch (c)
			{
			case '{':
				return Obj(s, ref i);
			case '[':
				return Arr(s, ref i);
			case '"':
				return Str(s, ref i);
			default:
			{
				if (At(s, i, "true"))
				{
					i += 4;
					return true;
				}
				if (At(s, i, "false"))
				{
					i += 5;
					return false;
				}
				if (At(s, i, "null"))
				{
					i += 4;
					return null;
				}
				int num = i;
				while (i < s.Length && "+-0123456789.eE".IndexOf(s[i]) >= 0)
				{
					i++;
				}
				if (i == num)
				{
					throw new FormatException("unexpected '" + c + "' at " + i);
				}
				return double.Parse(s.Substring(num, i - num), CultureInfo.InvariantCulture);
			}
			}
		}

		private static Dictionary<string, object> Obj(string s, ref int i)
		{
			Dictionary<string, object> dictionary = new Dictionary<string, object>();
			i++;
			Ws(s, ref i);
			if (s[i] == '}')
			{
				i++;
				return dictionary;
			}
			while (true)
			{
				Ws(s, ref i);
				string key = Str(s, ref i);
				Ws(s, ref i);
				i++;
				dictionary[key] = Value(s, ref i);
				Ws(s, ref i);
				if (s[i] != ',')
				{
					break;
				}
				i++;
			}
			i++;
			return dictionary;
		}

		private static List<object> Arr(string s, ref int i)
		{
			List<object> list = new List<object>();
			i++;
			Ws(s, ref i);
			if (s[i] == ']')
			{
				i++;
				return list;
			}
			while (true)
			{
				list.Add(Value(s, ref i));
				Ws(s, ref i);
				if (s[i] != ',')
				{
					break;
				}
				i++;
			}
			i++;
			return list;
		}

		private static string Str(string s, ref int i)
		{
			StringBuilder stringBuilder = new StringBuilder();
			i++;
			while (s[i] != '"')
			{
				if (s[i] == '\\')
				{
					i++;
					char c = s[i];
					switch (c)
					{
					case 'n':
						stringBuilder.Append('\n');
						break;
					case 't':
						stringBuilder.Append('\t');
						break;
					case 'r':
						stringBuilder.Append('\r');
						break;
					case 'b':
						stringBuilder.Append('\b');
						break;
					case 'f':
						stringBuilder.Append('\f');
						break;
					case 'u':
						stringBuilder.Append((char)Convert.ToInt32(s.Substring(i + 1, 4), 16));
						i += 4;
						break;
					default:
						stringBuilder.Append(c);
						break;
					}
				}
				else
				{
					stringBuilder.Append(s[i]);
				}
				i++;
			}
			i++;
			return stringBuilder.ToString();
		}

		private static void Write(StringBuilder sb, object v, bool indent, int depth)
		{
			if (v == null)
			{
				sb.Append("null");
			}
			else if (v is string || v is Enum || v is char)
			{
				Quote(sb, v.ToString());
			}
			else if (v is bool)
			{
				sb.Append(((bool)v) ? "true" : "false");
			}
			else if (v is float)
			{
				sb.Append(((float)v).ToString("R", CultureInfo.InvariantCulture));
			}
			else if (v is double)
			{
				sb.Append(((double)v).ToString("R", CultureInfo.InvariantCulture));
			}
			else if (v is IConvertible)
			{
				sb.Append(Convert.ToString(v, CultureInfo.InvariantCulture));
			}
			else if (v is IDictionary dictionary)
			{
				sb.Append('{');
				bool flag = true;
				foreach (DictionaryEntry item in dictionary)
				{
					if (!flag)
					{
						sb.Append(',');
					}
					flag = false;
					Break(sb, indent, depth + 1);
					Quote(sb, Convert.ToString(item.Key, CultureInfo.InvariantCulture));
					sb.Append(indent ? ": " : ":");
					Write(sb, item.Value, indent, depth + 1);
				}
				if (!flag)
				{
					Break(sb, indent, depth);
				}
				sb.Append('}');
			}
			else if (v is IEnumerable enumerable)
			{
				bool flag2 = true;
				foreach (object item2 in enumerable)
				{
					if (item2 is string || item2 is Enum || (item2 != null && !(item2 is IConvertible)))
					{
						flag2 = false;
						break;
					}
				}
				sb.Append('[');
				bool flag3 = true;
				foreach (object item3 in enumerable)
				{
					if (!flag3)
					{
						sb.Append((flag2 && indent) ? ", " : ",");
					}
					flag3 = false;
					if (!flag2)
					{
						Break(sb, indent, depth + 1);
					}
					Write(sb, item3, indent, depth + 1);
				}
				if (!flag3 && !flag2)
				{
					Break(sb, indent, depth);
				}
				sb.Append(']');
			}
			else
			{
				Quote(sb, v.ToString());
			}
		}

		private static void Break(StringBuilder sb, bool indent, int depth)
		{
			if (indent)
			{
				sb.Append('\n');
				sb.Append(' ', depth * 2);
			}
		}

		private static void Quote(StringBuilder sb, string s)
		{
			sb.Append('"');
			foreach (char c in s)
			{
				switch (c)
				{
				case '"':
					sb.Append("\\\"");
					continue;
				case '\\':
					sb.Append("\\\\");
					continue;
				case '\n':
					sb.Append("\\n");
					continue;
				case '\r':
					sb.Append("\\r");
					continue;
				case '\t':
					sb.Append("\\t");
					continue;
				}
				if (c < ' ')
				{
					StringBuilder stringBuilder = sb.Append("\\u");
					int num = c;
					stringBuilder.Append(num.ToString("x4"));
				}
				else
				{
					sb.Append(c);
				}
			}
			sb.Append('"');
		}
	}
	public static class ModUtil
	{
		public static readonly Dictionary<string, MonsterTraits> Traits = new Dictionary<string, MonsterTraits>();

		private static readonly FieldRef<Player, bool> s_isGhost = AccessTools.FieldRefAccess<Player, bool>("m_isGhost");

		public static GameObject Hero()
		{
			PlayerData heroPlayerData = SystemPlayers.GetHeroPlayerData();
			if (heroPlayerData == null)
			{
				return null;
			}
			return heroPlayerData.GameObject;
		}

		public static DamageSource HeroSource()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			PlayerData heroPlayerData = SystemPlayers.GetHeroPlayerData();
			if (heroPlayerData == null || !((Object)(object)heroPlayerData.GameObject != (Object)null))
			{
				return null;
			}
			return new DamageSource(heroPlayerData.GameObject, heroPlayerData.GameObject, heroPlayerData);
		}

		public static DamageSource MonsterSource(GameObject body)
		{
			//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_0049: Expected O, but got Unknown
			if ((Object)(object)body == (Object)null)
			{
				return null;
			}
			Player component = body.GetComponent<Player>();
			return new DamageSource(body, body, ((Object)(object)component != (Object)null) ? component.GetAttackSpawnerPlayer() : null, -1, -1, ((Object)(object)component != (Object)null) ? component.GetDamageModifierStack(false) : null, false)
			{
				m_sourceOwnerPlayer = body
			};
		}

		public static DamageSource HandOn(DamageSource from, GameObject effect, bool keepAttack = false)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			if (from == null)
			{
				return null;
			}
			DamageSource val = new DamageSource(effect, from.m_sourceOwner, from.m_sourcePlayer, keepAttack ? from.m_sourceAttack : (-1), keepAttack ? from.m_sourceAttackUId : (-1), from.m_damageMod, false);
			GameObject sourceOwner = from.m_sourceOwner;
			Player val2 = (((Object)(object)sourceOwner != (Object)null && (Object)(object)from.m_sourceOwnerPlayer == (Object)(object)sourceOwner) ? sourceOwner.GetComponent<Player>() : null);
			if ((Object)(object)val2 != (Object)null && val2.GetIsAI())
			{
				val.m_sourceOwnerPlayer = sourceOwner;
			}
			return val;
		}

		public static PlayerData CreditFor(DamageSource source)
		{
			if (source == null)
			{
				return null;
			}
			if (source.m_sourcePlayer != null)
			{
				return source.m_sourcePlayer;
			}
			GameObject[] array = (GameObject[])(object)new GameObject[3] { source.m_sourceOwnerPlayer, source.m_sourceOwner, source.m_source };
			foreach (GameObject val in array)
			{
				Player val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Player>() : null);
				PlayerData val3 = (((Object)(object)val2 != (Object)null) ? val2.GetAttackSpawnerPlayer() : null);
				if (val3 != null)
				{
					return val3;
				}
			}
			return null;
		}

		public static bool IsGhost(Player p)
		{
			if ((Object)(object)p != (Object)null)
			{
				return s_isGhost.Invoke(p);
			}
			return false;
		}

		public static Collider Hurtbox(GameObject who)
		{
			if ((Object)(object)who == (Object)null)
			{
				return null;
			}
			int num = LayerMask.NameToLayer("DamagablePlayer");
			Collider[] componentsInChildren = who.GetComponentsInChildren<Collider>();
			foreach (Collider val in componentsInChildren)
			{
				if ((Object)(object)((Component)val).transform != (Object)(object)who.transform && ((Component)val).gameObject.layer == num && val.enabled)
				{
					return val;
				}
			}
			return null;
		}

		public static string PrefabName(GameObject go)
		{
			string name = ((Object)go).name;
			int num = name.IndexOf("(Clone)");
			if (num < 0)
			{
				return name;
			}
			return name.Substring(0, num).Trim();
		}

		public static bool Clear(Vector2 a, Vector2 b)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = b - a;
			if (((Vector2)(ref val)).sqrMagnitude < 0.01f)
			{
				return true;
			}
			Vector3 val2 = new Vector3(a.x, a.y, 0f);
			Vector3 val3 = new Vector3(val.x, val.y, 0f);
			return !Physics.Raycast(val2, ((Vector3)(ref val3)).normalized, ((Vector2)(ref val)).magnitude, Constants.COL_MASK_WALLS);
		}

		public static Vector2 SafePoint(Vector2 from, Vector2 to, float margin = 6f)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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_0030: 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_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = to - from;
			float magnitude = ((Vector2)(ref val)).magnitude;
			if (magnitude < 0.01f)
			{
				return from;
			}
			RaycastHit val2 = default(RaycastHit);
			if (Physics.Raycast(new Vector3(from.x, from.y, 0f), new Vector3(val.x, val.y, 0f) / magnitude, ref val2, magnitude, Constants.COL_MASK_WALLS))
			{
				return from + val / magnitude * Mathf.Max(0f, ((RaycastHit)(ref val2)).distance - margin);
			}
			return to;
		}

		public static void Teleport(GameObject go, Vector2 p)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			float z = go.transform.position.z;
			go.transform.position = new Vector3(p.x, p.y, z);
			Rigidbody component = go.GetComponent<Rigidbody>();
			if ((Object)(object)component != (Object)null)
			{
				component.position = go.transform.position;
				component.velocity = Vector3.zero;
			}
		}

		public static void Pull(GameObject who, Vector2 toward, float strength)
		{
			//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)
			//IL_0031: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)who == (Object)null)
			{
				return;
			}
			PlayerMovement component = who.GetComponent<PlayerMovement>();
			if (!((Object)(object)component == (Object)null))
			{
				Vector2 val = toward - Vector2.op_Implicit(who.transform.position);
				if (!(((Vector2)(ref val)).sqrMagnitude < 36f))
				{
					component.AddImpulse(((Vector2)(ref val)).normalized * Mathf.Min(strength, ((Vector2)(ref val)).magnitude * 6f));
				}
			}
		}

		public static bool DoorsLocked()
		{
			SystemLevel get = Singleton<SystemLevel>.Get;
			Room val = (((Object)(object)get != (Object)null) ? R.Get<Room>(get, "m_currentRoom") : null);
			if ((Object)(object)val != (Object)null)
			{
				return val.GetDoorsLocked();
			}
			return false;
		}
	}
	public static class R
	{
		private delegate bool Mapper(Object from, out Object to);

		private static readonly Dictionary<Type, Dictionary<string, FieldInfo>> s_fields = new Dictionary<Type, Dictionary<string, FieldInfo>>();

		private static readonly MethodInfo s_memberwiseClone = typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic);

		internal static FieldInfo F(Type t, string name)
		{
			if (!s_fields.TryGetValue(t, out var value))
			{
				value = (s_fields[t] = new Dictionary<string, FieldInfo>());
			}
			if (value.TryGetValue(name, out var value2))
			{
				return value2;
			}
			value2 = AccessTools.Field(t, name);
			if ((object)value2 == null)
			{
				throw new MissingFieldException(t.Name, name);
			}
			value[name] = value2;
			return value2;
		}

		public static T Get<T>(object o, string field)
		{
			return (T)F(o.GetType(), field).GetValue(o);
		}

		public static void Set(object o, string field, object value)
		{
			F(o.GetType(), field).SetValue(o, value);
		}

		public static T Clone<T>(T o) where T : class
		{
			if (o != null)
			{
				return (T)s_memberwiseClone.Invoke(o, null);
			}
			return null;
		}

		internal static int RemapReferences(GameObject root, Dictionary<Object, Object> map)
		{
			return Walk(root, map.TryGetValue);
		}

		internal static int VisitReferences(GameObject root, Func<Object, Object> visit)
		{
			return Walk(root, delegate(Object k, out Object v)
			{
				v = visit(k);
				return v != (Object)null && v != k;
			});
		}

		private static int Walk(GameObject root, Mapper map)
		{
			int num = 0;
			HashSet<object> visited = new HashSet<object>();
			Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !(val is Transform))
				{
					num += RemapObject(val, map, visited, 0);
				}
			}
			return num;
		}

		private static int RemapObject(object o, Mapper map, HashSet<object> visited, int depth)
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Expected O, but got Unknown
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Expected O, but got Unknown
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Expected O, but got Unknown
			if (o == null || depth > 6)
			{
				return 0;
			}
			if (!(o is Object) && !visited.Add(o))
			{
				return 0;
			}
			int num = 0;
			Type type = o.GetType();
			if ((object)type.Assembly == typeof(GameObject).Assembly && !(o is MonoBehaviour))
			{
				return 0;
			}
			Type type2 = type;
			while ((object)type2 != null && (object)type2 != typeof(MonoBehaviour) && (object)type2 != typeof(object))
			{
				FieldInfo[] fields = type2.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (fieldInfo.IsNotSerialized || fieldInfo.IsLiteral || fieldInfo.IsInitOnly)
					{
						continue;
					}
					Type fieldType = fieldInfo.FieldType;
					object value;
					try
					{
						value = fieldInfo.GetValue(o);
					}
					catch
					{
						continue;
					}
					if (value == null)
					{
						continue;
					}
					Object to;
					if (typeof(Object).IsAssignableFrom(fieldType))
					{
						if (map((Object)value, out to))
						{
							fieldInfo.SetValue(o, to);
							num++;
						}
					}
					else if (fieldType.IsArray)
					{
						Array array = (Array)value;
						Type elementType = fieldType.GetElementType();
						for (int j = 0; j < array.Length; j++)
						{
							object value2 = array.GetValue(j);
							if (value2 == null)
							{
								continue;
							}
							if (typeof(Object).IsAssignableFrom(elementType))
							{
								if (map((Object)value2, out to))
								{
									array.SetValue(to, j);
									num++;
								}
							}
							else if (IsPlainSerializable(elementType))
							{
								num += RemapObject(value2, map, visited, depth + 1);
							}
						}
					}
					else if (value is IList && fieldType.IsGenericType)
					{
						IList list = (IList)value;
						Type type3 = fieldType.GetGenericArguments()[0];
						for (int k = 0; k < list.Count; k++)
						{
							object obj2 = list[k];
							if (obj2 == null)
							{
								continue;
							}
							if (typeof(Object).IsAssignableFrom(type3))
							{
								if (map((Object)obj2, out to))
								{
									list[k] = to;
									num++;
								}
							}
							else if (IsPlainSerializable(type3))
							{
								num += RemapObject(obj2, map, visited, depth + 1);
							}
						}
					}
					else if (IsPlainSerializable(fieldType))
					{
						num += RemapObject(value, map, visited, depth + 1);
					}
				}
				type2 = type2.BaseType;
			}
			return num;
		}

		private static bool IsPlainSerializable(Type t)
		{
			if (t.IsClass && !t.IsPrimitive && (object)t != typeof(string) && !typeof(Object).IsAssignableFrom(t))
			{
				return t.IsDefined(typeof(SerializableAttribute), inherit: false);
			}
			return false;
		}
	}
}
namespace CrawlFurther.UI
{
	public static class Branding
	{
		private static BrandingDef s_def;

		private static SpriteSheet s_wordmark;

		private static SpriteSheet s_spark;

		public static string DisplayName
		{
			get
			{
				if (s_def == null || string.IsNullOrEmpty(s_def.name))
				{
					return "Crawl Further Core";
				}
				return s_def.name;
			}
		}

		public static string Version
		{
			get
			{
				if (s_def == null || string.IsNullOrEmpty(s_def.version))
				{
					return "1.2.1";
				}
				return s_def.version;
			}
		}

		public static string Versioned => DisplayName + " " + Version;

		internal static SpriteSheet Wordmark
		{
			get
			{
				if (s_wordmark == null && s_def != null && s_def.wordmark != null)
				{
					s_wordmark = SpriteSheets.Get(s_def.wordmark);
				}
				return s_wordmark;
			}
		}

		internal static SpriteSheet Spark
		{
			get
			{
				if (s_spark == null && s_def != null && s_def.spark != null)
				{
					s_spark = SpriteSheets.Get(s_def.spark);
				}
				return s_spark;
			}
		}

		internal static SpriteSheet MenuPip
		{
			get
			{
				if (s_def == null || s_def.menuPip == null)
				{
					return null;
				}
				return SpriteSheets.Get(s_def.menuPip);
			}
		}

		internal static SpriteSheet MenuMote
		{
			get
			{
				if (s_def == null || s_def.menuMote == null)
				{
					return null;
				}
				return SpriteSheets.Get(s_def.menuMote);
			}
		}

		internal static bool HasVersionLine
		{
			get
			{
				if (s_def != null)
				{
					return !string.IsNullOrEmpty(s_def.name);
				}
				return false;
			}
		}

		public static void Set(BrandingDef def)
		{
			s_def = def;
			s_wordmark = null;
			s_spark = null;
		}

		public static void SelfCheck(Action<string> bad)
		{
			List<KeyValuePair<string, string[]>> list = new List<KeyValuePair<string, string[]>>();
			if (s_def != null)
			{
				if (s_def.wordmark != null)
				{
					list.Add(new KeyValuePair<string, string[]>(s_def.wordmark, new string[4] { "Idle", "Glitch", "In", "Out" }));
				}
				if (s_def.spark != null)
				{
					list.Add(new KeyValuePair<string, string[]>(s_def.spark, new string[1] { "Rise" }));
				}
				if (s_def.menuPip != null)
				{
					list.Add(new KeyValuePair<string, string[]>(s_def.menuPip, new string[1] { "Burn" }));
				}
				if (s_def.menuMote != null)
				{
					list.Add(new KeyValuePair<string, string[]>(s_def.menuMote, MenuRefresh.MoteAnims));
				}
			}
			list.Add(new KeyValuePair<string, string[]>("VaultIcons", new string[3] { "Undiscovered", "NoArt", "Locked" }));
			foreach (VaultCategory category in Vault.Categories)
			{
				if (!string.IsNullOrEmpty(category.stamp))
				{
					list.Add(new KeyValuePair<string, string[]>(category.stamp, new string[0]));
				}
			}
			foreach (KeyValuePair<string, string[]> item in list)
			{
				SpriteSheet spriteSheet = SpriteSheets.Get(item.Key);
				if (spriteSheet == null)
				{
					bad(item.Key + " art missing");
					continue;
				}
				string[] value = item.Value;
				foreach (string text in value)
				{
					if (!spriteSheet.Has(text))
					{
						bad(item.Key + " has no " + text + " anim");
					}
				}
			}
			if ((object)AccessTools.Field(typeof(MenuMain), "m_menuMain") == null)
			{
				bad("MenuMain.m_menuMain not found");
			}
			if ((object)AccessTools.Field(typeof(MenuCredits), "m_scrollContainer") == null)
			{
				bad("MenuCredits.m_scrollContainer not found");
			}
			LibraryEntries.SelfCheck(bad);
			NoModTags(bad);
			ModMusic.SelfCheck(bad);
			Secrets.SelfCheck(bad);
			ModMark.SelfCheck(bad);
		}

		public static void NoModTags(Action<string> bad)
		{
			Func<string, bool> func = (string t) => !string.IsNullOrEmpty(t) && (t.Contains("(MOD)") || t.Contains("[MOD]"));
			foreach (KeyValuePair<string, Powerup> item in ItemRegistry.Items)
			{
				if ((Object)(object)item.Value != (Object)null && (func(item.Value.GetDisplayName()) || func(item.Value.GetDescription())))
				{
					bad("item " + item.Key + " still tagged");
				}
			}
			foreach (KeyValuePair<string, Weapon> weapon in ItemRegistry.Weapons)
			{
				Weapon value = weapon.Value;
				if ((Object)(object)value == (Object)null)
				{
					continue;
				}
				if (func(value.m_weaponName) || func(value.m_weaponDescription))
				{
					bad("weapon " + weapon.Key + " still tagged");
				}
				if (value.m_combos == null)
				{
					continue;
				}
				foreach (Combo combo in value.m_combos)
				{
					if (combo != null && (func(combo.m_name) || func(combo.m_description)))
					{
						bad("weapon " + weapon.Key + " combo still tagged");
					}
				}
			}
			foreach (string builtName in DeityFactory.BuiltNames)
			{
				Deity deity = SystemDeity.GetDeity(builtName);
				if (deity != null && func(R.Get<string>(deity, "m_text")))
				{
					bad("god " + builtName + " text still tagged");
				}
			}
			if (Singleton<SystemLibrary>.HasInstance())
			{
				foreach (LibraryEntry item2 in R.Get<List<LibraryEntry>>(Singleton<SystemLibrary>.Instance, "m_entryList"))
				{
					if (item2 != null && (func(item2.m_name) || func(item2.m_description)))
					{
						bad("vault entry " + ((object)item2)?.ToString() + " still tagged");
					}
				}
			}
			foreach (string item3 in TipRegistry.VaultOrder)
			{
				if (TipRegistry.TryGet(item3, out var tip) && (func(tip.name) || func(tip.attack) || func(tip.special) || func(tip.passive)))
				{
					bad("tip " + item3 + " still tagged");
				}
			}
		}

		public static exSprite MakeSprite(string name, Transform parent, SpriteSheet sheet, Vector3 localPos)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.layer = ((Component)parent).gameObject.layer;
			val.transform.SetParent(parent, false);
			val.transform.localPosition = localPos;
			val.AddComponent<MeshFilter>();
			val.AddComponent<MeshRenderer>();
			exSprite obj = val.AddComponent<exSprite>();
			((exPlane)obj).anchor = (Anchor)4;
			obj.useTextureOffset = false;
			obj.SetSprite(sheet.atlas, 0, false);
			val.GetComponent<Renderer>().sharedMaterial = sheet.atlas.material;
			return obj;
		}
	}
	[HarmonyPatch(typeof(MenuMain), "Start")]
	internal static class Patch_BrandTitle
	{
		private static void Postfix(MenuMain __instance)
		{
			if (!UiSettings.Wordmark || Branding.Wordmark == null)
			{
				return;
			}
			try
			{
				Transform val = ((Component)__instance).transform.Find("Title");
				exSprite val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<exSprite>() : null);
				if ((Object)(object)val2 != (Object)null)
				{
					TitleWordmark.AttachTitle(val2);
				}
				else
				{
					FurtherCore.Log.LogWarning((object)"Branding: MenuMain has no Title sprite");
				}
			}
			catch (Exception ex)
			{
				FurtherCore.Log.LogError((object)("Branding title: " + ex));
			}
		}
	}
	[HarmonyPatch(typeof(MenuCredits), "OnEnable")]
	internal static class Patch_BrandCredits
	{
		private static void Postfix(MenuCredits __instance)
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			if (!UiSettings.Wordmark || Branding.Wordmark == null)
			{
				return;
			}
			try
			{
				GameObject val = R.Get<GameObject>(__instance, "m_scrollContainer");
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				exSprite[] componentsInChildren = val.GetComponentsInChildren<exSprite>(true);
				foreach (exSprite val2 in componentsInChildren)
				{
					if (!((Object)(object)val2.atlas == (Object)null) && !(((Object)val2.atlas).name != "AtlasMenuMain") && val2.index >= 347 && val2.index <= 391 && !((Object)(object)((Component)val2).GetComponent<TitleWordmark>() != (Object)null))
					{
						float x = ((exSpriteBase)val2).scale.x;
						TitleWordmark.AttachStatic(((Component)val2).transform, new Vector3(33f * x, -8.5f * x, -0.5f), 0.8f * x);
					}
				}
			}
			catch (Exception ex)
			{
				FurtherCore.Log.LogError((object)("Branding credits: " + ex));
			}
		}
	}
	public class BrandingDef
	{
		public string name;

		public string version;

		public string wordmark;

		public string spark;

		public string menuPip;

		public string menuMote;
	}
	public enum GemCorner
	{
		Art,
		Cell
	}
	internal class HudTimerView : MonoBehaviour
	{
		private sealed class Item
		{
			public GameObject root;

			public exSprite icon;

			public Renderer iconR;

			public TextMesh text;

			public TextMesh shadow;

			public Renderer textR;

			public Renderer shadowR;

			public SpriteSheet sheet;

			public int shown = -1;

			public float alpha = -1f;

			public bool measured;

			public int tries;
		}

		private sealed class Panel
		{
			public GUIPlayer gp;

			public GameObject root;

			public readonly List<Item> items = new List<Item>();

			public Bounds bounds;

			public bool hasBounds;

			public float limitRight;
		}

		private const int Players = 4;

		private const float LookEvery = 0.5f;

		private const float PausedAlpha = 0.45f;

		private static HudTimerView s_inst;

		private readonly Panel[] m_panels = new Panel[4];

		private float m_nextLook;

		private bool m_shown;

		private TextMesh m_nameRef;

		private exSprite m_iconRef;

		public static void Ensure()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			if (!((Object)(object)s_inst != (Object)null))
			{
				GameObject val = new GameObject("CrawlFurther.HudTimers");
				Object.DontDestroyOnLoad((Object)val);
				s_inst = val.AddComponent<HudTimerView>();
			}
		}

		private static bool Paused()
		{
			if (Time.timeScale <= 0f)
			{
				return true;
			}
			try
			{
				return Singleton<SystemTime>.HasInstance() && SystemTime.Paused;
			}
			catch
			{
				return false;
			}
		}

		private void LateUpdate()
		{
			if (!HudTimers.Any || Paused())
			{
				if (m_shown)
				{
					HideAll();
				}
				return;
			}
			try
			{
				if (Time.unscaledTime >= m_nextLook)
				{
					m_nextLook = Time.unscaledTime + 0.5f;
					Look();
				}
				for (int i = 0; i < 4; i++)
				{
					Draw(i);
				}
				m_shown = true;
			}
			catch (Exception ex)
			{
				FurtherCore.Log.LogWarning((object)("HUD timers: " + ex.Message));
				m_nextLook = Time.unscaledTime + 5f;
			}
		}

		private void HideAll()
		{
			m_shown = false;
			Panel[] panels = m_panels;
			foreach (Panel panel in panels)
			{
				if (panel == null)
				{
					continue;
				}
				foreach (Item item in panel.items)
				{
					Show(item, on: false);
				}
			}
		}

		private void Look()
		{
			//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_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			GUIPlayer[] array = (GUIPlayer[])(object)new GUIPlayer[4];
			GUIPlayer[] array2 = Object.FindObjectsOfType<GUIPlayer>();
			foreach (GUIPlayer val in array2)
			{
				int playerId = val.GetPlayerId();
				if (playerId >= 0 && playerId < 4 && ((Component)val).gameObject.activeInHierarchy)
				{
					array[playerId] = val;
				}
			}
			for (int j = 0; j < 4; j++)
			{
				Panel panel = m_panels[j];
				if (panel != null && (Object)(object)panel.gp != (Object)(object)array[j])
				{
					if ((Object)(object)panel.root != (Object)null)
					{
						Object.Destroy((Object)(object)panel.root);
					}
					panel = (m_panels[j] = null);
				}
				if (panel == null && (Object)(object)array[j] != (Object)null && HudTimers.Players[j].Count > 0)
				{
					Panel[] panels = m_panels;
					int num = j;
					Panel obj = new Panel
					{
						gp = array[j]
					};
					panel = obj;
					panels[num] = obj;
				}
				if (panel != null)
				{
					panel.hasBounds = Measure(panel.gp, panel.root, out panel.bounds);
				}
			}
			Camera val2 = Camera();
			float limitRight = (((Object)(object)val2 != (Object)null) ? val2.ViewportToWorldPoint(new Vector3(1f, 0.5f, val2.nearClipPlane + 1f)).x : float.MaxValue);
			for (int k = 0; k < 4; k++)
			{
				Panel panel2 = m_panels[k];
				if (panel2 == null || !panel2.hasBounds)
				{
					continue;
				}
				panel2.limitRight = limitRight;
				for (int l = 0; l < 4; l++)
				{
					if (l != k && !((Object)(object)array[l] == (Object)null))
					{
						Panel panel3 = m_panels[l];
						Bounds bounds;
						if (panel3 != null && panel3.hasBounds)
						{
							bounds = panel3.bounds;
						}
						else if (!Measure(array[l], null, out bounds))
						{
							continue;
						}
						if (((Bounds)(ref bounds)).min.x > ((Bounds)(ref panel2.bounds)).center.x)
						{
							panel2.limitRight = Mathf.Min(panel2.limitRight, ((Bounds)(ref bounds)).min.x);
						}
					}
				}
			}
		}

		private Camera Camera()
		{
			Panel[] panels = m_panels;
			foreach (Panel panel in panels)
			{
				ScreenAlign val = ((panel != null && (Object)(object)panel.gp != (Object)null) ? ((Component)panel.gp).GetComponent<ScreenAlign>() : null);
				if ((Object)(object)val != (Object)null && (Object)(object)val.m_camera != (Object)null)
				{
					return val.m_camera;
				}
			}
			try
			{
				return Singleton<SystemLevel>.HasInstance() ? SystemLevel.GetCameraGUI() : null;
			}
			catch
			{
				return null;
			}
		}

		private static bool Measure(GUIPlayer gp, GameObject skip, out Bounds bounds)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: 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)
			bounds = default(Bounds);
			bool flag = false;
			Renderer[] componentsInChildren = ((Component)gp).GetComponentsInChildren<Renderer>();
			foreach (Renderer val in componentsInChildren)
			{
				if (!val.enabled || !((Component)val).gameObject.activeInHierarchy || ((Object)(object)skip != (Object)null && ((Component)val).transform.IsChildOf(skip.transform)))
				{
					continue;
				}
				Bounds bounds2 = val.bounds;
				if (!(((Bounds)(ref bounds2)).size.x <= 0f) || !(((Bounds)(ref bounds2)).size.y <= 0f))
				{
					if (!flag)
					{
						bounds = bounds2;
						flag = true;
					}
					else
					{
						((Bounds)(ref bounds)).Encapsulate(bounds2);
					}
				}
			}
			return flag;
		}

		private void Draw(int id)
		{
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: 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_0368: Unknown result type (might be due to invalid IL or missing references)
			//IL_0312: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			Panel panel = m_panels[id];
			List<HudTimers.Entry> list = HudTimers.Players[id];
			if (panel == null)
			{
				return;
			}
			if ((Object)(object)panel.gp == (Object)null || !((Component)panel.gp).gameObject.activeInHierarchy || !panel.hasBounds || list.Count == 0)
			{
				foreach (Item item3 in panel.items)
				{
					Show(item3, on: false);
				}
				return;
			}
			if ((Object)(object)panel.root == (Object)null && !Build(panel))
			{
				return;
			}
			while (panel.items.Count < list.Count)
			{
				panel.items.Add(MakeItem(panel));
			}
			for (int i = list.Count; i < panel.items.Count; i++)
			{
				Show(panel.items[i], on: false);
			}
			float num = 0f;
			float num2 = 0f;
			float num3 = 0f;
			bool flag = true;
			Bounds bounds;
			for (int j = 0; j < list.Count; j++)
			{
				Item item = panel.items[j];
				Fill(item, list[j]);
				if (!item.measured)
				{
					flag = false;
					continue;
				}
				bounds = item.textR.bounds;
				Vector3 size = ((Bounds)(ref bounds)).size;
				Vector3 val;
				if (!((Behaviour)item.icon).enabled)
				{
					val = Vector3.zero;
				}
				else
				{
					bounds = item.iconR.bounds;
					val = ((Bounds)(ref bounds)).size;
				}
				Vector3 val2 = val;
				num3 = Mathf.Max(num3, size.y * 0.25f);
				num = Mathf.Max(num, Mathf.Max(size.y, val2.y));
				num2 = Mathf.Max(num2, val2.x + size.x);
			}
			if (!flag)
			{
				for (int k = 0; k < list.Count; k++)
				{
					Item item2 = panel.items[k];
					if (item2.measured)
					{
						continue;
					}
					int measured;
					if (item2.root.activeSelf)
					{
						bounds = item2.textR.bounds;
						if (((Bounds)(ref bounds)).size.x > 0f)
						{
							if (((Behaviour)item2.icon).enabled)
							{
								bounds = item2.iconR.bounds;
								if (!(((Bounds)(ref bounds)).size.x > 0f))
								{
									measured = ((++item2.tries > 10) ? 1 : 0);
									goto IL_027d;
								}
							}
							measured = 1;
							goto IL_027d;
						}
					}
					measured = 0;
					goto IL_027d;
					IL_027d:
					item2.measured = (byte)measured != 0;
					if (!item2.measured)
					{
						SetAlpha(item2, 0f);
						Show(item2, on: true);
					}
				}
				return;
			}
			num2 += num3;
			Bounds bounds2 = panel.bounds;
			float z = ((Bounds)(ref bounds2)).center.z - 0.5f;
			bool flag2 = ((Bounds)(ref bounds2)).max.x + num3 + num2 <= panel.limitRight - num3;
			for (int l = 0; l < list.Count; l++)
			{
				Item it = panel.items[l];
				float x;
				float y;
				if (flag2)
				{
					x = ((Bounds)(ref bounds2)).max.x + num3;
					y = ((Bounds)(ref bounds2)).center.y + (float)(list.Count - 1) * 0.5f * (num + num3 * 0.5f) - (float)l * (num + num3 * 0.5f);
				}
				else
				{
					float num4 = ItemWidth(it, num3);
					float num5 = ((Bounds)(ref bounds2)).max.x;
					for (int m = 0; m < l; m++)
					{
						num5 -= ItemWidth(panel.items[m], num3) + num3;
					}
					x = num5 - num4;
					y = ((Bounds)(ref bounds2)).max.y + num3 + num * 0.5f;
				}
				Place(it, x, y, z);
				SetAlpha(it, list[l].paused ? 0.45f : 1f);
				Show(it, on: true);
			}
		}

		private static float ItemWidth(Item it, float gap)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			float num;
			Bounds bounds;
			if (!((Behaviour)it.icon).enabled)
			{
				num = 0f;
			}
			else
			{
				bounds = it.iconR.bounds;
				num = ((Bounds)(ref bounds)).size.x;
			}
			float num2 = num + ((num > 0f) ? (gap * 0.5f) : 0f);
			bounds = it.textR.bounds;
			return num2 + ((Bounds)(ref bounds)).size.x;
		}

		private static void Place(Item it, float x, float y, float z)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: 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)
			float num;
			Bounds bounds;
			if (!((Behaviour)it.icon).enabled)
			{
				num = 0f;
			}
			else
			{
				bounds = it.iconR.bounds;
				num = ((Bounds)(ref bounds)).size.x;
			}
			float num2 = num;
			if (((Behaviour)it.icon).enabled)
			{
				((Component)it.icon).transform.position = new Vector3(x + num2 * 0.5f, y, z);
			}
			float num3 = x + num2;
			float num4;
			if (!(num2 > 0f))
			{
				num4 = 0f;
			}
			else
			{
				bounds = it.textR.bounds;
				num4 = ((Bounds)(ref bounds)).size.y * 0.15f;
			}
			float num5 = num3 + num4;
			((Component)it.text).transform.position = new Vector3(num5, y, z);
			bounds = it.textR.bounds;
			float num6 = ((Bounds)(ref bounds)).size.y / 9f;
			((Component)it.shadow).transform.position = new Vector3(num5 + num6, y - num6, z + 0.05f);
		}

		private void Fill(Item it, HudTimers.Entry e)
		{
			int num = HudTimers.Shown(e.seconds);
			if (num != it.shown)
			{
				it.shown = num;
				string text = num.ToString();
				it.text.text = text;
				it.shadow.text = text;
			}
			if (e.icon == it.sheet)
			{
				return;
			}
			it.sheet = e.icon;
			bool flag = e.icon != null && (Object)(object)e.icon.atlas != (Object)null && e.icon.atlas.elements != null && e.icon.atlas.elements.Length != 0;
			((Behaviour)it.icon).enabled = flag;
			it.iconR.enabled = flag;
			it.measured = false;
			it.tries = 0;
			if (flag)
			{
				SheetAnim sheetAnim = e.icon.Anim("Idle");
				int num2 = ((sheetAnim != null && sheetAnim.frames != null && sheetAnim.frames.Length != 0) ? sheetAnim.frames[0] : 0);
				it.icon.SetSprite(e.icon.atlas, num2, false);
				if ((Object)(object)e.icon.atlas.material != (Object)null)
				{
					it.iconR.sharedMaterial = e.icon.atlas.material;
				}
			}
		}

		private static void SetAlpha(Item it, float a)
		{
			//IL_0032: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			if (!(Mathf.Abs(a - it.alpha) < 0.004f))
			{
				it.alpha = a;
				it.text.color = new Color(1f, 0.96f, 0.86f, a);
				it.shadow.color = new Color(0f, 0f, 0f, a * 0.85f);
				if (((Behaviour)it.icon).enabled)
				{
					it.icon.color = new Color(1f, 1f, 1f, a);
				}
			}
		}

		private static void Show(Item it, bool on)
		{
			if (it.root.activeSelf != on)
			{
				it.root.SetActive(on);
			}
		}

		private bool Build(Panel p)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Expected O, but got Unknown
			m_nameRef = R.Get<TextMesh>(p.gp, "m_name");
			GameObject val = R.Get<GameObject>(p.gp, "m_goldIcon");
			m_iconRef = (((Object)(object)val != (Object)null) ? val.GetComponentInChildren<exSprite>(true) : null);
			if ((Object)(object)m_iconRef == (Object)null)
			{
				m_iconRef = R.Get<exSprite>(p.gp, "m_portrait");
			}
			if ((Object)(object)m_nameRef == (Object)null || (Object)(object)m_nameRef.font == (Object)null)
			{
				return false;
			}
			p.root = new GameObject("CrawlFurther.HudTimers");
			p.root.layer = ((Component)p.gp).gameObject.layer;
			p.root.transform.SetParent(((Component)p.gp).transform, false);
			return true;
		}

		private Item MakeItem(Panel p)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			//IL_012a: 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)
			Item item = new Item
			{
				root = new GameObject("Countdown")
			};
			item.root.layer = p.root.layer;
			item.root.transform.SetParent(p.root.transform, false);
			Renderer component = ((Component)m_nameRef).GetComponent<Renderer>();
			item.shadow = MakeText(item.root.transform, "Shadow", component, 4, out item.shadowR);
			item.text = MakeText(item.root.transform, "Text", component, 5, out item.textR);
			GameObject val = new GameObject("Picture");
			val.layer = item.root.layer;
			val.transform.SetParent(item.root.transform, false);
			val.AddComponent<MeshFilter>();
			item.iconR = (Renderer)(object)val.AddComponent<MeshRenderer>();
			item.icon = val.AddComponent<exSprite>();
			((exPlane)item.icon).anchor = (Anchor)4;
			if ((Object)(object)m_iconRef != (Object)null)
			{
				MatchScale(val.transform, ((Component)m_iconRef).transform);
				((exSpriteBase)item.icon).scale = ((exSpriteBase)m_iconRef).scale;
				((exSpriteBase)item.icon).ppfScale = ((exSpriteBase)m_iconRef).ppfScale;
				Camera renderCamera = ((exPlane)m_iconRef).renderCamera;
				if ((Object)(object)renderCamera != (Object)null)
				{
					((exPlane)item.icon).renderCamera = renderCamera;
				}
			}
			((Behaviour)item.icon).enabled = false;
			item.iconR.enabled = false;
			item.root.SetActive(false);
			return item;
		}

		private TextMesh MakeText(Transform parent, string name, Renderer like, int sortAdd, out Renderer rend)
		{
			//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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name)
			{
				layer = ((Component)parent).gameObject.layer
			};
			val.transform.SetParent(parent, false);
			MatchScale(val.transform, ((Component)m_nameRef).transform);
			MeshRenderer val2 = val.AddComponent<MeshRenderer>();
			TextMesh obj = val.AddComponent<TextMesh>();
			obj.font = m_nameRef.font;
			obj.fontSize = m_nameRef.fontSize;
			obj.characterSize = m_nameRef.characterSize;
			obj.anchor = (TextAnchor)3;
			obj.alignment = (TextAlignment)0;
			obj.richText = false;
			((Renderer)val2).sharedMaterial = (((Object)(object)like != (Object)null && (Object)(object)like.sharedMaterial != (Object)null) ? like.sharedMaterial : m_nameRef.font.material);
			if ((Object)(object)like != (Object)null)
			{
				((Renderer)val2).sortingLayerID = like.sortingLayerID;
				((Renderer)val2).sortingOrder = like.sortingOrder + sortAdd;
			}
			((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)val2).receiveShadows = false;
			rend = (Renderer)(object)val2;
			return obj;
		}

		private static void MatchScale(Transform t, Transform like)
		{
			//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_0022: 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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			Vector3 lossyScale = like.lossyScale;
			Vector3 val = (((Object)(object)t.parent != (Object)null) ? t.parent.lossyScale : Vector3.one);
			t.localScale = new Vector3(Div(lossyScale.x, val.x), Div(lossyScale.y, val.y), 1f);
		}

		private static float Div(float a, float b)
		{
			if (!(Mathf.Abs(b) > 0.0001f))
			{
				return 1f;
			}
			return Mathf.Abs(a / b);
		}
	}
	public static class HudTimers
	{
		internal sealed class Entry
		{
			public string key;

			public float seconds;

			public SpriteSheet icon;

			public bool paused;
		}

		internal static readonly List<Entry>[] Players = new List<Entry>[4]
		{
			new List<Entry>(),
			new List<Entry>(),
			new List<Entry>(),
			new List<Entry>()
		};

		internal static int Version;

		public static bool Any
		{
			get
			{
				List<Entry>[] players = Players;
				for (int i = 0; i < players.Length; i++)
				{
					if (players[i].Count > 0)
					{
						return true;
					}
				}
				return false;
			}
		}

		public static void Set(int playerId, string key, float secondsLeft, SpriteSheet icon = null, bool paused = false)
		{
			if (playerId < 0 || playerId >= Players.Length || string.IsNullOrEmpty(key))
			{
				return;
			}
			if (secondsLeft <= 0f)
			{
				Clear(playerId, key);
				return;
			}
			List<Entry> list = Players[playerId];
			Entry entry = list.Find((Entry x) => x.key == key);
			if (entry == null)
			{
				entry = new Entry
				{
					key = key
				};
				list.Add(entry);
				Version++;
			}
			if (entry.icon != icon || entry.paused != paused || Shown(entry.seconds) != Shown(secondsLeft))
			{
				Version++;
			}
			entry.seconds = secondsLeft;
			entry.icon = icon;
			entry.paused = paused;
			HudTimerView.Ensure();
		}

		public static void Clear(int playerId, string key)
		{
			if (playerId >= 0 && playerId < Players.Length && Players[playerId].RemoveAll((Entry x) => x.key == key) > 0)
			{
				Version++;
			}
		}

		public static void Clear(int playerId)
		{
			if (playerId >= 0 && playerId < Players.Length && Players[playerId].Count != 0)
			{
				Players[playerId].Clear();
				Version++;
			}
		}

		public static void ClearAll()
		{
			for (int i = 0; i < Players.Length; i++)
			{
				Clear(i);
			}
		}

		internal static int Shown(float seconds)
		{
			return Mathf.CeilToInt(seconds);
		}
	}
	public static class LibraryEntries
	{
		private class Info
		{
			public string name;

			public string desc;

			public Info(string n, string d)
			{
				name = n;
				desc = d;
			}
		}

		private struct SavedRec
		{
			public bool found;

			public bool isNew;

			public int high;

			public int last;
		}

		private class PageInfo
		{
			public VaultCategory cat;

			public VaultPage page;

			public string text;
		}

		private class Extra
		{
			public GameObject prefab;

			public string name;

			public string desc;

			public exSpriteAnimClip portrait;

			public Vector2 offset;

			public bool obj;
		}

		public const string OldTag = " (MOD)";

		private static SystemLibrary s_registeredInto;

		private static readonly HashSet<LibraryEntry> s_mod = new HashSet<LibraryEntry>();

		private static readonly Dictionary<string, LibraryEntry> s_keys = new Dictionary<string, LibraryEntry>();

		private static readonly HashSet<GameObject> s_summoned = new HashSet<GameObject>();

		private static readonly HashSet<LibraryEntry> s_challenge = new HashSet<LibraryEntry>();

		private static readonly Dictionary<string, Dictionary<string, SavedRec>> s_pending = new Dictionary<string, Dictionary<string, SavedRec>>();

		private static List<LibraryEntry> s_lists;

		private static Dictionary<string, LibraryEntry> s_dict;

		private static List<string> s_users;

		private static SystemLibrary s_lib;

		private static GameObject s_vaultHolder;

		public const string NoChallengeText = "No challenge available";

		private static readonly Dictionary<VaultCategory, List<LibraryEntry>> s_pages = new Dictionary<VaultCategory, List<LibraryEntry>>();

		private static readonly Dictionary<LibraryEntry, PageInfo> s_pageInfo = new Dictionary<LibraryEntry, PageInfo>();

		private static readonly List<LibraryEntry> s_none = new List<LibraryEntry>();

		private static readonly List<Extra> s_extra = new List<Extra>();

		public static readonly List<LibraryEntry> SecretList = new List<LibraryEntry>();

		private static readonly Dictionary<LibraryEntry, string> s_secretOf = new Dictionary<LibraryEntry, string>();

		private static readonly Dictionary<string, LibraryEntry> s_pageOf = new Dictionary<string, LibraryEntry>();

		private static readonly Dictionary<string, exSpriteAnimClip> s_secretClip = new Dictionary<string, exSpriteAnimClip>();

		private static MethodInfo s_getStats;

		private static FieldInfo s_fRatio;

		private static FieldInfo s_fRatioW;

		private static FieldInfo s_fRatioC;

		private static FieldInfo s_fCountC;

		public static bool HasModEntries => s_mod.Count > 0;

		public static int ExtraObjects
		{
			get
			{
				int num = 0;
				foreach (Extra item in s_extra)
				{
					if (item.obj)
					{
						num++;
					}
				}
				return num;
			}
		}

		public static bool IsMod(LibraryEntry e)
		{
			if (e != null)
			{
				return s_mod.Contains(e);
			}
			return false;
		}

		public static bool IsSummoned(GameObject prefab)
		{
			if ((Object)(object)prefab != (Object)null)
			{
				return s_summoned.Contains(prefab);
			}
			return false;
		}

		public static bool HasChallenge(LibraryEntry e)
		{
			if (e != null)
			{
				return s_challenge.Contains(e);
			}
			return false;
		}

		internal static List<KeyValuePair<int, string>> NoChallengeLines()
		{
			return new List<KeyValuePair<int, string>>
			{
				new KeyValuePair<int, string>(2, "No challenge available")
			};
		}

		public static bool NoChallenge(LibraryEntry e)
		{
			if (IsMod(e) && e is LibraryEntryMonster)
			{
				return !s_challenge.Contains(e);
			}
			return false;
		}

		public static void Register()
		{
			if (!Singleton<SystemLibrary>.HasInstance())
			{
				FurtherCore.Log.LogWarning((object)"Library: SystemLibrary not up yet; entries will be added when the vault opens");
			}
			else
			{
				EnsureRegistered();
			}
		}

		public static void EnsureRegistered()
		{
			if (!ContentManager.Registered || !Singleton<SystemLibrary>.HasInstance())
			{
				return;
			}
			SystemLibrary instance = Singleton<SystemLibrary>.Instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance == (Object)(object)s_registeredInto)
			{
				return;
			}
			s_registeredInto = instance;
			s_mod.Clear();
			s_keys.Clear();
			s_summoned.Clear();
			s_challenge.Clear();
			s_pages.Clear();
			s_pageInfo.Clear();
			SecretList.Clear();
			s_secretOf.Clear();
			s_pageOf.Clear();
			try
			{
				AddAll(instance);
			}
			catch (Exception ex)
			{
				FurtherCore.Log.LogError((object)("Library entries failed: " + ex));
			}
		}

		private static void AddAll(SystemLibrary lib)
		{
			//IL_009a: 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_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_00c4: 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_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Expected O, but got Unknown
			//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_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Expected O, but got Unknown
			//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Expected O, but got Unknown
			//IL_031a: Unknown result type (might be due to invalid IL or missing references)
			//IL_031f: Unknown result type (might be due to invalid IL or missing references)
			//IL_032c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0338: Expected O, but got Unknown
			//IL_033a: Unknown result type (might be due to invalid IL or missing references)
			//IL_033f: 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)
			//IL_035f: Expected O, but got Unknown
			List<LibraryEntry> list = R.Get<List<LibraryEntry>>(lib, "m_entryList");
			Dictionary<string, LibraryEntry> dictionary = R.Get<Dictionary<string, LibraryEntry>>(lib, "m_entries");
			if (list == null || dictionary == null || lib.m_monsters == null || lib.m_items == null || lib.m_weapons == null)
			{
				FurtherCore.Log.LogError((object)"Library: SystemLibrary has not built its lists; no mod entries added");
				return;
			}
			List<string> list2 = KnownUsers(lib);
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			HashSet<GameObject> hashSet = Reachable();
			foreach (string item in MonsterOrder())
			{
				Player val = MonsterFactory.Built[item];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Info info = Lookup(item);
				LibraryEntryMonster val2 = new LibraryEntryMonster
				{
					m_prefab = ((Component)val).gameObject,
					m_type = string.Empty,
					m_name = info.name,
					m_description = info.name + "\n" + info.desc,
					m_portraitOffset = PortraitOffset(val),
					m_startFound = false,
					m_targetScore = 9999
				};
				if (Add(list, dictionary, (LibraryEntry)(object)val2, list2))
				{
					lib.m_monsters.Add(val2);
					if (!hashSet.Contains(((Component)val).gameObject))
					{
						s_summoned.Add(((Component)val).gameObject);
					}
					num++;
				}
			}
			foreach (KeyValuePair<string, Powerup> item2 in ItemRegistry.Items)
			{
				Powerup value = item2.Value;
				if (!((Object)(object)value == (Object)null))
				{
					string text = Strip(value.GetDisplayName());
					if (string.IsNullOrEmpty(text))
					{
						text = Words(item2.Key);
					}
					LibraryEntry val3 = new LibraryEntry
					{
						m_prefab = ((Component)value).gameObject,
						m_type = string.Empty,
						m_name = text,
						m_description = Strip(value.GetDescription()),
						m_startFound = false
					};
					if (Add(list, dictionary, val3, list2))
					{
						lib.m_items.Add(val3);
						num2++;
					}
				}
			}
			foreach (KeyValuePair<string, Weapon> weapon in ItemRegistry.Weapons)
			{
				Weapon value2 = weapon.Value;
				if (!((Object)(object)value2 == (Object)null))
				{
					string text2 = ((value2.m_combos != null && value2.m_combos.Count > 0) ? value2.m_combos[0].m_name : string.Empty);
					string text3 = Strip((!string.IsNullOrEmpty(text2)) ? text2 : value2.m_weaponName);
					if (string.IsNullOrEmpty(text3))
					{
						text3 = Words(weapon.Key);
					}
					LibraryEntry val4 = new LibraryEntry();
					val4.m_prefab = ((Component)value2).gameObject;
					val4.m_type = text2 ?? string.Empty;
					val4.m_name = text3;
					val4.m_description = string.Empty;
					val4.m_startFound = false;
					val4.m_otherPrefabs = (LibraryEntryAdditional[])(object)(string.IsNullOrEmpty(text2) ? null : new LibraryEntryAdditional[2]
					{
						new LibraryEntryAdditional
						{
							m_prefab = ((Component)value2).gameObject,
							m_type = string.Empty
						},
						new LibraryEntryAdditional
						{
							m_prefab = ((Component)value2).gameObject,
							m_type = text2 + " (MOD)"
						}
					});
					LibraryEntry val5 = val4;
					if (Add(list, dictionary, val5, list2))
					{
						lib.m_weapons.Add(val5);
						num3++;
					}
				}
			}
			int num4 = 0;
			try
			{
				num4 = AddPages(list, dictionary, list2);
			}
			catch (Exception ex)
			{
				FurtherCore.Log.LogError((object)("Library category pages: " + ex));
			}
			s_lists = list;
			s_dict = dictionary;
			s_users = list2;
			s_lib = lib;
			foreach (Extra item3 in s_extra)
			{
				try
				{
					AddExtra(lib, item3);
				}
				catch (Exception ex2)
				{
					FurtherCore.Log.LogError((object)("Library extra page " + item3.name + ": " + ex2.Message));
				}
			}
			try
			{
				SyncSecrets();
			}
			catch (Exception ex3)
			{
				FurtherCore.Log.LogError((object)("Library SECRETS entries: " + ex3));
			}
			FurtherCore.Log.LogInfo((object)("Library: " + SecretList.Count + " secret pages (" + Secrets.All.Count + " registered)"));
			ApplyPending();
			try
			{
				RefreshChallenges();
			}
			catch (Exception ex4)
			{
				FurtherCore.Log.LogError((object)("Library challenges: " + ex4));
			}
			try
			{
				SystemLibrary.UpdateHasNewEntries();
			}
			catch (Exception ex5)
			{
				FurtherCore.Log.LogWarning((object)("Library: UpdateHasNewEntries: " + ex5.Message));
			}
			FurtherCore.Log.LogInfo((object)("Library: added " + num + " monsters (" + s_summoned.Count + " summoned-only), " + num2 + " items, " + num3 + " weapons, " + num4 + " category pages for " + list2.Count + " user(s). Vanilla: " + (lib.m_monsters.Count - num) + "/" + (lib.m_items.Count - num2) + "/" + (lib.m_weapons.Count - num3)));
		}

		public static string Key(GameObject obj, string type)
		{
			string text = (((Object)(object)obj != (Object)null) ? ((Object)obj).name : null);
			if (text != null && text.EndsWith(")") && text.Length >= 7)
			{
				text = text.Substring(0, text.Length - 7);
			}
			if (!string.IsNullOrEmpty(type))
			{
				return (text ?? string.Empty) + type;
			}
			return text ?? string.Empty;
		}

		private static bool Add(List<LibraryEntry> list, Dictionary<string, LibraryEntry> dict, LibraryEntry e, List<string> users)
		{
			string text = Key(e.m_prefab, e.m_type);
			if (string.IsNullOrEmpty(text) || dict.ContainsKey(text))
			{
				FurtherCore.Log.LogWarning((object)("Library: skipped '" + text + "' (empty or already in the library)"));
				return false;
			}
			foreach (string user in users)
			{
				e.CreateSyncData(user);
			}
			dict.Add(text, e);
			s_keys[text] = e;
			if (e.m_otherPrefabs != null)
			{
				LibraryEntryAdditional[] otherPrefabs = e.m_otherPrefabs;
				foreach (LibraryEntryAdditional val in otherPrefabs)
				{
					string text2 = Key(val.m_prefab, val.m_type);
					if (!string.IsNullOrEmpty(text2) && !dict.ContainsKey(text2))
					{
						dict.Add(text2, e);
						s_keys[text2] = e;
					}
				}
			}
			list.Add(e);
			s_mod.Add(e);
			return true;
		}

		private static List<string> KnownUsers(SystemLibrary lib)
		{
			List<string> list = new List<string>();
			try
			{
				if (Singleton<SystemUsers>.HasInstance())
				{
					foreach (UserData user in Singleton<SystemUsers>.Get.GetUsers())
					{
						if (user != null && !string.IsNullOrEmpty(user.GetUid()) && !list.Contains(user.GetUid()))
						{
							list.Add(user.GetUid());
						}
					}
				}
				if (R.Get<object>(lib, "m_usersCompletionStats") is IDictionary dictionary)
				{
					foreach (object key in dictionary.Keys)
					{
						string text = key as string;
						if (!string.IsNullOrEmpty(text) && !list.Contains(text))
						{
							list.Add(text);
						}
					}
				}
				foreach (string key2 in s_pending.Keys)
				{
					if (!list.Contains(key2))
					{
						list.Add(key2);
					}
				}
			}
			catch (Exception ex)
			{
				FurtherCore.Log.LogWarning((object)("Library: user scan: " + ex.Message));
			}
			return list;
		}

		private static HashSet<GameObject> Reachable()
		{
			HashSet<GameObject> hashSet = new HashSet<GameObject>();
			Stack<Player> stack = new Stack<Player>();
			try
			{
				List<Deity> deities = SystemDeity.GetDeities();
				if (deities != null)
				{
					foreach (Deity item in deities)
					{
						GameObject[] array = ((item != null) ? item.GetStartingMonsters() : null);
						if (array == null)
						{
							continue;
						}
						GameObject[] array2 = array;
						foreach (GameObject val in array2)
						{
							if ((Object)(object)val != (Object)null)
							{
								Player component = val.GetComponent<Player>();
								if ((Object)(object)component != (Object)null)
								{
									stack.Push(component);
								}
							}
						}
					}
				}
			}
			catch (Exception ex)
			{
				FurtherCore.Log.LogWarning((object)("Library: roster scan: " + ex.Message));
			}
			while (stack.Count > 0)
			{
				Player val2 = stack.Pop();
				if ((Object)(object)val2 == (Object)null || !hashSet.Add(((Component)val2).gameObject))
				{
					continue;
				}
				Player[] evolveTo = val2.GetEvolveTo();
				if (evolveTo == null)
				{
					continue;
				}
				Player[] array3 = evolveTo;
				foreach (Player val3 in array3)
				{
					if ((Object)(object)val3 != (Object)null && !hashSet.Contains(((Component)val3).gameObject))
					{
						stack.Push(val3);
					}
				}
			}
			return hashSet;
		}

		private static HashSet<GameObject> Playable()
		{
			HashSet<GameObject> hashSet = Reachable();
			Stack<Player> stack = new Stack<Player>();
			foreach (SecretDef item in Secrets.All)
			{
				Player val = SecretMonster(item);
				if ((Object)(object)val != (Object)null)
				{
					stack.Push(val);
				}
			}
			while (stack.Count > 0)
			{
				Player val2 = stack.Pop();
				if ((Object)(object)val2 == (Object)null || !hashSet.Add(((Component)val2).gameObject))
				{
					continue;
				}
				Player[] evolveTo = val2.GetEvolveTo();
				if (evolveTo == null)
				{
					continue;
				}
				Player[] array = evolveTo;
				foreach (Player val3 in array)
				{
					if ((Object)(object)val3 != (Object)null && !hashSet.Contains(((Component)val3).gameObject))
					{
						stack.Push(val3);
					}
				}
			}
			return hashSet;
		}

		public static Player SecretMonster(SecretDef se)
		{
			if (se == null || string.IsNullOrEmpty(se.id))
			{
				return null;
			}
			bool flag = se.id.StartsWith("Mod", StringComparison.Ordinal);
			if (!se.monster && !flag)
			{
				return null;
			}
			if (!MonsterFactory.Built.TryGetValue(flag ? se.id.Substring(3) : se.id, out var value))
			{
				return null;
			}
			return value;
		}

		public static void RefreshChallenges()
		{
			if ((Object)(object)s_lib == (Object)null)
			{
				return;
			}
			HashSet<GameObject> hashSet = Playable();
			s_challenge.Clear();
			foreach (LibraryEntryMonster monster in s_lib.m_monsters)
			{
				if (monster != null && s_mod.Contains((LibraryEntry)(object)monster) && !((Object)(object)((LibraryEntry)monster).m_prefab == (Object)null))
				{
					int num = Challenges.GoalOf(((LibraryEntry)monster).m_prefab.GetComponent<Player>(), hashSet.Contains(((LibraryEntry)monster).m_prefab));
					monster.m_targetScore = ((num > 0) ? num : 9999);
					if (num > 0)
					{
						s_challenge.Add((LibraryEntry)(object)monster);
					}
				}
			}
		}

		internal static int ModChallengesPassed()
		{
			int num = 0;
			foreach (LibraryEntry item in s_challenge)
			{
				LibraryEntryMonster val = (LibraryEntryMonster)(object)((item is LibraryEntryMonster) ? item : null);
				if (val != null && val.GetHighScore(string.Empty) >= val.m_targetScore)
				{
					num++;
				}
			}
			return num;
		}

		internal static List<KeyValuePair<int, string>> ChallengeLines(MenuLibrary lib, LibraryEntryMonster e)
		{
			List<KeyValuePair<int, string>> list = new List<KeyValuePair<int, string>>();
			if ((Object)(object)lib == (Object)null || !HasChallenge((LibraryEntry)(object)e))
			{
				return list;
			}
			int highScore = e.GetHighScore(string.Empty);
			bool flag = (!Singleton<SystemDebug>.HasInstance() || !Singleton<SystemDebug>.Get.m_challengeModeHidePassedFeature) && highScore > 0 && highScore >= e.m_targetScore;
			string text;
			if (highScore == 0)
			{
				text = R.Get<string>(lib, "m_stringHeroChallengeNotAttempted");
			}
			else
			{
				string text2 = R.Get<string>(lib, "m_stringHeroChallenge") ?? string.Empty;
				try
				{
					text = string.Format(text2, e.GetLastScore(), highScore);
				}
				catch (FormatException)
				{
					text = text2;
				}
			}
			List<string> list2 = new List<string>();
			string[] array = (text ?? string.Empty).Replace("\r", string.Empty).Split(new char[1] { '\n' });
			foreach (string text3 in array)
			{
				if (text3.Trim().Length > 0)
				{
					list2.Add(text3.Trim());
				}
			}
			if (list2.Count > 0)
			{
				list.Add(new KeyValuePair<int, string>(2 + list2.Count - 1, list2[list2.Count - 1]));
			}
			List<string> list3 = Headings(R.Get<GUIText>(lib, "m_textDescriptionMonster"));
			if (flag)
			{
				foreach (string item in Headings(R.Get<GUIText>(lib, "m_textDescriptionMonsterPassed")))
				{
					if (!list3.Contains(item))
					{
						list.Add(new KeyValuePair<int, string>(1, item));
					}
				}
			}
			for (int j = 0; j < list2.Count - 1; j++)
			{
				list.Add(new KeyValuePair<int, string>(2 + j, list2[j]));
			}
			if (list3.Count > 0)
			{
				list.Add(new KeyValuePair<int, string>(0, list3[0]));
			}
			return list;
		}

		private static List<string> Headings(GUIText holder)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			List<KeyValuePair<float, string>> list = new List<KeyValuePair<float, string>>();
			if ((Object)(object)holder != (Object)null)
			{
				TextMesh[] componentsInChildren = ((Component)holder).GetComponentsInChildren<TextMesh>(true);
				foreach (TextMesh val in componentsInChildren)
				{
					if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)(object)((Component)holder).gameObject) && !string.IsNullOrEmpty(val.text))
					{
						float y = ((Component)holder).transform.InverseTransformPoint(((Component)val).transform.position).y;
						list.Add(new KeyValuePair<float, string>(y, val.text.Replace("\r", string.Empty).Trim()));
					}
				}
			}
			list.Sort((KeyValuePair<float, string> a, KeyValuePair<float, string> b) => b.Key.CompareTo(a.Key));
			List<string> list2 = new List<string>();
			foreach (KeyValuePair<float, string> item in list)
			{
				if (item.Value.Length > 0)
				{
					list2.Add(item.Value);
				}
			}
			return list2;
		}

		public static void ChallengeSelfCheck(Action<string> bad, Action<string> note)
		{
			string[] array = new string[7] { "m_stringHeroChallenge", "m_stringHeroChallengeNotAttempted", "m_stringMonstersCategorySummary", "m_textDescriptionMonster", "m_textDescriptionMonsterPassed", "m_selectedCategory", "m_menuItemsMonster" };
			foreach (string text in array)
			{
				if ((object)AccessTools.Field(typeof(MenuLibrary), text) == null)
				{
					bad("MenuLibrary." + text + " not found (mod monster challenge pages)");
				}
			}
			if ((object)AccessTools.Method(typeof(MenuLibrary), "StartChallenge", (Type[])null, (Type[])null) == null)
			{
				bad("MenuLibrary.StartChallenge not found");
			}
			if ((object)AccessTools.Method(typeof(AchievementBase), "Unlock", (Type[])null, (Type[])null) == null)
			{
				bad("AchievementBase.Unlock not found (no achievements in mod challenges)");
			}
			if ((object)AccessTools.Field(typeof(Player), "m_evolveCost") == null)
			{
				bad("Player.m_evolveCost not found (challenge goals by cost)");
			}
			if ((Object)(object)s_lib == (Object)null || !Singleton<SystemLibrary>.HasInstance())
			{
				note("the vault is not built yet: challenges are given when it is");
				return;
			}
			HashSet<GameObject> hashSet = Playable();
			int num = 0;
			int num2 = 0;
			SortedDictionary<int, int> sortedDictionary = new SortedDictionary<int, int>();
			foreach (KeyValuePair<string, Player> item in MonsterFactory.Built)
			{
				Player value = item.Value;
				if ((Object)(object)value == (Object)null)
				{
					continue;
				}
				string name = ((Object)((Component)value).gameObject).name;
				if (!name.StartsWith("Mod", StringComparison.Ordinal))
				{
					bad(name + ": prefab name does not start with Mod (its save key would not be a mod key)");
				}
				LibraryEntryMonster monsterEntry = SystemLibrary.GetMonsterEntry(((Component)value).gameObject);
				if (monsterEntry == null)
				{
					bad(name + ": no vault entry, so no challenge");
					continue;
				}
				if (!IsMod((LibraryEntry)(object)monsterEntry))
				{
					bad(name + ": its vault entry is not a mod entry");
				}
				if ((Object)(object)((LibraryEntry)monsterEntry).m_prefab == (Object)null || (Object)(object)((LibraryEntry)monsterEntry).m_prefab.GetComponent<Player>() != (Object)(object)value)
				{
					bad(name + ": its vault entry does not resolve to its prefab");
				}
				if ((object)SystemLibrary.GetLibraryEntry(((Component)value).gameObject, (string)null) != monsterEntry)
				{
					bad(name + ": its save key does not find its vault entry");
				}
				bool flag = Challenges.GoalOf(value, hashSet.Contains(((Component)value).gameObject)) > 0;
				if (flag != HasChallenge((LibraryEntry)(object)monsterEntry))
				{
					bad(name + (flag ? ": should have a challenge but has none" : ": has a challenge it should not have"));
				}
				if (HasChallenge((LibraryEntry)(object)monsterEntry))
				{
					num++;
					if (monsterEntry.m_targetScore < 1 || monsterEntry.m_targetScore > 30)
					{
						bad(name + ": challenge goal " + monsterEntry.m_targetScore + " is out of range");
					}
					sortedDictionary.TryGetValue(monsterEntry.m_targetScore, out var value2);
					sortedDictionary[monsterEntry.m_targetScore] = value2 + 1;
				}
				else
				{
					num2++;
					if (monsterEntry.m_targetScore != 9999)
					{
						bad(name + ": no challenge, but its goal is " + monsterEntry.m_targetScore);
					}
				}
			}
			List<string> list = new List<string>();
			foreach (KeyValuePair<int, int> item2 in sortedDictionary)
			{
				list.Add("level " + item2.Key + " x" + item2.Value);
			}
			note(num + " mod monsters have a challenge (" + string.Join(", ", list.ToArray()) + "), " + num2 + " have none (minions and blobs)");
		}

		private static List<string> MonsterOrder()
		{
			List<string> list = new List<string>();
			HashSet<string> hashSet = new HashSet<string>();
			string text = null;
			foreach (Vault.MonsterLine monsterLine in Vault.MonsterLines)
			{
				string text2 = GroupOf(monsterLine.id);
				if (text2 != text)
				{
					if (text != null)
					{
						AddFromTips(list, hashSet, text);
					}
					text = text2;
				}
				if (MonsterFactory.Built.ContainsKey(monsterLine.id) && hashSet.Add(monsterLine.id))
				{
					list.Add(monsterLine.id);
				}
			}
			if (text != null)
			{
				AddFromTips(list, hashSet, text);
			}
			AddFromTips(list, hashSet, null);
			foreach (string key in MonsterFactory.Built.Keys)
			{
				if (hashSet.Add(key))
				{
					list.Add(key);
				}
			}
			return list;
		}

		private static string GroupOf(string id)
		{
			if (!TipRegistry.Group.TryGetValue("Mod" + id, out var value))
			{
				return null;
			}
			return value;
		}

		private static void AddFromTips(List<string> order, HashSet<string> seen, string group)
		{
			foreach (string item in TipRegistry.VaultOrder)
			{
				if (item != null && item.StartsWith("Mod", StringComparison.Ordinal) && (group == null || (TipRegistry.Group.TryGetValue(item, out var value) && !(value != group))))
				{
					string text = item.Substring(3);
					if (MonsterFactory.Built.ContainsKey(text) && seen.Add(text))
					{
						order.Add(text);
					}
				}
			}
		}

		private static Info Lookup(string id)
		{
			foreach (Vault.MonsterLine monsterLine in Vault.MonsterLines)
			{
				if (monsterLine.id == id)
				{
					return new Info(monsterLine.name, monsterLine.line);
				}
			}
			VaultRegistry.Entry entry = Registered("Monsters", id);
			if (entry != null && !string.IsNullOrEmpty(entry.name))
			{
				return new Info(entry.name, entry.text ?? string.Empty);
			}
			if (TipRegistry.Vault.TryGetValue("Mod" + id, out var value) && !string.IsNullOrEmpty(value.Key))
			{
				return new Info(value.Key, value.Value);
			}
			if (TipRegistry.TryGet("Mod" + id, out var tip) && !string.IsNullOrEmpty(tip.name))
			{
				FurtherCore.Log.LogWarning((object)("Library: no vault text for " + id + ", using its monster tip"));
				string d = tip.attack + ((string.IsNullOrEmpty(tip.special) || tip.special.StartsWith("none")) ? "" : (". " + tip.special));
				return new Info(tip.name, d);
			}
			FurtherCore.Log.LogWarning((object)("Library: no vault text for " + id));
			return new Info(Words(id), string.Empty);
		}

		public static string PictureAnim(SpriteSheet sh)
		{
			if (sh == null)
			{
				return null;
			}
			string[] array = new string[3] { "Portrait", "Vault", "Idle" };
			foreach (string text in array)
			{
				if (sh.Has(text))
				{
					return text;
				}
			}
			return null;
		}

		public static void MonsterInfo(string id, out string name, out string text)
		{
			Info info = Lookup(id);
			name = info.name;
			text = info.desc;
		}

		private static VaultRegistry.Entry Registered(string category, string id)
		{
			foreach (VaultRegistry.Entry entry in VaultRegistry.Entries)
			{
				if (entry != null && entry.category == category && (entry.id == id || entry.id == "Mod" + id))
				{
					return entry;
				}
			}
			return null;
		}

		public static List<LibraryEntry> EntriesOf(VaultCategory c)
		{
			if (c == null)
			{
				return s_none;
			}
			if (c.secrets)
			{
				return SecretList;
			}
			if (!s_pages.TryGetValue(c, out var value))
			{
				return s_none;
			}
			return value;
		}

		public static List<KeyValuePair<VaultPage, LibraryEntry>> PagesOf(VaultCategory c)
		{
			List<KeyValuePair<VaultPage, LibraryEntry>> list = new List<KeyValuePair<VaultPage, LibraryEntry>>();
			foreach (LibraryEntry item in EntriesOf(c))
			{
				if (s_pageInfo.TryGetValue(item, out var value))
				{
					list.Add(new KeyValuePair<VaultPage, LibraryEntry>(value.page, item));
				}
			}
			return list;
		}

		private static int AddPages(List<LibraryEntry> list, Dictionary<string, LibraryEntry> dict, List<string> users)
		{
			int num = 0;
			foreach (VaultCategory category in Vault.Categories)
			{
				if (category.secrets || category.pages == null)
				{
					continue;
				}
				List<LibraryEntry> list2 = new List<LibraryEntry>();
				s_pages[category] = list2;
				HashSet<string> names = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
				IEnumerable<VaultPage> enumerable;
				try
				{
					enumerable = category.pages();
				}
				catch (Exception ex)
				{
					FurtherCore.Log.LogError((object)("Vault " + category.label + " pages: " + ex));
					continue;
				}
				if (enumerable == null)
				{
					continue;
				}
				foreach (VaultPage item in enumerable)
				{
					LibraryEntry val = AddPage(list, dict, users, names, category, item);
					if (val != null)
					{
						list2.Add(val);
						num++;
					}
				}
			}
			return num;
		}

		private static LibraryEntry AddPage(List<LibraryEntry> list, Dictionary<string, LibraryEntry> dict, List<string> users, HashSet<string> names, VaultCategory cat, VaultPage p)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			if (p == null || string.IsNullOrEmpty(p.id) || string.IsNullOrEmpty(p.name) || !names.Add(p.name))
			{
				return null;
			}
			GameObject val = Holder(KeyName("ModVault" + p.kind, p.id));
			LibraryEntry val2 = new LibraryEntry
			{
				m_prefab = val,
				m_type = string.Empty,
				m_name = p.name,
				m_description = (p.text ?? string.Empty),
				m_portrait = PageClip(p.art, "ModVault_" + ((Object)val).name),
				m_startFound = true
			};
			if (!Add(list, dict, val2, users))
			{
				return null;
			}
			s_pageInfo[val2] = new PageInfo
			{
				cat = cat,
				page = p,
				text = val2.m_description
			};
			return val2;
		}

		private static string KeyName(string prefix, string id)
		{
			StringBuilder stringBuilder = new StringBuilder(prefix);
			foreach (char c in id)
			{
				if (char.IsLetterOrDigit(c))
				{
					stringBuilder.Append(c);
				}
			}
			return stringBuilder.ToString();
		}

		private static GameObject Holder(string name)
		{
			//IL_0032: 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_004e: Expected O, but got Unknown
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			if ((Object)(object)s_vaultHolder == (Object)null)
			{
				s_vaultHolder = new GameObject("CrawlMod_VaultEntries");
				s_vaultHolder.SetActive(false);
				Object.DontDestroyOnLoad((Object)(object)s_vaultHolder);
			}
			GameObject val = new GameObject(name);
			val.transform.SetParent(s_vaultHolder.transform, false);
			return val;
		}

		private static exSpriteAnimClip PageClip(string art, string clipName)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			SpriteSheet spriteSheet = (string.IsNullOrEmpty(art) ? null : SpriteSheets.Get(art));
			if (spriteSheet == null || (Object)(object)spriteSheet.atlas == (Object)null || (Object)(object)spriteSheet.atlas.texture == (Object)null)
			{
				return null;
			}
			string text = PictureAnim(spriteSheet);
			exSpriteAnimClip val = ((text != null) ? SpriteSheets.MakeClip(spriteSheet, text, null, clipName) : null);
			if ((Object)(object)val != (Object)null)
			{
				val.wrapMode = (WrapMode)2;
			}
			return val;
		}

		public static bool IsLocked(LibraryEntry e)
		{
			if (e == null || !s_pageInfo.TryGetValue(e, out var value))
			{
				return false;
			}
			if (value.page.locked != null)
			{
				try
				{
					return value.page.locked();
				}
				catch
				{
					return false;
				}
			}
			if (value.page.unlock != null)
			{
				return !Unlocks.IsUnlocked(value.page.unlock);
			}
			return false;
		}

		public static void RefreshPages(VaultCategory c)
		{
			foreach (LibraryEntry item in EntriesOf(c))
			{
				if (s_pageInfo.TryGetValue(item, out var value))
				{
					if (!VaultGrid.Alive(item.m_portrait))
					{
						item.m_portrait = PageClip(value.page.art, "ModVault_" + value.page.kind + value.page.id);
					}
					string text = value.text;
					if (IsLocked(item) && value.page.unlock != null)
					{
						UnlockDef unlockDef = Unlocks.Find(value.page.unlock);
						text = "LOCKED" + ((unlockDef != null && !string.IsNullOrEmpty(unlockDef.title)) ? (": " + unlockDef.title) : "") + "\n" + Unlocks.ProgressText(value.page.unlock) + "\n" + text;
					}
					item.m_description = text;
				}
			}
		}

		public static bool HasNew(VaultCategory c)
		{
			if (c != null && c.secrets)
			{
				return SecretsHaveNew();
			}
			try
			{
				foreach (LibraryEntry item in EntriesOf(c))
				{
					if (item.IsNew(string.Empty))
					{
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		public static void Se