Decompiled source of TitlesMod v0.16.8

TitlesMod.dll

Decompiled 16 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn;
using Jotunn.Entities;
using Jotunn.GUI;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using Splatform;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("TitlesMod")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("TitlesMod")]
[assembly: AssemblyTitle("TitlesMod")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace TitlesMod
{
	internal static class AchievementTitles
	{
		private static bool registered;

		private static IEnumerable<Achievement> All()
		{
			Achievements instance = Achievements.m_instance;
			if ((Object)(object)instance == (Object)null || instance.m_achievementLists == null)
			{
				return Enumerable.Empty<Achievement>();
			}
			return from a in instance.m_achievementLists.Where((AchievementList l) => (Object)(object)l != (Object)null && l.m_achievements != null).SelectMany((AchievementList l) => l.m_achievements)
				where (Object)(object)a != (Object)null
				select a;
		}

		public static bool AnyUnlocked()
		{
			return All().Any((Achievement a) => a.m_unlocked);
		}

		public static void TryRegister()
		{
			if (registered || (Object)(object)Achievements.m_instance == (Object)null || Localization.instance == null)
			{
				return;
			}
			registered = true;
			int num = 0;
			HashSet<string> hashSet = new HashSet<string>();
			foreach (Achievement item in All())
			{
				if (!string.IsNullOrEmpty(item.m_id) && hashSet.Add(item.m_id))
				{
					Achievement a = item;
					string text = Localize(a.m_name, a.m_id);
					TitleDefinition titleDefinition = new TitleDefinition("ach_" + a.m_id, text, "Achievement: " + Localize(a.m_description, text) + ".").Require(TitleRequirement.Custom((Player _) => a.m_unlocked, "Unlock the achievement " + text));
					if (a.m_isSecret)
					{
						titleDefinition.SetHidden();
					}
					if (TitleAPI.RegisterTitle(titleDefinition))
					{
						num++;
					}
				}
			}
			Logger.LogInfo((object)$"Registered {num} achievement titles.");
		}

		private static string Localize(string token, string fallback)
		{
			if (string.IsNullOrEmpty(token))
			{
				return fallback;
			}
			string text = Localization.instance.Localize(token).Trim().TrimEnd(new char[1] { '.' });
			return string.IsNullOrEmpty(text) ? fallback : text;
		}
	}
	internal static class BuildPerks
	{
		[HarmonyPatch(typeof(Player), "PlacePiece")]
		private static class FreeBuildRoll
		{
			private static void Postfix(Player __instance, Piece piece)
			{
				if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !((Object)(object)piece == (Object)null))
				{
					float statBonus = TitleManager.GetStatBonus("FreeBuildChance");
					if (statBonus > 0f && Random.value * 100f < statBonus && IsWoodOrStone(piece))
					{
						freeBuildFrame = Time.frameCount;
					}
				}
			}
		}

		[HarmonyPatch(typeof(Player), "ConsumeResources")]
		private static class FreeBuildConsume
		{
			private static bool Prefix(Player __instance)
			{
				if (freeBuildFrame != Time.frameCount || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
				{
					return true;
				}
				freeBuildFrame = -1;
				((Character)__instance).Message((MessageType)1, "Built for free!", 0, (Sprite)null, false);
				return false;
			}
		}

		[HarmonyPatch(typeof(WearNTear), "Repair")]
		private static class RepairCount
		{
			private static void Postfix(bool __result)
			{
				if (__result && !auraRepairing)
				{
					TitleManager.Increment("repair");
				}
			}
		}

		internal const string RepairCounter = "repair";

		private static int freeBuildFrame = -1;

		private static bool auraRepairing;

		private static bool IsWoodOrStone(Piece piece)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected I4, but got Unknown
			WearNTear component = ((Component)piece).GetComponent<WearNTear>();
			if ((Object)(object)component == (Object)null)
			{
				return false;
			}
			MaterialType materialType = component.m_materialType;
			MaterialType val = materialType;
			switch ((int)val)
			{
			case 0:
			case 1:
			case 3:
			case 4:
			case 5:
			case 8:
				return true;
			default:
				return false;
			}
		}

		public static void Tick(Player player)
		{
			//IL_0026: 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_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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			float statBonus = TitleManager.GetStatBonus("RepairAura");
			if (statBonus <= 0f)
			{
				return;
			}
			Vector3 position = ((Component)player).transform.position;
			float num = statBonus * statBonus;
			auraRepairing = true;
			try
			{
				foreach (WearNTear allInstance in WearNTear.GetAllInstances())
				{
					if ((Object)(object)allInstance == (Object)null)
					{
						continue;
					}
					Vector3 val = ((Component)allInstance).transform.position - position;
					if (!(((Vector3)(ref val)).sqrMagnitude > num) && !(allInstance.GetHealthPercentage() >= 1f))
					{
						Piece component = ((Component)allInstance).GetComponent<Piece>();
						if (!((Object)(object)component == (Object)null) && component.IsPlacedByPlayer() && PrivateArea.CheckAccess(((Component)allInstance).transform.position, 0f, false, false))
						{
							allInstance.Repair();
						}
					}
				}
			}
			finally
			{
				auraRepairing = false;
			}
		}
	}
	internal static class DefaultTitles
	{
		private class Perk
		{
			public string Stat;

			public float PerTier;

			public float First;

			public float Last;

			public bool Range;

			public float Amount(int tier)
			{
				return Range ? Mathf.Round(First + (Last - First) * (float)tier / (float)(TierLevels.Length - 1)) : (PerTier * (float)(tier + 1));
			}
		}

		private class Milestone
		{
			public string Skill;

			public string Label;

			public string Noun;

			public Perk[] Perks;
		}

		private static readonly string[] Bosses = new string[7] { "boss_eikthyr", "boss_elder", "boss_bonemass", "boss_moder", "boss_yagluth", "boss_queen", "boss_fader" };

		public const string PaladinModGuid = "com.yourname.paladinmod";

		private static readonly string[] ConsecratedShields = new string[6] { "ConsecratedShieldWoodTower", "ConsecratedShieldBoneTower", "ConsecratedShieldIronTower", "ConsecratedShieldSerpentscale", "ConsecratedShieldBlackmetalTower", "ConsecratedShieldFlametalTower" };

		private static readonly string[] Pronouns = new string[9] { "He/Him", "She/Her", "They/Them", "He/They", "She/They", "It/Its", "Xe/Xem", "Ze/Zir", "Any Pronouns" };

		private static readonly string[] Colours = new string[10] { "Red", "Blue", "Yellow", "Pink", "Purple", "Green", "Orange", "Crimson", "Black", "Golden" };

		private static readonly string[] Emotions = new string[25]
		{
			"Happy", "Sad", "Depressed", "Bubbly", "Curious", "Angry", "Grumpy", "Calm", "Anxious", "Excited",
			"Bored", "Brave", "Shy", "Cheerful", "Gloomy", "Jolly", "Moody", "Sleepy", "Hungry", "Lonely",
			"Proud", "Silly", "Confused", "Loving", "Fearless"
		};

		private static readonly string[] Descriptors = new string[17]
		{
			"Thick", "Large", "Small", "Tiny", "Huge", "Long", "Short", "Tall", "Big", "Little",
			"Giant", "Massive", "Mini", "Slim", "Chunky", "Round", "Wide"
		};

		private static readonly string[] Identities = new string[24]
		{
			"Straight", "Gay", "Lesbian", "Bi", "Pan", "Ace", "Aro", "Demi", "Queer", "Questioning",
			"Cis", "Trans", "Nonbinary", "Enby", "Genderfluid", "Genderqueer", "Agender", "Intersex", "Two-Spirit", "Man",
			"Woman", "Boy", "Girl", "Ally"
		};

		private static readonly int[] TierLevels = new int[6] { 10, 25, 50, 75, 90, 100 };

		private static readonly string[] TierRanks = new string[6] { "Novice", "Apprentice", "Adept", "Veteran", "Master", "Legendary" };

		private static readonly Milestone[] Milestones = new Milestone[24]
		{
			M("Swords", "Swords", "Duelist", P("StaminaRegen", 2f)),
			M("Knives", "Knives", "Assassin", P("SneakAttack", 10f)),
			M("Clubs", "Clubs", "Bonebreaker", P("Armor", 1f)),
			M("Polearms", "Polearms", "Halberdier", P("MaxHealth", 3f)),
			M("Spears", "Spears", "Lancer", P("MaxStamina", 3f)),
			M("Axes", "Axes", "Reaver", P("Armor", 1f)),
			M("Bows", "Bows", "Archer", P("StaminaRegen", 2f)),
			M("Crossbows", "Crossbows", "Arbalist", P("ReloadSpeed", 5f)),
			M("Unarmed", "Unarmed", "Brawler", P("StaggerBonus", 10f)),
			M("Blocking", "Blocking", "Bulwark", P("BlockStamina", 3f)),
			M("ElementalMagic", "Elemental Magic", "Elementalist", P("EitrRegen", 3f)),
			M("BloodMagic", "Blood Magic", "Bloodbinder", P("SpellHealthCost", 5f), P("MaxEitr", 2f)),
			M("Pickaxes", "Pickaxes", "Miner", P("MiningDamage", 4f)),
			M("WoodCutting", "Wood Cutting", "Woodcutter", P("ChopDamage", 4f)),
			M("Run", "Run", "Runner", P("RunStamina", 3f), P("CarryWeight", 5f)),
			M("Jump", "Jump", "Leaper", R("JumpStamina", 4f, 40f), R("FallDamage", 5f, 50f)),
			M("Sneak", "Sneak", "Shadow", P("SneakStamina", 4f)),
			M("Swim", "Swim", "Swimmer", P("SwimStamina", 4f)),
			M("Dodge", "Dodge", "Evader", P("DodgeStamina", 3f)),
			M("Ride", "Ride", "Rider", P("MaxStamina", 2f)),
			M("Fishing", "Fishing", "Angler", P("StaminaRegen", 2f)),
			M("Cooking", "Cooking", "Cook", P("ExtraCookChance", 5f)),
			M("Farming", "Farming", "Farmer", P("ExtraHarvestChance", 5f)),
			M("Crafting", "Crafting", "Artisan", P("CarryWeight", 10f))
		};

		public static void Register()
		{
			Add(Title("biome_meadows", "Meadows", "Enter the Meadows.").Require(TitleRequirement.DiscoverBiome((Biome)1)).Bonus("Bows", 5f));
			Add(Title("biome_blackforest", "Black Forest", "Enter the Black Forest.").Require(TitleRequirement.DiscoverBiome((Biome)8)).Bonus("WoodCutting", 5f));
			Add(Title("biome_swamp", "Swamp", "Enter the Swamp.").Require(TitleRequirement.DiscoverBiome((Biome)2)).Bonus("Sneak", 5f));
			Add(Title("biome_mountain", "Mountains", "Enter the Mountains.").Require(TitleRequirement.DiscoverBiome((Biome)4)).Bonus("Jump", 5f));
			Add(Title("biome_ocean", "Ocean", "Reach the Ocean.").Require(TitleRequirement.DiscoverBiome((Biome)256)).Bonus("Swim", 5f));
			Add(Title("biome_plains", "Plains", "Enter the Plains.").Require(TitleRequirement.DiscoverBiome((Biome)16)).Bonus("Ride", 5f));
			Add(Title("biome_mistlands", "Mistlands", "Enter the Mistlands.").Require(TitleRequirement.DiscoverBiome((Biome)512)).Bonus("Dodge", 5f));
			Add(Title("biome_ashlands", "Ashlands", "Enter the Ashlands.").Require(TitleRequirement.DiscoverBiome((Biome)32)).Bonus("Blocking", 5f));
			Add(Title("biome_deepnorth", "Deep North", "Enter the Deep North.").Require(TitleRequirement.DiscoverBiome((Biome)64)).Bonus("Run", 5f));
			Add(Title("biome_all", "Worldwalker", "Set foot in every biome.").Require(TitleRequirement.DiscoverBiome((Biome)1)).Require(TitleRequirement.DiscoverBiome((Biome)8)).Require(TitleRequirement.DiscoverBiome((Biome)2))
				.Require(TitleRequirement.DiscoverBiome((Biome)4))
				.Require(TitleRequirement.DiscoverBiome((Biome)256))
				.Require(TitleRequirement.DiscoverBiome((Biome)16))
				.Require(TitleRequirement.DiscoverBiome((Biome)512))
				.Require(TitleRequirement.DiscoverBiome((Biome)32))
				.Require(TitleRequirement.DiscoverBiome((Biome)64))
				.Bonus("All", 20f));
			AddDungeon((Theme)8, "Burial Chambers", "burial", "Burial", "chamber", "Chamber", "dungeon", "Dungeon");
			AddDungeon((Theme)512, "the Smouldering Tomb", "smouldering", "Smouldering", "tomb", "Tomb");
			AddDungeon((Theme)2, "a Sunken Crypt", "sunken", "Sunken", "crypt", "Crypt");
			AddDungeon((Theme)4, "a Frost Cave", "cave", "Cave");
			AddDungeon((Theme)1024, "the Howling Cavern", "howling", "Howling", "cavern", "Cavern");
			AddDungeon((Theme)2048, "the Sealed Tower", "sealed", "Sealed", "tower", "Tower");
			AddDungeon((Theme)128, "an Infested Mine", "infested", "Infested", "mine", "Mine");
			AddDungeon((Theme)8192, "a Charred fortress", "fortress", "Fortress");
			string[] array = new string[7] { "Copper", "Tin", "Bronze", "Iron", "Silver", "Black Metal", "Flametal" };
			string[][] array2 = new string[7][]
			{
				new string[1] { "Copper" },
				new string[1] { "Tin" },
				new string[1] { "Bronze" },
				new string[1] { "Iron" },
				new string[1] { "Silver" },
				new string[1] { "BlackMetal" },
				new string[2] { "FlametalNew", "Flametal" }
			};
			for (int i = 0; i < array.Length; i++)
			{
				TitleRequirement[] bars = array2[i].Select(TitleRequirement.DiscoverItem).ToArray();
				string text = "Have " + array[i].ToLowerInvariant() + " in your inventory";
				Add(Title("metal_" + array[i].ToLowerInvariant().Replace(" ", "_"), array[i], text + ".").Require((bars.Length == 1) ? bars[0] : TitleRequirement.Custom((Player p) => bars.Any((TitleRequirement r) => r.IsMet(p)), text)).Stat("CarryWeight", 5 * (i + 1)).SetGroup("metal"));
			}
			Add(Title("recipe_cultivator", "Gardener", "Learn to craft a cultivator.").Require(TitleRequirement.KnowRecipe("Cultivator")).Bonus("Farming", 5f));
			Add(Title("recipe_fishingrod", "Fisher", "Learn to craft a fishing rod.").Require(TitleRequirement.KnowRecipe("FishingRod")).Bonus("Fishing", 5f));
			Add(Title("gather_wood", "Lumberjack", "Gather 500 wood.").Require(TitleRequirement.Gather("Wood", 500)).Bonus("WoodCutting", 5f));
			Add(Title("gather_copper", "Prospector", "Gather 250 copper ore.").Require(TitleRequirement.Gather("CopperOre", 250)).Bonus("Pickaxes", 5f));
			Add(Title("gather_deerhide", "Huntsman", "Gather 50 deer hides.").Require(TitleRequirement.Gather("DeerHide", 50)).Bonus("Bows", 5f));
			string[] array3 = new string[5] { "Arrow Maker", "Arrows", "Fletcher", "Master Fletcher", "Legendary Fletcher" };
			string[] array4 = new string[5] { "Bolt Maker", "Bolts", "Boltwright", "Master Boltwright", "Legendary Boltwright" };
			for (int num = 0; num < 5; num++)
			{
				int num2 = 100 * (num + 1);
				Add(Title($"craft_arrows_{num2}", array3[num], $"Craft {num2} arrows.").Require(TitleRequirement.CraftAmmo("$ammo_arrows", num2, "Craft arrows")).Stat("ExtraArrows", num + 1).SetGroup("arrows"));
				Add(Title($"craft_bolts_{num2}", array4[num], $"Craft {num2} crossbow bolts.").Require(TitleRequirement.CraftAmmo("$ammo_bolts", num2, "Craft bolts")).Stat("ExtraBolts", num + 1).SetGroup("bolts"));
			}
			AddBuildTier("build_10", "DIY", 10, 1);
			AddBuildTier("build_100", "Handyman", 100, 2);
			AddBuildTier("build_100f", "Handywoman", 100, 2);
			AddBuildTier("build_1000", "Builder", 1000, 3);
			AddBuildTier("build_5000", "Designer", 5000, 4);
			AddBuildTier("build_10000", "Architect", 10000, 5);
			Add(Title("repair_100", "Fixer", "Repair 100 damaged building pieces.").Require(TitleRequirement.Counter("repair", 100, "Repair building pieces")).Stat("RepairAura", 2f).SetGroup("repair"));
			Add(Title("repair_1000", "Mender", "Repair 1000 damaged building pieces.").Require(TitleRequirement.Counter("repair", 1000, "Repair building pieces")).Stat("RepairAura", 10f).SetGroup("repair"));
			AddBoss("eikthyr", "Eikthyr", "Eikthyr", "Run");
			AddBoss("elder", "Elder", "gd_king", "WoodCutting", "The Elder");
			AddBoss("bonemass", "Bonemass", "Bonemass", "Clubs");
			AddBoss("moder", "Moder", "Dragon", "Swords");
			AddBoss("yagluth", "Yagluth", "GoblinKing", "Polearms");
			AddBoss("queen", "Queen", "SeekerQueen", "ElementalMagic", "the Queen");
			AddBoss("fader", "Fader", "Fader", "BloodMagic");
			TitleDefinition titleDefinition = Title("boss_all", "Godslayer", "Defeat every Forsaken.").SetHidden().Stat("MaxHealth", 50f).Stat("MaxStamina", 50f)
				.Stat("MaxEitr", 50f);
			string[] bosses = Bosses;
			foreach (string titleId in bosses)
			{
				titleDefinition.Require(TitleRequirement.HasTitle(titleId));
			}
			Add(titleDefinition);
			int[] array5 = new int[7] { 50, 100, 250, 500, 1000, 2500, 5000 };
			string[] array6 = new string[7] { "Killer", "Hunter", "Breaker", "Crusher", "Slayer", "Bane", "Vanquisher" };
			for (int num4 = 0; num4 < array5.Length; num4++)
			{
				Add(Title($"kill_{array5[num4]}", array6[num4], $"Defeat {array5[num4]} creatures.").Require(TitleRequirement.Kill("*", array5[num4])).Stat("MaxHealth", 5 * (num4 + 1)).Stat("Damage", num4 + 1)
					.SetGroup("kills"));
			}
			int[] array7 = new int[5] { 1, 10, 50, 100, 1000 };
			string[] array8 = new string[5] { "Dead", "Undead", "Death", "Lich", "Eternal" };
			for (int num5 = 0; num5 < array7.Length; num5++)
			{
				int num6 = array7[num5];
				Add(Title($"death_{num6}", array8[num5], (num6 == 1) ? "Die for the first time." : $"Die {num6} times.").Require(TitleRequirement.Die(num6)).Stat("DeathSkillLoss", 10 * (num5 + 1)).SetGroup("deaths"));
			}
			int[] array9 = new int[5] { 10, 50, 100, 250, 500 };
			string[] array10 = new string[5] { "Fish", "Dolphin", "Shark", "Orca", "Whale" };
			for (int num7 = 0; num7 < array9.Length; num7++)
			{
				Add(Title($"fish_{array9[num7]}", array10[num7], $"Catch {array9[num7]} fish.").Require(TitleRequirement.PlayerStat((PlayerStatType)160, array9[num7], "Catch fish")).Stat("SwimStamina", 2 * (num7 + 1)).Bonus("Fishing", 2 * (num7 + 1))
					.SetGroup("fish"));
			}
			Add(Title("run_marathon", "Marathon", "Run the length of a marathon (42.2 km) in total.").Require(TitleRequirement.PlayerStat((PlayerStatType)18, 42195f, "Run", 1000f, " km")).Stat("MaxStamina", 25f));
			int[] array11 = new int[7] { 1, 10, 20, 40, 60, 75, 100 };
			int[] array12 = new int[7] { 1, 3, 5, 7, 9, 12, 15 };
			string[] array13 = new string[7] { "Bait", "Deckhand", "Sailor", "Navigator", "Captain", "Commodore", "Admiral" };
			for (int num8 = 0; num8 < array11.Length; num8++)
			{
				Add(Title($"sail_{array11[num8]}", array13[num8], $"Sail {array11[num8]} km at the helm.").Require(TitleRequirement.PlayerStat((PlayerStatType)150, (float)array11[num8] * 1000f, "Sail at the helm", 1000f, " km")).Stat("SailSpeed", array12[num8]).SetGroup("sail"));
			}
			Add(Title("noob", "Noob", "Join a world with a brand new character.").Require(TitleRequirement.Counter("freshspawn", 1, "Start a brand new character")).Stat("MaxHealth", 5f).Stat("MaxStamina", 10f)
				.Stat("CarryWeight", 15f));
			Add(Title("cold", "Cold", "Get cold for the first time.").Require(TitleRequirement.Counter("cold", 1, "Get cold")).Stat("FireResistance", 5f).Stat("FrostWeakness", 5f));
			Add(Title("freezing", "Freezing", "Start freezing for the first time.").Require(TitleRequirement.Counter("freezing", 1, "Start freezing")).Stat("FireResistance", 10f).Stat("FrostWeakness", 10f));
			Add(Title("overweight", "Gym", "Carry more than your carry weight limit.").Require(TitleRequirement.Custom((Player p) => ((Character)p).IsEncumbered(), "Be over your carry weight limit")).Stat("CarryWeight", 10f));
			string[] array14 = new string[6] { "Mindful", "Meditator", "Serene", "Zen", "Enlightened", "Sage" };
			int[] array15 = new int[6] { 10, 60, 300, 1800, 3600, 86400 };
			int[] array16 = new int[6] { 10, 20, 30, 40, 50, 100 };
			for (int num9 = 0; num9 < array14.Length; num9++)
			{
				Add(Title($"rest_{array15[num9]}", array14[num9], "Sit while resting for " + TimeCounterRequirement.Format(array15[num9]) + ".").Require(new TimeCounterRequirement("rest:seconds", array15[num9], "Sit while resting")).Stat("EitrRegen", array16[num9]).SetGroup("rest"));
			}
			Add(Title("magic_blood_1", "Bloody", "Cast a blood magic spell for the first time.").Require(TitleRequirement.Custom((Player p) => TitleManager.GetCounter("magic:blood") > 0 || ((Character)p).GetSkillLevel((SkillType)10) > 0f, "Cast a blood magic spell")).Stat("MaxHealth", 10f).Stat("HealthRegen", 10f)
				.SetGroup("bloodmagic"));
			Add(Title("magic_blood_10", "Bloodied", "Cast 10 blood magic spells.").Require(TitleRequirement.Counter("magic:blood", 10, "Cast blood magic spells")).Stat("MaxHealth", 20f).Stat("HealthRegen", 20f)
				.SetGroup("bloodmagic"));
			Add(Title("magic_blood_50", "Blood", "Cast 50 blood magic spells.").Require(TitleRequirement.Counter("magic:blood", 50, "Cast blood magic spells")).Stat("MaxHealth", 30f).Stat("HealthRegen", 30f)
				.SetGroup("bloodmagic"));
			AddSkillGain("skills_5_above_20", "Jack of Some Trades", 5, 20, 25f, "jack");
			AddSkillGain("skills_10_above_20", "Jack of Most Trades", 10, 20, 50f, "jack");
			AddSkillGain("skills_15_above_20", "Jack of All Trades", 15, 20, 75f, "jack");
			AddSkillGain("skills_15_above_30", "Jacked", 15, 30, 100f, "jack");
			AddSkillGain("skills_3_above_50", "Skilled", 3, 50, 50f, "skilled");
			AddSkillGain("skills_5_above_50", "Skillmaxxing", 5, 50, 100f, "skilled");
			Add(Title("skills_10_tier", "Unbroken", "Get 10 skills to level 10. While equipped, dying never lowers any skill below the highest threshold it has reached.").Require(TitleRequirement.SkillsAtLeast(10, TierLevels[0])).ProtectAllSkillsAtTiers(((IEnumerable<int>)TierLevels).Select((Func<int, float>)((int l) => l)).ToArray()));
			if (Chainloader.PluginInfos.ContainsKey("com.yourname.paladinmod"))
			{
				TitleRequirement[] shields = ConsecratedShields.Select(TitleRequirement.DiscoverItem).ToArray();
				Add(new TitleDefinition("paladin_shield", "Paladin", "Craft your first consecrated shield at a Dvergr Paladin Shrine.").Require(TitleRequirement.Custom((Player p) => shields.Any((TitleRequirement r) => r.IsMet(p)), "Craft a consecrated shield")).Stat("ArmorPercent", 10f));
				string[] array17 = new string[2] { "Holy", "Divine" };
				foreach (string text2 in array17)
				{
					Add(Title("element_" + text2.ToLowerInvariant(), text2, "Strike foes 100 times with holy damage from a consecrated shield.").Require(TitleRequirement.Counter("paladin:holy", 100, "Strike with holy damage")).Stat("HolyDamage", 5f).SetGroup("holy"));
				}
			}
			Milestone[] milestones = Milestones;
			foreach (Milestone milestone in milestones)
			{
				for (int num12 = 0; num12 < TierLevels.Length; num12++)
				{
					int num13 = TierLevels[num12];
					TitleDefinition titleDefinition2 = TitleDefinition.SkillMilestone($"skill_{milestone.Skill.ToLower()}_{num13}", TierRanks[num12] + " " + milestone.Noun, milestone.Skill, num13, milestone.Label);
					Perk[] perks = milestone.Perks;
					foreach (Perk perk in perks)
					{
						titleDefinition2.Stat(perk.Stat, perk.Amount(num12));
					}
					Add(titleDefinition2);
				}
			}
			int[] array18 = new int[5] { 10, 100, 500, 1000, 5000 };
			string[] array19 = new string[5] { "Power", "Crasher", "Wrecker", "Destroyer", "Annihilator" };
			for (int num15 = 0; num15 < array18.Length; num15++)
			{
				Add(Title($"heavy_{array18[num15]}", array19[num15], $"Do {array18[num15]} heavy attacks.").Require(TitleRequirement.Counter("heavyattack", array18[num15], "Heavy attacks")).Stat("AttackStamina", 2 * (num15 + 1)).SetGroup("heavy"));
			}
			AddBerry("Raspberry", "Raspberry", "raspberries");
			AddBerry("Blueberries", "Blueberry", "blueberries");
			AddBerry("Cloudberry", "Cloudberry", "cloudberries");
			AddBerry("MushroomJotunPuffs", "Puff", "jotun puffs");
			AddBerry("Vineberry", "Vineberry", "vineberry clusters");
			float[] array20 = new float[9] { 1f, 5f, 10f, 20f, 30f, 50f, 75f, 90f, 100f };
			string[] array21 = new string[9] { "Wanderer", "Scout", "Explorer", "Pathfinder", "Trailblazer", "Cartographer", "Globetrotter", "Completionist", "Autism" };
			for (int num16 = 0; num16 < array20.Length; num16++)
			{
				Add(Title($"map_{array20[num16]:0}", array21[num16], $"Uncover {array20[num16]:0}% of a world's map yourself.").Require(new MapExploredRequirement(array20[num16])).SetGroup("map"));
			}
			int[] array22 = new int[5] { 10, 50, 100, 365, 1000 };
			string[] array23 = new string[5] { "Settler", "Pioneer", "Old-Timer", "Ancient", "Timeless" };
			for (int num17 = 0; num17 < array22.Length; num17++)
			{
				int num18 = array22[num17];
				Add(Title($"days_{num18}", array23[num17], $"Play for {num18} in-game days.").Require(TitleRequirement.Counter("days:played", num18, "Days played")).SetGroup("days"));
			}
			int[] array24 = new int[5] { 10, 50, 100, 365, 1000 };
			string[] array25 = new string[5] { "Fresh", "Rooted", "Weathered", "Venerable", "Primordial" };
			for (int num19 = 0; num19 < array24.Length; num19++)
			{
				int day = array24[num19];
				Add(Title($"worldday_{day}", array25[num19], $"Play in a world that has reached day {day}.").Require(TitleRequirement.Custom((Player _) => (Object)(object)EnvMan.instance != (Object)null && EnvMan.instance.GetDay() >= day, $"Be in a world on day {day} or later")).SetGroup("worldday"));
			}
			AddFirstKill("kill_first_valkyrie_fallen", "Fallen", "fallen valkyrie", "FallenValkyrie");
			AddFirstKill("kill_first_valkyrie_angel", "Angel", "fallen valkyrie", "FallenValkyrie");
			AddFirstKill("kill_first_chicken", "Chicken", "chicken", "Hen", "Chicken");
			AddFirstKill("kill_first_nuggets", "Nuggets", "chicken", "Hen", "Chicken");
			AddFirstKill("kill_first_deer", "Dear", "deer", "Deer");
			AddFirstKill("kill_first_boar", "Beer", "boar", "Boar");
			AddFirstKill("kill_first_neck", "Tail", "neck", "Neck");
			string[] prefabs = new string[4] { "Goblin", "GoblinArcher", "GoblinShaman", "GoblinBrute" };
			AddFirstKill("kill_first_goblin", "Goblin", "fuling", prefabs);
			AddFirstKill("kill_first_goblin_mode", "Goblin Mode", "fuling", prefabs);
			AddFirstKill("kill_first_skeeter", "Skeeter", "deathsquito", "Deathsquito");
			AddFirstKill("kill_first_backstab", "Backstab", "deathsquito", "Deathsquito");
			AddFirstKill("kill_first_dog", "Dog", "wolf", "Wolf", "Wolf_cub");
			AddFirstKill("kill_first_dawg", "Dawg", "wolf", "Wolf", "Wolf_cub");
			AddFirstKill("kill_first_lizard", "Lizard", "lox", "Lox", "Lox_Calf");
			AddFirstKill("kill_first_ox", "Ox", "lox", "Lox", "Lox_Calf");
			AddFirstKill("kill_first_steak", "Steak", "lox", "Lox", "Lox_Calf");
			AddFirstKill("kill_first_grey", "Grey", "greyling", "Greyling");
			AddFirstKill("kill_first_dwarf", "Dwarf", "greyling", "Greyling");
			AddFirstKill("kill_first_bridge", "Bridge", "troll", "Troll");
			string[] prefabs2 = new string[3] { "Draugr", "Draugr_Ranged", "Draugr_Elite" };
			AddFirstKill("kill_first_zombie", "Zombie", "draugr", prefabs2);
			AddFirstKill("kill_first_brains", "Brains", "draugr", prefabs2);
			AddFirstKill("kill_first_sucker", "Sucker", "leech", "Leech");
			AddFirstKill("kill_first_slime", "Slime", "blob", "Blob", "BlobElite");
			AddFirstKill("kill_first_balloon", "Balloon", "gjall", "Gjall");
			AddFirstKill("kill_first_noodle", "Noodle", "serpent", "Serpent");
			AddFirstKill("kill_first_bunny", "Bunny", "hare", "Hare");
			AddFirstKill("kill_first_hot", "Hot", "surtling", "Surtling");
			AddFirstKill("kill_first_bat", "Bat", "bat", "Bat");
			string[] prefabs3 = new string[3] { "Skeleton", "Skeleton_NoArcher", "Skeleton_Poison" };
			AddFirstKill("kill_first_spooky", "Spooky", "skeleton", prefabs3);
			AddFirstKill("kill_first_scary", "Scary", "skeleton", prefabs3);
			AddFirstKill("kill_first_ethereal", "Ethereal", "ghost", "Ghost");
			AddFirstKill("kill_first_furry", "Furry", "fenring", "Fenring");
			AddFirstKill("kill_first_chain", "Chain", "wraith", "Wraith");
			AddFirstKill("kill_first_funsized", "Fun-sized", "dvergr", "Dverger", "DvergerMage", "DvergerMageFire", "DvergerMageIce", "DvergerMageSupport");
			AddFirstKill("kill_first_piranha", "Piranha", "morgen", "Morgen");
			AddFirstKill("kill_first_bite", "Bite", "morgen", "Morgen");
			AddFirstKill("kill_first_magic", "Magic", "drake", "Hatchling");
			AddFirstKill("kill_first_fart", "Fart", "abomination", "Abomination");
			AddFirstKill("kill_first_aerial", "Aerial", "volture", "Volture");
			AddFirstKill("kill_first_turkey", "Turkey", "volture", "Volture");
			AddFirstKill("kill_first_raptor", "Raptor", "asksvin", "Asksvin");
			AddFirstKill("kill_first_mutant", "Mutant", "asksvin", "Asksvin");
			AddFirstKill("kill_first_cult", "Cult", "cultist", "Fenring_Cultist");
			AddFirstKill("kill_first_classic", "Classic", "cultist", "Fenring_Cultist");
			AddFirstKill("kill_first_rock", "Rock", "stone golem", "StoneGolem");
			AddFirstKill("kill_first_hard", "Hard", "stone golem", "StoneGolem");
			string[] prefabs4 = new string[3] { "Moose", "moose", "Moose_calf" };
			AddFirstKill("kill_first_meese", "Meese", "moose", prefabs4);
			AddFirstKill("kill_first_mice", "Mice", "moose", prefabs4);
			AddFirstKill("kill_first_twig", "Twig", "greydwarf", "Greydwarf");
			AddFirstKill("kill_first_stump", "Stump", "greydwarf brute", "Greydwarf_Elite");
			AddFirstKill("kill_first_hippie", "Hippie", "greydwarf shaman", "Greydwarf_Shaman");
			AddFirstKill("kill_first_teddy", "Teddy", "bear", "Bjorn");
			AddFirstKill("kill_first_grizzly", "Grizzly", "vile", "Unbjorn");
			AddFirstKill("kill_first_howl", "Howl", "ulv", "Ulv");
			AddFirstKill("kill_first_tock", "Tock", "tick", "Tick");
			AddFirstKill("kill_first_bug", "Bug", "seeker", "Seeker");
			AddFirstKill("kill_first_buzz", "Buzz", "seeker", "Seeker");
			AddFirstKill("kill_first_crunchy", "Crunchy", "seeker soldier", "SeekerBrute");
			AddFirstKill("kill_first_crispy", "Crispy", "charred warrior", "Charred_Melee");
			AddFirstKill("kill_first_burnt", "Burnt", "charred marksman", "Charred_Archer");
			AddFirstKill("kill_first_ashy", "Ashy", "charred warlock", "Charred_Mage");
			AddFirstKill("kill_first_jaws", "Jaws", "bonemaw", "BonemawSerpent");
			AddFirstKill("kill_first_lava", "Lava", "lava blob", "BlobLava");
			AddFirstKill("kill_first_lamp", "Lamp", "lava blob", "BlobLava");
			AddFirstKill("kill_first_sticky", "Sticky", "growth", "BlobTar");
			AddFirstKill("kill_first_torch", "Torch", "Brenna", "Skeleton_Hildir");
			AddFirstKill("kill_first_frozen", "Frozen", "Geirrhafa", "Fenring_Cultist_Hildir");
			AddFirstKill("kill_first_bros", "Bros", "Zil or Thungr", "GoblinBruteBros", "GoblinBrute_Hildir", "GoblinShaman_Hildir", "BruteBros");
			AddBossCosmetic("kill_first_greenhorn", "Greenhorn", "Eikthyr", "Eikthyr");
			AddBossCosmetic("kill_first_groot", "Groot", "The Elder", "gd_king");
			AddBossCosmetic("kill_first_boner", "Boner", "Bonemass", "Bonemass");
			AddBossCosmetic("kill_first_dragon", "Dragon", "Moder", "Dragon");
			AddBossCosmetic("kill_first_meteor", "Meteor", "Yagluth", "GoblinKing");
			AddBossCosmetic("kill_first_hive", "Hive", "the Queen", "SeekerQueen");
			AddBossCosmetic("kill_first_warped", "Warped", "Fader", "Fader");
			AddBossCosmetic("kill_first_madness", "Madness", "Fader", "Fader");
			AddBossCosmetic("kill_first_pride", "Pride", "Fader", "Fader");
			Add(DeathBy("death_fall", "Gravity", "Die from falling.", (PlayerStatType)58).Stat("FallDamage", 10f));
			Add(DeathBy("death_drown", "Extra Wet", "Drown.", (PlayerStatType)59).Bonus("Swim", 5f).Stat("SwimStamina", 5f));
			PlayerStatType[] array26 = new PlayerStatType[7];
			RuntimeHelpers.InitializeArray(array26, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
			Add(DeathBy("death_tree", "Oops", "Get killed by a falling tree.", (PlayerStatType[])(object)array26).Stat("Armor", 5f));
			Add(DeathBy("death_burn", "Toasty", "Burn to death.", (PlayerStatType)60).Stat("FrostResistance", 10f).Stat("FireWeakness", 10f));
			Add(DeathBy("death_cart", "Roadkill", "Get run over by a cart.", (PlayerStatType)67).Bonus("Dodge", 15f));
			string[] array27 = new string[4] { "Chill", "Relax", "Jacuzzi", "Moist" };
			foreach (string text3 in array27)
			{
				Add(Title("hottub_" + text3.ToLowerInvariant(), text3, "Cosmetic title: get into a hot tub for the first time.").Require(TitleRequirement.Counter("hottub", 1, "Get into a hot tub")));
			}
			Add(Title("achievement_first", "Achievement", "Unlock your first Valheim achievement.").Require(TitleRequirement.Custom((Player _) => AchievementTitles.AnyUnlocked(), "Unlock any achievement")));
			AddElement("Fire", "FireDamage");
			AddElement("Frost", "FrostDamage");
			AddElement("Lightning", "LightningDamage");
			AddElement("Poison", "PoisonDamage");
			AddElement("Spirit", "SpiritDamage");
			Add(Title("doom", "Doom", "Defeat 25 bosses in total.").Require(TitleRequirement.DefeatBosses(25)).Stat("BossDamage", 10f));
			Add(Title("valhalla", "Valhalla", "Be killed by a boss.").Require(TitleRequirement.Counter("death:boss", 1, "Be killed by a boss")).Stat("DeathSkillLoss", 25f));
			Add(Title("legendary_warrior", "Legendary Warrior", "Reach level 100 in any weapon skill.").Require(TitleRequirement.Custom((Player p) => TitleManager.WeaponSkills.Any((SkillType s) => TitleManager.GetRawSkillLevel(p, s) >= 100f), "Reach level 100 in a weapon skill")).Stat("OtherWeaponSkills", 25f));
			int[] array28 = new int[7] { 1, 5, 10, 25, 50, 75, 100 };
			string[] array29 = new string[7] { "murderer", "pvp_5", "pvp_10", "pvp_25", "pvp_50", "pvp_75", "pvp_100" };
			string[] array30 = new string[7] { "Murderer", "Serial Killer", "Bloody Prince", "Bloody King", "Demon Lord", "Demon God", "Evil" };
			for (int num21 = 0; num21 < array28.Length; num21++)
			{
				int num22 = array28[num21];
				Add(Title(array29[num21], array30[num21], ((num22 == 1) ? "Kill another player." : $"Kill {num22} players.") + " While equipped, your PvP is always on.").Require(TitleRequirement.Counter("playerkill", num22, "Kill players")).Stat("ForcePvp", 1f).SetGroup("pvp"));
			}
			Add(Title("friend", "Friend", "Play in the same world as another player.").Require(TitleRequirement.Custom((Player _) => (Object)(object)ZNet.instance != (Object)null && ZNet.instance.GetNrOfPlayers() > 1, "Meet another player")));
			string[] names = ServerTitles.Names;
			foreach (string name in names)
			{
				Add(new TitleDefinition(ServerTitles.Id(name), name, "Given by the server owner.").SetServerGranted());
			}
			string[] identities = Identities;
			foreach (string name2 in identities)
			{
				AddCosmetic("identity_", name2, "Cosmetic identity title, always available.");
			}
			string[] pronouns = Pronouns;
			foreach (string name3 in pronouns)
			{
				AddCosmetic("pronoun_", name3, "Cosmetic pronoun title, always available.");
			}
			string[] colours = Colours;
			foreach (string name4 in colours)
			{
				AddCosmetic("colour_", name4, "Cosmetic colour title, always available.");
			}
			string[] emotions = Emotions;
			foreach (string name5 in emotions)
			{
				AddCosmetic("emotion_", name5, "Cosmetic emotion title, always available.");
			}
			string[] descriptors = Descriptors;
			foreach (string name6 in descriptors)
			{
				AddCosmetic("descriptor_", name6, "Cosmetic descriptive title, always available.");
			}
			AddCosmetic("cosmetic_", "Kill", "Cosmetic title, always available.");
			AddCosmetic("cosmetic_", "Seagull", "Cosmetic title, always available.");
			Milestone[] milestones2 = Milestones;
			foreach (Milestone milestone2 in milestones2)
			{
				AddCosmetic("skillname_", milestone2.Label, "Cosmetic skill title, always available.");
				AddCosmetic("skillnoun_", milestone2.Noun, "Cosmetic " + milestone2.Label + " title, always available.");
			}
		}

		private static Perk P(string stat, float perTier)
		{
			return new Perk
			{
				Stat = stat,
				PerTier = perTier
			};
		}

		private static Perk R(string stat, float first, float last)
		{
			return new Perk
			{
				Stat = stat,
				First = first,
				Last = last,
				Range = true
			};
		}

		private static Milestone M(string skill, string label, string noun, params Perk[] perks)
		{
			return new Milestone
			{
				Skill = skill,
				Label = label,
				Noun = noun,
				Perks = perks
			};
		}

		private static void Add(TitleDefinition title)
		{
			TitleAPI.RegisterTitle(title);
		}

		private static TitleDefinition DeathBy(string id, string name, string description, params PlayerStatType[] stats)
		{
			TitleRequirement[] deaths = stats.Select((PlayerStatType s) => TitleRequirement.PlayerStat(s, 1f, description.TrimEnd(new char[1] { '.' }))).ToArray();
			return Title(id, name, description).Require((deaths.Length == 1) ? deaths[0] : TitleRequirement.Custom((Player p) => deaths.Any((TitleRequirement d) => d.IsMet(p)), description.TrimEnd(new char[1] { '.' })));
		}

		private static void AddBossCosmetic(string id, string name, string boss, string prefab)
		{
			Add(Title(id, name, "Cosmetic title: defeat " + boss + ".").Require(TitleRequirement.Kill(prefab)));
		}

		private static void AddDungeon(Theme theme, string dungeon, params string[] idsAndNames)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i + 1 < idsAndNames.Length; i += 2)
			{
				Add(Title("dungeon_" + idsAndNames[i], idsAndNames[i + 1], "Cosmetic title: enter " + dungeon + ".").Require(TitleRequirement.Counter(DungeonTitles.Key(theme), 1, "Enter " + dungeon)));
			}
		}

		private static void AddFirstKill(string id, string name, string creature, params string[] prefabs)
		{
			TitleRequirement[] kills = prefabs.Select((string p) => TitleRequirement.Kill(p)).ToArray();
			Add(Title(id, name, "Cosmetic title: kill your first " + creature + ".").Require(TitleRequirement.Custom((Player p) => kills.Any((TitleRequirement k) => k.IsMet(p)), "Kill a " + creature)));
		}

		private static void AddElement(string name, string stat)
		{
			string key = "element:" + name.ToLowerInvariant();
			Add(Title("element_" + name.ToLowerInvariant(), name, "Hit creatures 100 times with " + name.ToLowerInvariant() + " damage.").Require(TitleRequirement.Counter(key, 100, "Hit with " + name.ToLowerInvariant())).Stat(stat, 5f));
		}

		private static void AddSkillGain(string id, string name, int count, int level, float percent, string group)
		{
			Add(Title(id, name, $"Get {count} skills above level {level}.").Require(TitleRequirement.SkillsAbove(count, level)).Stat("SkillGain", percent).SetGroup(group));
		}

		private static void AddBoss(string key, string name, string prefab, string skill, string fullName = null)
		{
			Add(Title("boss_" + key, name, "Defeat " + (fullName ?? name) + ".").Require(TitleRequirement.Kill(prefab)).Bonus(skill, 5f));
		}

		private static void AddBuildTier(string id, string name, int amount, int tier)
		{
			Add(Title(id, name, $"Build {amount} pieces.").Require(TitleRequirement.Build("*", amount)).Stat("FreeBuildChance", 5 * tier).SetGroup("build"));
		}

		private static TitleDefinition Title(string id, string name, string description)
		{
			return new TitleDefinition(id, name, description);
		}

		private static void AddBerry(string prefab, string name, string plural)
		{
			Add(Title("berry_" + name.ToLowerInvariant(), name, "Cosmetic title: eat 10 " + plural + ".").Require(TitleRequirement.Eat(prefab, 10)));
		}

		private static void AddCosmetic(string idPrefix, string name, string description)
		{
			Add(new TitleDefinition(idPrefix + name.ToLowerInvariant().Replace(" ", "_").Replace("-", "_")
				.Replace("/", "_"), name, description).SetAlwaysUnlocked());
		}
	}
	internal static class DungeonTitles
	{
		public unsafe static string Key(Theme theme)
		{
			return "dungeon:" + ((object)(*(Theme*)(&theme))/*cast due to .constrained prefix*/).ToString();
		}

		public static void Tick(Player player)
		{
			//IL_0007: 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_0073: 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_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: 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)
			Location zoneLocation = Location.GetZoneLocation(((Component)player).transform.position);
			if ((Object)(object)zoneLocation == (Object)null)
			{
				return;
			}
			DungeonGenerator val = (((Object)(object)zoneLocation.m_generator != (Object)null) ? zoneLocation.m_generator : ((Component)zoneLocation).GetComponentInChildren<DungeonGenerator>());
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Theme val2;
			if (((Character)player).InInterior())
			{
				val2 = InteriorTheme(val.m_themes);
			}
			else
			{
				if ((val.m_themes & 0x2000) == 0 || !InsideCamp(player, val))
				{
					return;
				}
				val2 = (Theme)8192;
			}
			if ((int)val2 != 0 && TitleManager.GetCounter(Key(val2)) == 0)
			{
				TitleManager.Increment(Key(val2));
			}
		}

		private static Theme InteriorTheme(Theme themes)
		{
			//IL_0001: 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_0009: Invalid comparison between Unknown and I4
			//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_001f: Invalid comparison between Unknown and I4
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Invalid comparison between Unknown and I4
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Invalid comparison between Unknown and I4
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Invalid comparison between Unknown and I4
			//IL_0051: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Invalid comparison between Unknown and I4
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Invalid comparison between Unknown and I4
			//IL_0071: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			if ((themes & 0x200) > 0)
			{
				return (Theme)512;
			}
			if ((themes & 0x400) > 0)
			{
				return (Theme)1024;
			}
			if ((themes & 0x800) > 0)
			{
				return (Theme)2048;
			}
			if ((themes & 9) > 0)
			{
				return (Theme)8;
			}
			if ((themes & 2) > 0)
			{
				return (Theme)2;
			}
			if ((themes & 4) > 0)
			{
				return (Theme)4;
			}
			if ((themes & 0x80) > 0)
			{
				return (Theme)128;
			}
			return (Theme)0;
		}

		private static bool InsideCamp(Player player, DungeonGenerator generator)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Component)player).transform.position - ((Component)generator).transform.position;
			val.y = 0f;
			return ((Vector3)(ref val)).magnitude <= generator.m_campRadiusMax;
		}
	}
	internal static class ExploreTitles
	{
		private const float WorldRadius = 10000f;

		private const float RecountSeconds = 10f;

		private static readonly FieldRef<Minimap, BitArray> Explored = AccessTools.FieldRefAccess<Minimap, BitArray>("m_explored");

		private static float nextCount;

		private static int[] buffer;

		public static float Percent { get; private set; }

		public static void Tick()
		{
			if (Time.time < nextCount)
			{
				return;
			}
			nextCount = Time.time + 10f;
			if (!TitleManager.TrackerNeeded("map"))
			{
				return;
			}
			Minimap instance = Minimap.instance;
			BitArray bitArray = (((Object)(object)instance != (Object)null) ? Explored.Invoke(instance) : null);
			if (bitArray != null && !(instance.m_pixelSize <= 0f))
			{
				int num = (bitArray.Length + 31) / 32;
				if (buffer == null || buffer.Length != num)
				{
					buffer = new int[num];
				}
				bitArray.CopyTo(buffer, 0);
				long num2 = 0L;
				int[] array = buffer;
				foreach (int v in array)
				{
					num2 += PopCount((uint)v);
				}
				float num3 = 10000f / instance.m_pixelSize;
				double num4 = Math.PI * (double)num3 * (double)num3;
				Percent = Mathf.Clamp((float)((double)num2 / num4 * 100.0), 0f, 100f);
			}
		}

		private static int PopCount(uint v)
		{
			v -= (v >> 1) & 0x55555555;
			v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
			return (int)(((v + (v >> 4)) & 0xF0F0F0F) * 16843009 >> 24);
		}
	}
	public class MapExploredRequirement : TitleRequirement
	{
		public float Percent { get; }

		public MapExploredRequirement(float percent)
		{
			Percent = percent;
		}

		public override bool IsMet(Player player)
		{
			return ExploreTitles.Percent >= Percent;
		}

		public override string Describe(Player player)
		{
			return $"Uncover {Percent:0}% of a world's map ({Mathf.Min(ExploreTitles.Percent, Percent):0.#}/{Percent:0}%)";
		}
	}
	internal static class MonsterTitles
	{
		[HarmonyPatch(typeof(CharacterDrop), "GenerateDropList")]
		private static class DoubleDrops
		{
			private static readonly FieldRef<Character, HitData> LastHit = AccessTools.FieldRefAccess<Character, HitData>("m_lastHit");

			private static void Postfix(Character ___m_character, List<KeyValuePair<GameObject, int>> __result)
			{
				if ((Object)(object)___m_character == (Object)null || __result == null || __result.Count == 0)
				{
					return;
				}
				string prefabName = Utils.GetPrefabName(((Component)___m_character).gameObject);
				string value;
				bool flag = CreatureTrophy.TryGetValue(prefabName, out value);
				bool flag2 = IsCharred(prefabName);
				if (!flag && !flag2)
				{
					return;
				}
				HitData obj = LastHit.Invoke(___m_character);
				Character obj2 = ((obj != null) ? obj.GetAttacker() : null);
				Player val = (Player)(object)((obj2 is Player) ? obj2 : null);
				ZNetView val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<ZNetView>() : null);
				if ((Object)(object)val2 == (Object)null || !val2.IsValid())
				{
					return;
				}
				float num = (flag ? TitleManager.GetStatBonusOf(val2.GetZDO(), StatKey(value)) : 0f) + (flag2 ? TitleManager.GetStatBonusOf(val2.GetZDO(), "DoubleDrop:Charred") : 0f);
				if (!(num <= 0f) && !(Random.value * 100f >= num))
				{
					int count = __result.Count;
					for (int i = 0; i < count; i++)
					{
						__result.Add(__result[i]);
					}
					if ((Object)(object)val == (Object)(object)Player.m_localPlayer)
					{
						((Character)val).Message((MessageType)1, "Double drops!", 0, (Sprite)null, false);
					}
				}
			}
		}

		private const float DoubleDropChance = 25f;

		private const float BossDoubleDropChance = 15f;

		private const float CharredDoubleDropChance = 10f;

		private const string CharredStat = "DoubleDrop:Charred";

		private const string CharredGroup = "charred";

		private static bool registered;

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

		private static readonly Dictionary<string, string> BossTitles = new Dictionary<string, string>
		{
			{ "Eikthyr", "boss_eikthyr" },
			{ "gd_king", "boss_elder" },
			{ "Bonemass", "boss_bonemass" },
			{ "Dragon", "boss_moder" },
			{ "GoblinKing", "boss_yagluth" },
			{ "SeekerQueen", "boss_queen" },
			{ "Fader", "boss_fader" }
		};

		private static readonly Dictionary<string, string> NameOverrides = new Dictionary<string, string> { { "TrophyDvergr", "Dvergr" } };

		private static bool IsCharred(string prefabName)
		{
			return prefabName.IndexOf("Charred", StringComparison.OrdinalIgnoreCase) >= 0;
		}

		internal static string StatKey(string trophy)
		{
			return "DoubleDrop:" + trophy;
		}

		public static void TryRegister()
		{
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Invalid comparison between Unknown and I4
			if (registered || (Object)(object)ZNetScene.instance == (Object)null || (Object)(object)ObjectDB.instance == (Object)null || Localization.instance == null)
			{
				return;
			}
			registered = true;
			Dictionary<string, List<GameObject>> dictionary = new Dictionary<string, List<GameObject>>();
			foreach (GameObject prefab in ZNetScene.instance.m_prefabs)
			{
				CharacterDrop val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<CharacterDrop>() : null);
				if ((Object)(object)val == (Object)null || val.m_drops == null || (Object)(object)prefab.GetComponent<Character>() == (Object)null)
				{
					continue;
				}
				foreach (Drop drop in val.m_drops)
				{
					ItemDrop val2 = ((drop != null && (Object)(object)drop.m_prefab != (Object)null) ? drop.m_prefab.GetComponent<ItemDrop>() : null);
					if (!((Object)(object)val2 == (Object)null) && (int)val2.m_itemData.m_shared.m_itemType == 13)
					{
						CreatureTrophy[((Object)prefab).name] = ((Object)drop.m_prefab).name;
						if (!dictionary.TryGetValue(((Object)drop.m_prefab).name, out var value))
						{
							value = (dictionary[((Object)drop.m_prefab).name] = new List<GameObject>());
						}
						value.Add(prefab);
					}
				}
			}
			int num = 0;
			foreach (KeyValuePair<string, List<GameObject>> item in dictionary.OrderBy((KeyValuePair<string, List<GameObject>> k) => k.Key))
			{
				string key = item.Key;
				string text = StatKey(key);
				string text2 = TitleName(key, item.Value);
				if (text2 == null)
				{
					continue;
				}
				TitleStats.RegisterLabel(text, "{0}% chance of double drops from " + text2);
				string value2;
				string text3 = item.Value.Select((GameObject c) => BossTitles.TryGetValue(((Object)c).name, out value2) ? value2 : null).FirstOrDefault((string id) => id != null);
				if (text3 != null)
				{
					TitleAPI.AddStatBonus(text3, text, 15f);
					continue;
				}
				TitleDefinition titleDefinition = new TitleDefinition("trophy_" + key, text2, "Find a " + TitleRequirement.ItemName(key) + ".").Require(TitleRequirement.DiscoverItem(key)).Stat(text, 25f);
				if (IsCharred(key))
				{
					titleDefinition.SetGroup("charred");
				}
				if (TitleAPI.RegisterTitle(titleDefinition))
				{
					num++;
				}
			}
			TitleRequirement[] charred = dictionary.Keys.Where(IsCharred).Select(TitleRequirement.DiscoverItem).ToArray();
			if (charred.Length != 0)
			{
				TitleStats.RegisterLabel("DoubleDrop:Charred", "{0}% chance of double drops from all charred");
				TitleAPI.RegisterTitle(new TitleDefinition("trophy_charred_any", "Charred", "Find any charred trophy.").Require(TitleRequirement.Custom((Player p) => charred.Any((TitleRequirement r) => r.IsMet(p)), "Find a charred trophy")).Stat("DoubleDrop:Charred", 10f).SetGroup("charred"));
			}
			Logger.LogInfo((object)$"Registered {num} trophy titles.");
		}

		private static string TitleName(string trophy, List<GameObject> creatures)
		{
			if (NameOverrides.TryGetValue(trophy, out var value))
			{
				return value;
			}
			foreach (GameObject item in creatures.OrderBy((GameObject c) => (!trophy.EndsWith(((Object)c).name)) ? 1 : 0))
			{
				string text = Localization.instance.Localize(item.GetComponent<Character>().m_name).Trim();
				int num = text.LastIndexOf('&');
				if (num >= 0)
				{
					text = text.Substring(num + 1).Trim();
				}
				if (text.Length > 0 && text[0] != '[' && text[0] != '$' && text.IndexOf('_') < 0)
				{
					return text;
				}
			}
			return null;
		}
	}
	internal static class PaladinCompat
	{
		internal const string HolyCounter = "paladin:holy";

		public static void Patch(Harmony harmony)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method("PaladinMod.Paladin:Reflect", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				Logger.LogWarning((object)"PaladinMod found, but not its Paladin.Reflect method: the Holy title has no effect.");
			}
			else
			{
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(PaladinCompat), "ReflectPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}

		private static void ReflectPrefix(Player player, Character attacker, ref float blocked)
		{
			if (!((Object)(object)player == (Object)null) && !((Object)(object)player != (Object)(object)Player.m_localPlayer) && !((Object)(object)attacker == (Object)null) && !attacker.IsDead() && !(blocked <= 0f))
			{
				TitleManager.Increment("paladin:holy");
				blocked *= 1f + TitleManager.GetStatBonus("HolyDamage") / 100f;
			}
		}
	}
	internal static class ProducePerks
	{
		[HarmonyPatch(typeof(CookingStation), "OnInteract")]
		private static class ExtraCook
		{
			private static readonly MethodInfo GetSlot = AccessTools.Method(typeof(CookingStation), "GetSlot", (Type[])null, (Type[])null);

			private static void Prefix(CookingStation __instance, Humanoid user, out string __state)
			{
				__state = null;
				if ((Object)(object)user == (Object)null || (Object)(object)user != (Object)(object)Player.m_localPlayer || !Roll("ExtraCookChance"))
				{
					return;
				}
				for (int i = 0; i < __instance.m_slots.Length; i++)
				{
					object[] array = new object[5] { i, null, 0f, null, false };
					GetSlot.Invoke(__instance, array);
					if (array[3] != null && array[3].ToString() == "Done" && array[1] is string { Length: >0 } text)
					{
						__state = text;
						break;
					}
				}
			}

			private static void Postfix(bool __result, Humanoid user, string __state)
			{
				//IL_003b: 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_0045: 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)
				if (__result && __state != null && !((Object)(object)ZNetScene.instance == (Object)null))
				{
					GameObject prefab = ZNetScene.instance.GetPrefab(__state);
					if (!((Object)(object)prefab == (Object)null))
					{
						Object.Instantiate<GameObject>(prefab, ((Component)user).transform.position + Vector3.up, Quaternion.identity);
						((Character)user).Message((MessageType)1, "Extra cooked item!", 0, (Sprite)null, false);
					}
				}
			}
		}

		private class AmmoCraft
		{
			public string Prefab;

			public string Token;

			public int Before;

			public int PerCraft;

			public float Extra;
		}

		[HarmonyPatch(typeof(InventoryGui), "DoCrafting")]
		private static class ExtraAmmo
		{
			private static void Prefix(Player player, Recipe ___m_craftRecipe, out AmmoCraft __state)
			{
				//IL_004d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0054: Invalid comparison between Unknown and I4
				__state = null;
				ItemDrop val = (((Object)(object)___m_craftRecipe != (Object)null) ? ___m_craftRecipe.m_item : null);
				if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer || (Object)(object)val == (Object)null)
				{
					return;
				}
				SharedData shared = val.m_itemData.m_shared;
				if ((int)shared.m_itemType == 9)
				{
					float num = ((shared.m_ammoType == "$ammo_arrows") ? TitleManager.GetStatBonus("ExtraArrows") : ((shared.m_ammoType == "$ammo_bolts") ? TitleManager.GetStatBonus("ExtraBolts") : 0f));
					if (!(num < 1f))
					{
						__state = new AmmoCraft
						{
							Prefab = ((Object)((Component)val).gameObject).name,
							Token = shared.m_name,
							PerCraft = Mathf.Max(1, ___m_craftRecipe.m_amount),
							Before = ((Humanoid)player).GetInventory().CountItems(shared.m_name, -1, true),
							Extra = num
						};
					}
				}
			}

			private static void Postfix(Player player, AmmoCraft __state)
			{
				//IL_0065: Unknown result type (might be due to invalid IL or missing references)
				if (__state != null)
				{
					int num = (((Humanoid)player).GetInventory().CountItems(__state.Token, -1, true) - __state.Before) / __state.PerCraft;
					int num2 = num * Mathf.FloorToInt(__state.Extra);
					if (num2 > 0)
					{
						((Humanoid)player).GetInventory().AddItem(__state.Prefab, num2, 1, 0, player.GetPlayerID(), player.GetPlayerName(), new Vector2i(-1, -1), false, false, true);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Pickable), "Interact")]
		private static class ExtraHarvest
		{
			private static readonly MethodInfo Drop = AccessTools.Method(typeof(Pickable), "Drop", (Type[])null, (Type[])null);

			private static void Prefix(bool ___m_picked, out bool __state)
			{
				__state = ___m_picked;
			}

			private static void Postfix(Pickable __instance, Humanoid character, bool __result, bool __state)
			{
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Invalid comparison between Unknown and I4
				if (!(!__result || __state) && !((Object)(object)character == (Object)null) && !((Object)(object)character != (Object)(object)Player.m_localPlayer) && (int)__instance.m_pickRaiseSkill == 106 && !((Object)(object)__instance.m_itemPrefab == (Object)null) && Roll("ExtraHarvestChance"))
				{
					Drop.Invoke(__instance, new object[3]
					{
						__instance.m_itemPrefab,
						0,
						Mathf.Max(1, __instance.m_amount)
					});
					((Character)character).Message((MessageType)1, "Extra harvest!", 0, (Sprite)null, false);
				}
			}
		}

		private static bool Roll(string stat)
		{
			return Random.value * 100f < TitleManager.GetStatBonus(stat);
		}
	}
	internal static class PvpTitles
	{
		[HarmonyPatch(typeof(Player), "OnDeath")]
		private static class VictimPatch
		{
			private static void Prefix(Player __instance)
			{
				if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
				{
					return;
				}
				HitData obj = LastHit.Invoke((Character)(object)__instance);
				Character val = ((obj != null) ? obj.GetAttacker() : null);
				if ((Object)(object)val != (Object)null && val.IsBoss())
				{
					TitleManager.Increment("death:boss");
				}
				if (ZRoutedRpc.instance == null)
				{
					return;
				}
				Player val2 = (Player)(object)((val is Player) ? val : null);
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)__instance))
				{
					ZNetView component = ((Component)val2).GetComponent<ZNetView>();
					if (!((Object)(object)component == (Object)null) && component.IsValid())
					{
						ZRoutedRpc.instance.InvokeRoutedRPC(component.GetZDO().GetOwner(), "TitlesMod_PlayerKill", Array.Empty<object>());
					}
				}
			}
		}

		[HarmonyPatch(typeof(Player), "SetPVP")]
		private static class KeepPvpOn
		{
			private static bool Prefix(Player __instance, bool enabled)
			{
				if (enabled || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || !IsPvpForced())
				{
					return true;
				}
				((Character)__instance).Message((MessageType)2, "Your title keeps PvP on.", 0, (Sprite)null, false);
				return false;
			}
		}

		internal const string PlayerKillCounter = "playerkill";

		internal const string Group = "pvp";

		internal const string KilledByBossCounter = "death:boss";

		private const string RpcName = "TitlesMod_PlayerKill";

		private static ZRoutedRpc registeredOn;

		private static readonly FieldRef<Character, HitData> LastHit = AccessTools.FieldRefAccess<Character, HitData>("m_lastHit");

		public static void Tick(Player player)
		{
			if (ZRoutedRpc.instance != null && ZRoutedRpc.instance != registeredOn)
			{
				ZRoutedRpc.instance.Register("TitlesMod_PlayerKill", (Action<long>)RPC_PlayerKill);
				registeredOn = ZRoutedRpc.instance;
			}
			if (IsPvpForced() && !((Character)player).IsPVPEnabled())
			{
				player.SetPVP(true);
			}
		}

		private static void RPC_PlayerKill(long sender)
		{
			Player localPlayer = Player.m_localPlayer;
			if (TitleManager.GetCounter("playerkill") != 0 && !TitleManager.EquippedTitles.Any((TitleDefinition t) => t.Group == "pvp"))
			{
				if (localPlayer != null)
				{
					((Character)localPlayer).Message((MessageType)1, "Player killed (not counted: equip a PvP title)", 0, (Sprite)null, false);
				}
				return;
			}
			TitleManager.Increment("playerkill");
			if (localPlayer != null)
			{
				((Character)localPlayer).Message((MessageType)1, string.Format("Player killed ({0})", TitleManager.GetCounter("playerkill")), 0, (Sprite)null, false);
			}
		}

		private static bool IsPvpForced()
		{
			return TitleManager.HasStat("ForcePvp");
		}
	}
	internal static class ServerTitles
	{
		private const string Prefix = "titlesmod.grant.";

		public static readonly string[] Names = new string[9] { "Admin", "Owner", "Donor", "VIP", "Super VIP", "Mega VIP", "Fan", "Guest", "Visitor" };

		private static readonly HashSet<string> Granted = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		public static IEnumerable<string> TitleIds => Names.Select(Id);

		public static string Id(string name)
		{
			return "server_" + name.ToLowerInvariant().Replace(" ", "_");
		}

		private static string Sanitize(string playerName)
		{
			return new string((from c in playerName.Trim().ToLowerInvariant()
				select char.IsLetterOrDigit(c) ? c : '_').ToArray());
		}

		private static string Key(string playerName, string titleId)
		{
			return ("titlesmod.grant." + titleId + "." + Sanitize(playerName)).ToLowerInvariant();
		}

		public static bool IsGranted(string titleId)
		{
			return titleId != null && Granted.Contains(titleId);
		}

		public static void Grant(string playerName, string titleId)
		{
			ZoneSystem instance = ZoneSystem.instance;
			if (instance != null)
			{
				instance.SetGlobalKey(Key(playerName, titleId));
			}
		}

		public static void Revoke(string playerName, string titleId)
		{
			ZoneSystem instance = ZoneSystem.instance;
			if (instance != null)
			{
				instance.RemoveGlobalKey(Key(playerName, titleId));
			}
		}

		public static IEnumerable<string> AllGrants()
		{
			return ((Object)(object)ZoneSystem.instance == (Object)null) ? Enumerable.Empty<string>() : (from k in ZoneSystem.instance.GetGlobalKeys()
				where k.StartsWith("titlesmod.grant.", StringComparison.OrdinalIgnoreCase)
				select k.Substring("titlesmod.grant.".Length)).Select(delegate(string rest)
			{
				int num = rest.LastIndexOf('.');
				return (num > 0) ? (rest.Substring(num + 1) + ": " + (TitleAPI.GetTitle(rest.Substring(0, num))?.Name ?? rest.Substring(0, num))) : rest;
			});
		}

		public static void Refresh(Player player)
		{
			HashSet<string> now = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			if ((Object)(object)ZoneSystem.instance != (Object)null && (Object)(object)player != (Object)null)
			{
				string text = "." + Sanitize(player.GetPlayerName());
				foreach (string globalKey in ZoneSystem.instance.GetGlobalKeys())
				{
					if (globalKey.StartsWith("titlesmod.grant.", StringComparison.OrdinalIgnoreCase) && globalKey.EndsWith(text, StringComparison.OrdinalIgnoreCase))
					{
						now.Add(globalKey.Substring("titlesmod.grant.".Length, globalKey.Length - "titlesmod.grant.".Length - text.Length));
					}
				}
			}
			if (now.SetEquals(Granted))
			{
				return;
			}
			foreach (string item in now.Where((string id) => !Granted.Contains(id)))
			{
				TitleDefinition title = TitleAPI.GetTitle(item);
				if (title != null && player != null)
				{
					((Character)player).Message((MessageType)2, "Title granted by the server: <color=#FFD27F>" + title.Name + "</color>", 0, (Sprite)null, false);
				}
			}
			foreach (string item2 in Granted.Where((string id) => !now.Contains(id)))
			{
				TitleDefinition title2 = TitleAPI.GetTitle(item2);
				if (title2 != null && player != null)
				{
					((Character)player).Message((MessageType)1, "Title removed by the server: " + title2.Name, 0, (Sprite)null, false);
				}
			}
			Granted.Clear();
			Granted.UnionWith(now);
			TitleManager.OnGrantsChanged();
		}

		public static void Clear()
		{
			Granted.Clear();
		}
	}
	internal static class StatPatches
	{
		[HarmonyPatch(typeof(SEMan), "ModifyHealthRegen")]
		private static class HealthRegen
		{
			private static void Postfix(SEMan __instance, ref float regenMultiplier)
			{
				if (IsLocal(__instance))
				{
					regenMultiplier += Percent("HealthRegen");
				}
			}
		}

		[HarmonyPatch(typeof(SEMan), "ModifyStaminaRegen")]
		private static class StaminaRegen
		{
			private static void Postfix(SEMan __instance, ref float staminaMultiplier)
			{
				if (IsLocal(__instance))
				{
					staminaMultiplier += Percent("StaminaRegen");
				}
			}
		}

		[HarmonyPatch(typeof(SEMan), "ModifyEitrRegen")]
		private static class EitrRegen
		{
			private static void Postfix(SEMan __instance, ref float eitrMultiplier)
			{
				if (IsLocal(__instance))
				{
					eitrMultiplier += Percent("EitrRegen");
				}
			}
		}

		[HarmonyPatch(typeof(SEMan), "ModifyRaiseSkill")]
		private static class SkillGain
		{
			private static void Postfix(SEMan __instance, ref float multiplier)
			{
				if (IsLocal(__instance))
				{
					multiplier += Percent("SkillGain");
				}
			}
		}

		[HarmonyPatch(typeof(SEMan), "ModifyMaxCarryWeight")]
		private static class CarryWeight
		{
			private static void Postfix(SEMan __instance, ref float limit)
			{
				if (IsLocal(__instance))
				{
					limit += TitleManager.GetStatBonus("CarryWeight");
				}
			}
		}

		[HarmonyPatch(typeof(Character), "RPC_Damage")]
		private static class ElementResistance
		{
			private static void Prefix(Character __instance, HitData hit)
			{
				if (hit != null && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
				{
					if (hit.m_damage.m_fire > 0f)
					{
						hit.m_damage.m_fire *= Taken("FireResistance", "FireWeakness");
					}
					if (hit.m_damage.m_frost > 0f)
					{
						hit.m_damage.m_frost *= Taken("FrostResistance", "FrostWeakness");
					}
				}
			}

			private static float Taken(string resistance, string weakness)
			{
				return Mathf.Max(0f, 1f - Percent(resistance) + Percent(weakness));
			}
		}

		[HarmonyPatch(typeof(Ship), "GetSailForce")]
		private static class SailSpeed
		{
			private static void Postfix(Ship __instance, ref Vector3 __result)
			{
				//IL_0027: 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)
				Player localPlayer = Player.m_localPlayer;
				if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)localPlayer.GetControlledShip() != (Object)(object)__instance))
				{
					__result *= 1f + Percent("SailSpeed");
				}
			}
		}

		[HarmonyPatch(typeof(SEMan), "ModifyAttack")]
		private static class ToolDamage
		{
			private static void Postfix(SEMan __instance, ref HitData hitData)
			{
				if (hitData != null && IsLocal(__instance))
				{
					hitData.m_damage.m_chop *= 1f + Percent("ChopDamage");
					hitData.m_damage.m_pickaxe *= 1f + Percent("MiningDamage");
					TitleManager.MultiplyCombatDamage(ref hitData.m_damage, 1f + Percent("Damage"));
					hitData.m_damage.m_fire *= 1f + Percent("FireDamage");
					hitData.m_damage.m_frost *= 1f + Percent("FrostDamage");
					hitData.m_damage.m_lightning *= 1f + Percent("LightningDamage");
					hitData.m_damage.m_poison *= 1f + Percent("PoisonDamage");
					hitData.m_damage.m_spirit *= 1f + Percent("SpiritDamage");
				}
			}
		}

		[HarmonyPatch(typeof(SEMan), "ModifyRunStaminaDrain")]
		private static class RunStamina
		{
			private static void Postfix(SEMan __instance, float baseDrain, ref float drain, bool minZero)
			{
				Reduce(__instance, "RunStamina", baseDrain, ref drain, minZero);
			}
		}

		[HarmonyPatch(typeof(SEMan), "ModifyJumpStaminaUsage")]
		private static class JumpStamina
		{
			private static void Postfix(SEMan __instance, float baseStaminaUse, ref float staminaUse, bool minZero)
			{
				Reduce(__instance, "JumpStamina", baseStaminaUse, ref staminaUse, minZero);
			}
		}

		[HarmonyPatch(typeof(SEMan), "ModifySwimStaminaUsage")]
		private static class SwimStamina
		{
			private static void Postfix(SEMan __instance, float baseStaminaUse, ref float staminaUse, bool minZero)
			{
				Reduce(__instance, "SwimStamina", baseStaminaUse, ref staminaUse, minZero);
			}
		}

		[HarmonyPatch(typeof(SEMan), "ModifySneakStaminaUsage")]
		private static class SneakStamina
		{
			private static void Postfix(SEMan __instance, float baseStaminaUse, ref float staminaUse, bool minZero)
			{
				Reduce(__instance, "SneakStamina", baseStaminaUse, ref staminaUse, minZero);
			}
		}

		[HarmonyPatch(typeof(SEMan), "ModifyDodgeStaminaUsage")]
		private static class DodgeStamina
		{
			private static void Postfix(SEMan __instance, float baseStaminaUse, ref float staminaUse, bool minZero)
			{
				Reduce(__instance, "DodgeStamina", baseStaminaUse, ref staminaUse, minZero);
			}
		}

		[HarmonyPatch(typeof(SEMan), "ModifyAttackStaminaUsage")]
		private static class AttackStamina
		{
			private static void Postfix(SEMan __instance, float baseStaminaUse, ref float staminaUse, bool minZero)
			{
				Reduce(__instance, "AttackStamina", baseStaminaUse, ref staminaUse, minZero);
			}
		}

		[HarmonyPatch(typeof(SEMan), "ModifyBlockStaminaUsage")]
		private static class BlockStamina
		{
			private static void Postfix(SEMan __instance, float baseStaminaUse, ref float staminaUse, bool minZero)
			{
				Reduce(__instance, "BlockStamina", baseStaminaUse, ref staminaUse, minZero);
			}
		}

		[HarmonyPatch(typeof(SEMan), "ModifyFallDamage")]
		private static class FallDamage
		{
			private static void Postfix(SEMan __instance, float baseDamage, ref float damage)
			{
				Reduce(__instance, "FallDamage", baseDamage, ref damage);
			}
		}

		[HarmonyPatch(typeof(Player), "GetTotalFoodValue")]
		private static class MaxPools
		{
			private static void Postfix(Player __instance, ref float hp, ref float stamina, ref float eitr)
			{
				if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
				{
					hp += TitleManager.GetStatBonus("MaxHealth");
					stamina += TitleManager.GetStatBonus("MaxStamina");
					eitr += TitleManager.GetStatBonus("MaxEitr");
				}
			}
		}

		[HarmonyPatch(typeof(ItemData), "GetWeaponLoadingTime")]
		private static class ReloadSpeed
		{
			private static void Postfix(ref float __result)
			{
				float num = Percent("ReloadSpeed");
				if (num > 0f)
				{
					__result /= 1f + num;
				}
			}
		}

		[HarmonyPatch(typeof(Attack), "GetAttackHealth")]
		private static class SpellHealthCost
		{
			private static void Postfix(Humanoid ___m_character, ref float __result)
			{
				if (!((Object)(object)___m_character == (Object)null) && !((Object)(object)___m_character != (Object)(object)Player.m_localPlayer))
				{
					__result *= Mathf.Clamp01(1f - Percent("SpellHealthCost"));
				}
			}
		}

		[HarmonyPatch(typeof(Player), "GetBodyArmor")]
		private static class Armor
		{
			private static void Postfix(Player __instance, ref float __result)
			{
				if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
				{
					__result += TitleManager.GetStatBonus("Armor");
					__result *= 1f + TitleManager.GetStatBonus("ArmorPercent") / 100f;
				}
			}
		}

		private static readonly FieldRef<SEMan, Character> SEManCharacter = AccessTools.FieldRefAccess<SEMan, Character>("m_character");

		private static bool IsLocal(SEMan seman)
		{
			return (Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)SEManCharacter.Invoke(seman) == (Object)(object)Player.m_localPlayer;
		}

		private static float Percent(string stat)
		{
			return TitleManager.GetStatBonus(stat) / 100f;
		}

		private static void Reduce(SEMan seman, string stat, float baseValue, ref float value, bool minZero = true)
		{
			if (!IsLocal(seman))
			{
				return;
			}
			float num = Percent(stat);
			if (num != 0f)
			{
				value -= baseValue * num;
				if (minZero && value < 0f)
				{
					value = 0f;
				}
			}
		}
	}
	public static class TitleAPI
	{
		private static readonly Dictionary<string, TitleDefinition> Titles = new Dictionary<string, TitleDefinition>(StringComparer.OrdinalIgnoreCase);

		private static readonly List<TitleDefinition> Ordered = new List<TitleDefinition>();

		private static readonly Dictionary<string, List<Action<TitleDefinition>>> Pending = new Dictionary<string, List<Action<TitleDefinition>>>(StringComparer.OrdinalIgnoreCase);

		public static event Action<TitleDefinition> OnTitleUnlocked;

		public static event Action<TitleDefinition> OnTitleEquipped;

		public static event Action<TitleSlot, TitleDefinition> OnSlotChanged;

		public static bool RegisterTitle(TitleDefinition title)
		{
			if (title == null || string.IsNullOrEmpty(title.Id))
			{
				return false;
			}
			if (Titles.ContainsKey(title.Id))
			{
				Logger.LogWarning((object)("Title id '" + title.Id + "' is already registered, skipping."));
				return false;
			}
			Titles[title.Id] = title;
			Ordered.Add(title);
			if (Pending.TryGetValue(title.Id, out var value))
			{
				foreach (Action<TitleDefinition> item in value)
				{
					item(title);
				}
				Pending.Remove(title.Id);
			}
			return true;
		}

		public static void AddSkillBonus(string titleId, string skillName, float levels)
		{
			ChangeTitle(titleId, delegate(TitleDefinition t)
			{
				t.Bonus(skillName, levels);
			});
		}

		public static void AddSkillBonus(string titleId, SkillType skill, float levels)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			ChangeTitle(titleId, delegate(TitleDefinition t)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				t.Bonus(skill, levels);
			});
		}

		public static void AddSkillFloor(string titleId, string skillName, float level)
		{
			ChangeTitle(titleId, delegate(TitleDefinition t)
			{
				t.ProtectSkill(skillName, level);
			});
		}

		public static void AddSkillFloor(string titleId, SkillType skill, float level)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			ChangeTitle(titleId, delegate(TitleDefinition t)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				t.ProtectSkill(skill, level);
			});
		}

		public static void AddStatBonus(string titleId, string stat, float amount)
		{
			ChangeTitle(titleId, delegate(TitleDefinition t)
			{
				t.Stat(stat, amount);
			});
		}

		private static void ChangeTitle(string titleId, Action<TitleDefinition> change)
		{
			if (Titles.TryGetValue(titleId, out var value))
			{
				change(value);
				return;
			}
			if (!Pending.TryGetValue(titleId, out var value2))
			{
				value2 = (Pending[titleId] = new List<Action<TitleDefinition>>());
			}
			value2.Add(change);
		}

		public static TitleDefinition GetTitle(string id)
		{
			TitleDefinition value;
			return (id != null && Titles.TryGetValue(id, out value)) ? value : null;
		}

		public static IReadOnlyList<TitleDefinition> GetAllTitles()
		{
			return Ordered;
		}

		public static bool IsUnlocked(string titleId)
		{
			return TitleManager.IsUnlocked(titleId);
		}

		public static void Unlock(string titleId)
		{
			TitleManager.Unlock(GetTitle(titleId));
		}

		public static TitleDefinition GetEquippedTitle()
		{
			return TitleManager.GetEquipped(TitleSlot.Main);
		}

		public static TitleDefinition GetEquippedTitle(TitleSlot slot)
		{
			return TitleManager.GetEquipped(slot);
		}

		public static IEnumerable<TitleDefinition> GetEquippedTitles()
		{
			return TitleManager.EquippedTitles;
		}

		public static string GetFullTitle()
		{
			return TitleManager.FullTitle;
		}

		public static IReadOnlyList<string> GetConnectors()
		{
			return TitleManager.AvailableConnectors;
		}

		public static void AddConnector(string word)
		{
			TitleManager.AddConnector(word);
		}

		public static float GetSkillBonus(SkillType skill)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return TitleManager.GetSkillBonus(skill);
		}

		public static float GetSkillFloor(SkillType skill)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			return ((Object)(object)localPlayer != (Object)null) ? TitleManager.GetSkillFloor(skill, TitleManager.GetRawSkillLevel(localPlayer, skill)) : 0f;
		}

		public static float GetStatBonus(string stat)
		{
			return TitleManager.GetStatBonus(stat);
		}

		public static int GetCounter(string key)
		{
			return TitleManager.GetCounter(key);
		}

		public static void IncrementCounter(string key, int amount = 1)
		{
			TitleManager.Increment(key, amount);
		}

		internal static void RaiseUnlocked(TitleDefinition t)
		{
			SafeInvoke(TitleAPI.OnTitleUnlocked, t);
		}

		internal static void RaiseEquipped(TitleSlot slot, TitleDefinition t)
		{
			SafeInvoke(TitleAPI.OnTitleEquipped, t);
			if (TitleAPI.OnSlotChanged == null)
			{
				return;
			}
			Delegate[] invocationList = TitleAPI.OnSlotChanged.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				Action<TitleSlot, TitleDefinition> action = (Action<TitleSlot, TitleDefinition>)invocationList[i];
				try
				{
					action(slot, t);
				}
				catch (Exception arg)
				{
					Logger.LogError((object)$"Title event handler failed: {arg}");
				}
			}
		}

		private static void SafeInvoke(Action<TitleDefinition> handlers, TitleDefinition t)
		{
			if (handlers == null)
			{
				return;
			}
			Delegate[] invocationList = handlers.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				Action<TitleDefinition> action = (Action<TitleDefinition>)invocationList[i];
				try
				{
					action(t);
				}
				catch (Exception arg)
				{
					Logger.LogError((object)$"Title event handler failed: {arg}");
				}
			}
		}
	}
	public enum TitleSlot
	{
		Prefix,
		Main,
		Suffix
	}
	public enum TitleKind
	{
		Main,
		Epithet
	}
	public class TitleDefinition
	{
		public string Id { get; }

		public string Name { get; set; }

		public string Description { get; set; }

		public TitleKind Kind { get; set; } = TitleKind.Main;

		public bool AlwaysUnlocked { get; set; }

		public bool ServerGranted { get; set; }

		public List<float> TierFloors { get; } = new List<float>();

		public bool Hidden { get; set; }

		public List<TitleRequirement> Requirements { get; } = new List<TitleRequirement>();

		public List<SkillBonus> SkillBonuses { get; } = new List<SkillBonus>();

		public List<SkillFloor> SkillFloors { get; } = new List<SkillFloor>();

		public List<StatBonus> StatBonuses { get; } = new List<StatBonus>();

		public string Group { get; set; }

		public TitleDefinition(string id, string name, string description)
		{
			Id = id;
			Name = name;
			Description = description;
		}

		public static TitleDefinition SkillMilestone(string id, string name, string skillName, float level, string skillLabel = null)
		{
			string arg = skillLabel ?? skillName;
			return new TitleDefinition(id, name, $"Reach {arg} level {level:0}. While equipped, dying never lowers it below {level:0}.").Require(TitleRequirement.SkillLevel(skillName, level)).ProtectSkill(skillName, level).SetGroup("skill:" + skillName);
		}

		public TitleDefinition Require(TitleRequirement requirement)
		{
			Requirements.Add(requirement);
			return this;
		}

		public TitleDefinition Bonus(string skillName, float levels)
		{
			SkillBonuses.Add(new SkillBonus(skillName, levels));
			return this;
		}

		public TitleDefinition Bonus(SkillType skill, float levels)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Expected I4, but got Unknown
			return Bonus(((int)skill).ToString(), levels);
		}

		public TitleDefinition ProtectSkill(string skillName, float level)
		{
			SkillFloors.Add(new SkillFloor(skillName, level));
			return this;
		}

		public TitleDefinition ProtectSkill(SkillType skill, float level)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Expected I4, but got Unknown
			return ProtectSkill(((int)skill).ToString(), level);
		}

		public TitleDefinition Stat(string stat, float amount)
		{
			StatBonuses.Add(new StatBonus(stat, amount));
			return this;
		}

		public TitleDefinition SetHidden(bool hidden = true)
		{
			Hidden = hidden;
			return this;
		}

		public TitleDefinition SetGroup(string group)
		{
			Group = group;
			return this;
		}

		public TitleDefinition SetKind(TitleKind kind)
		{
			Kind = kind;
			return this;
		}

		public TitleDefinition AsEpithet()
		{
			return SetKind(TitleKind.Epithet);
		}

		public bool FitsSlot(TitleSlot slot)
		{
			return true;
		}

		public TitleDefinition SetAlwaysUnlocked(bool value = true)
		{
			AlwaysUnlocked = value;
			return this;
		}

		public TitleDefinition SetServerGranted(bool value = true)
		{
			ServerGranted = value;
			return this;
		}

		public TitleDefinition ProtectAllSkillsAtTiers(params float[] tiers)
		{
			TierFloors.AddRange(tiers);
			TierFloors.Sort();
			return this;
		}

		public float TierFloorFor(float level)
		{
			float num = 0f;
			foreach (float tierFloor in TierFloors)
			{
				if (tierFloor <= level)
				{
					num = Mathf.Max(num, tierFloor);
				}
			}
			return num;
		}

		public bool RequirementsMet(Player player)
		{
			return AlwaysUnlocked || (Requirements.Count > 0 && Requirements.All((TitleRequirement r) => r.IsMet(player)));
		}

		public string RewardText()
		{
			IEnumerable<string> first = SkillBonuses.Select((SkillBonus b) => $"+{b.Levels:0.#} {b.DisplayName}").Concat(SkillFloors.Select((SkillFloor f) => $"{f.DisplayName} kept at {f.Level:0}+"));
			if (TierFloors.Count > 0)
			{
				first = first.Concat(new string[1] { "every skill kept at its highest threshold (" + string.Join("/", TierFloors.Select((float t) => t.ToString("0")).ToArray()) + ")" });
			}
			return string.Join(", ", first.Concat(StatBonuses.Select((StatBonus s) => TitleStats.Describe(s.Stat, s.Amount))).ToArray());
		}
	}
	public class SkillReference
	{
		private SkillType resolved;

		private bool isResolved;

		private float nextAttempt;

		public string SkillName { get; }

		public unsafe string DisplayName
		{
			get
			{
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Invalid comparison between Unknown and I4
				if (!TryResolve(out var skill))
				{
					return SkillName;
				}
				if ((int)skill == 999)
				{
					return "all skills";
				}
				Localization instance = Localization.instance;
				string text = ((instance != null) ? instance.Localize("$skill_" + ((object)(*(SkillType*)(&skill))/*cast due to .constrained prefix*/).ToString().ToLower()) : null);
				return (string.IsNullOrEmpty(text) || text.StartsWith("[")) ? SkillName : text;
			}
		}

		public SkillReference(string skillName)
		{
			SkillName = skillName;
		}

		public bool TryResolve(out SkillType skill)
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Expected I4, but got Unknown
			//IL_0046: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			if (!isResolved && Time.time >= nextAttempt)
			{
				nextAttempt = Time.time + 10f;
				if (Enum.TryParse<SkillType>(SkillName, ignoreCase: true, out SkillType result))
				{
					resolved = result;
					isResolved = true;
				}
				else
				{
					SkillDef skill2 = SkillManager.Instance.GetSkill(SkillName);
					if (skill2 != null)
					{
						resolved = skill2.m_skill;
						isResolved = true;
					}
				}
			}
			skill = (SkillType)(int)resolved;
			return isResolved;
		}
	}
	public class SkillBonus : SkillReference
	{
		public float Levels { get; }

		public SkillBonus(string skillName, float levels)
			: base(skillName)
		{
			Levels = levels;
		}
	}
	public class SkillFloor : SkillReference
	{
		public float Level { get; }

		public SkillFloor(string skillName, float level)
			: base(skillName)
		{
			Level = level;
		}
	}
	internal static class TitleManager
	{
		[HarmonyPatch(typeof(Game), "UpdateRespawn")]
		private static class FreshSpawnPatch
		{
			private static void Prefix(Game __instance, out bool __state)
			{
				__state = __instance.GetPlayerProfile() != null && __instance.GetPlayerProfile().m_firstSpawn;
			}

			private static void Postfix(Game __instance, bool __state)
			{
				if (__state && __instance.GetPlayerProfile() != null && !__instance.GetPlayerProfile().m_firstSpawn)
				{
					freshSpawnPending = true;
				}
			}
		}

		[HarmonyPatch(typeof(Skills), "GetSkillLevel")]
		private static class SkillLevelPatch
		{
			private static void Postfix(Skills __instance, SkillType skillType, ref float __result)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				if ((int)skillType != 0 && IsTrackedSkills(__instance))
				{
					__result += GetSkillBonus(skillType);
				}
			}
		}

		[HarmonyPatch(typeof(Skills), "LowerAllSkills")]
		private static class DeathPenaltyPatch
		{
			private static void Prefix(Skills __instance, ref float factor, out Dictionary<Skill, float> __state)
			{
				//IL_0069: Unknown result type (might be due to invalid IL or missing references)
				__state = null;
				if (!IsTrackedSkills(__instance))
				{
					return;
				}
				factor *= Mathf.Clamp01(1f - GetStatBonus("DeathSkillLoss") / 100f);
				if (!HasAnyFloor())
				{
					return;
				}
				__state = new Dictionary<Skill, float>();
				foreach (Skill skill in __instance.GetSkillList())
				{
					float num = Mathf.Min(GetSkillFloor(skill.m_info.m_skill, skill.m_level), skill.m_level);
					if (num > 0f)
					{
						__state[skill] = num;
					}
				}
			}

			private static void Postfix(Dictionary<Skill, float> __state)
			{
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				//IL_006e: Expected I4, but got Unknown
				if (__state == null)
				{
					return;
				}
				List<string> list = new List<string>();
				foreach (KeyValuePair<Skill, float> item in __state)
				{
					if (!(item.Key.m_level >= item.Value))
					{
						item.Key.m_level = item.Value;
						list.Add(new SkillReference(((int)item.Key.m_info.m_skill).ToString()).DisplayName);
					}
				}
				if (list.Count > 0)
				{
					((Character)trackedPlayer).Message((MessageType)1, "Your title protected: " + string.Join(", ", list.ToArray()), 0, (Sprite)null, false);
				}
			}
		}

		private class PickupInfo
		{
			public string Prefab;

			public int Amount;
		}

		[HarmonyPatch(typeof(Humanoid), "Pickup")]
		private static class PickupPatch
		{
			private static void Prefix(Humanoid __instance, GameObject go, out PickupInfo __state)
			{
				__state = null;
				if ((Object)(object)trackedPlayer == (Object)null || (Object)(object)__instance != (Object)(object)trackedPlayer || (Object)(object)go == (Object)null)
				{
					return;
				}
				ItemDrop component = go.GetComponent<ItemDrop>();
				if (!((Object)(object)component == (Object)null))
				{
					ZNetView component2 = go.GetComponent<ZNetView>();
					if (!((Object)(object)component2 != (Object)null) || !component2.IsValid() || !component2.GetZDO().GetBool("TitlesMod_Dropped", false))
					{
						__state = new PickupInfo
						{
							Prefab = Utils.GetPrefabName(go),
							Amount = component.m_itemData.m_stack
						};
					}
				}
			}

			private static void Postfix(bool __result, PickupInfo __state)
			{
				if (__result && __state != null)
				{
					Increment("gather:" + __state.Prefab, __state.Amount);
				}
			}
		}

		[HarmonyPatch(typeof(ItemDrop), "DropItem")]
		private static class DropPatch
		{
			private static void Postfix(ItemDrop __result)
			{
				ZNetView val = (((Object)(object)__result != (Object)null) ? ((Component)__result).GetComponent<ZNetView>() : null);
				if ((Object)(object)val != (Object)null && val.IsValid())
				{
					val.GetZDO().Set("TitlesMod_Dropped", true);
				}
			}
		}

		[HarmonyPatch(typeof(Humanoid), "StartAttack")]
		private static class HeavyAttackPatch
		{
			private static void Postfix(Humanoid __instance, bool secondaryAttack, bool __result)
			{
				//IL_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_004d: Invalid comparison between Unknown and I4
				if (__result && !((Object)(object)trackedPlayer == (Object)null) && !((Object)(object)__instance != (Object)(object)trackedPlayer))
				{
					if (secondaryAttack)
					{
						Increment("heavyattack");
					}
					ItemData currentWeapon = __instance.GetCurrentWeapon();
					if (currentWeapon != null && (int)currentWeapon.m_shared.m_skillType == 10)
					{
						Increment("magic:blood");
					}
				}
			}
		}

		[HarmonyPatch(typeof(Player), "PlacePiece")]
		private static class BuildPatch
		{
			private static void Postfix(Player __instance, Piece piece)
			{
				if (!((Object)(object)__instance != (Object)(object)trackedPlayer) && !((Object)(object)piece == (Object)null))
				{
					Increment("build:" + Utils.GetPrefabName(((Component)piece).gameObject));
					Increment("build:*");
				}
			}
		}

		[HarmonyPatch(typeof(Character), "Damage")]
		private static class DamagePatch
		{
			private static void Prefix(Character __instance, HitData hit)
			{
				if (!((Object)(object)trackedPlayer == (Object)null) && hit != null && !(__instance is Player) && !((Object)(object)hit.GetAttacker() != (Object)(object)trackedPlayer) && !__instance.IsDead())
				{
					KillTracker.OnHit(__instance);
					if (hit.m_damage.m_fire > 0f)
					{
						Increment("element:fire");
					}
					if (hit.m_damage.m_frost > 0f)
					{
						Increment("element:frost");
					}
					if (hit.m_damage.m_lightning > 0f)
					{
						Increment("element:lightning");
					}
					if (hit.m_damage.m_poison > 0f)
					{
						Increment("element:poison");
					}
					if (hit.m_damage.m_spirit > 0f)
					{
						Increment("element:spirit");
					}
					if (hit.m_backstabBonus > 1f)
					{
						hit.m_backstabBonus *= 1f + GetStatBonus("SneakAttack") / 100f;
					}
					if (__instance.IsBoss())
					{
						MultiplyCombatDamage(ref hit.m_damage, 1f + GetStatBonus("BossDamage") / 100f);
					}
					hit.m_staggerMultiplier *= 1f + GetStatBonus("StaggerBonus") / 100f;
					float statBonus = GetStatBonus("Lifesteal");
					if (statBonus > 0f)
					{
						((Character)trackedPlayer).Heal(hit.GetTotalDamage() * statBonus / 100f, true);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Chat), "SendText")]
		private static class ChatTitlePatch
		{
			private static void Prefix(ref string text)
			{
				string value = TitlesPlugin.ChatFormat.Value;
				if (!((Object)(object)trackedPlayer == (Object)null) && !string.IsNullOrEmpty(value) && !string.IsNullOrEmpty(text))
				{
					string fullTitle = FullTitle;
					if (fullTitle.Length > 0)
					{
						text = value.Replace("{title}", fullTitle).Replace("{text}", text);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Terminal), "AddString", new Type[]
		{
			typeof(PlatformUserID),
			typeof(string),
			typeof(Type),
			typeof(bool)
		})]
		private static class ChatColorPatch
		{
			private static void Prefix(PlatformUserID user, ref string text)
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				PlayerInfo val = default(PlayerInfo);
				if (ZDOMan.instance != null && ZNet.TryGetPlayerByPlatformUserID(user, ref val))
				{
					ZDO zDO = ZDOMan.instance.GetZDO(val.m_characterID);
					if (zDO != null)
					{
						text = Colorize(text, zDO.GetString("TitlesMod_Title", ""), ColorOf(zDO));
					}
				}
			}
		}

		[HarmonyPatch(typeof(Chat), "AddInworldText")]
		private static class InworldColorPatch
		{
			private static void Prefix(GameObject go, long senderID, ref string text)
			{
				ZDO val = SpeakerZdo(go, senderID);
				if (val != null)
				{
					text = Colorize(text, val.GetString("TitlesMod_Title", ""), ColorOf(val));
				}
			}
		}

		[HarmonyPatch(typeof(Player), "GetHoverName")]
		private static class HoverNamePatch
		{
			private static void Postfix(Player __instance, ref string __result)
			{
				if (!TitlesPlugin.ShowTitleOverName.Value)
				{
					return;
				}
				ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
				if (!((Object)(object)component == (Object)null) && component.IsValid())
				{
					ZDO zDO = component.GetZDO();
					string text = zDO.GetString("TitlesMod_Title", "");
					if (text.Length > 0)
					{
						__result = TitlesPlugin.NameFormat.Value.Replace("{name}", __result).Replace("{title}", text).Replace("{color}", ColorOf(zDO))
							.Replace("\\n", "\n");
					}
				}
			}
		}

		private const string UnlockedKey = "TitlesMod.Unlocked";

		private const string EquippedKey = "TitlesMod.Equipped";

		private const string CountersKey = "TitlesMod.Counters";

		private const string ColorKey = "TitlesMod.Color";

		internal const string ZdoTitleKey = "TitlesMod_Title";

		internal const string ZdoColorKey = "TitlesMod_Color";

		internal const string ZdoEquippedKey = "TitlesMod_Equipped";

		public const string DefaultColor = "FFD27F";

		internal const string ZdoDroppedKey = "TitlesMod_Dropped";

		private static Player trackedPlayer;

		private static readonly HashSet<string> Unlocked = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, int> Counters = new Dictionary<string, int>();

		private static readonly string[] EquippedIds = new string[3];

		private static readonly string[] Words = new string[2];

		internal const string NoWord = "";

		internal const string SpaceWord = " ";

		private const string DefaultWord1 = " ";

		private const string DefaultWord2 = "the";

		public static readonly TitleSlot[] Slots = new TitleSlot[3]
		{
			TitleSlot.Prefix,
			TitleSlot.Main,
			TitleSlot.Suffix
		};

		private static string colorHex = "FFD27F";

		private static readonly List<string> ExtraConnectors = new List<string>();

		public static readonly HashSet<string> WordEndings = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "er", "ed", "est" };

		private static bool countersChanged;

		internal const string DaysPlayedCounter = "days:played";

		private static int lastDay = -1;

		internal const string MapTracker = "map";

		private static readonly Dictionary<string, List<TitleDefinition>> TitlesByTracker = new Dictionary<string, List<TitleDefinition>>();

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

		private static int indexedTitles = -1;

		internal const string FreshSpawnCounter = "freshspawn";

		private static bool freshSpawnPending;

		internal const string ColdCounter = "cold";

		internal const string FreezingCounter = "freezing";

		internal const string RestSecondsCounter = "rest:seconds";

		internal const string HotTubCounter = "hottub";

		private static readonly List<Piece> nearbyPieces = new List<Piece>();

		public static readonly SkillType[] WeaponSkills;

		private static readonly Dictionary<SkillType, float> RawLevels;

		private static int rawLevelsFrame;

		private static Player rawLevelsPlayer;

		private static readonly FieldRef<Skills, Player> SkillsPlayer;

		internal const string HeavyAttackCounter = "heavyattack";

		internal const string BloodMagicCounter = "magic:blood";

		public static Color TitleColor
		{
			get
			{
				//IL_001f: 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)
				Color val = default(Color);
				return ColorUtility.TryParseHtmlString("#" + colorHex, ref val) ? val : Color.white;
			}
		}

		public static IEnumerable<TitleDefinition> EquippedTitles => from t in Slots.Select(GetEquipped)
			where t != null
			select t;

		public static List<string> AvailableConnectors
		{
			get
			{
				List<string> list = new List<string> { "", " " };
				foreach (string item in TitlesPlugin.ConnectorWords.Value.Split(new char[1] { '|' }).Concat(ExtraConnectors))
				{
					string text = item.Trim();
					if (text.Length > 0 && !list.Contains(text))
					{
						list.Add(text);
					}
				}
				return list;
			}
		}

		public static string FullTitle
		{
			get
			{
				string text = GetEquipped(TitleSlot.Prefix)?.Name;
				string text2 = GetEquipped(TitleSlot.Main)?.Name;
				string text3 = GetEquipped(TitleSlot.Suffix)?.Name;
				string text4 = text ?? "";
				if (text2 != null)
				{
					text4 = ((text != null) ? Join(text4, GetWord(TitleSlot.Prefix), text2) : Lead(GetWord(TitleSlot.Prefix), text2));
				}
				if (text3 != null)
				{
					text4 = ((text4.Length > 0) ? Join(text4, GetWord(TitleSlot.Suffix), text3) : text3);
				}
				return text4;
			}
		}

		public static void SetColor(Color color)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)trackedPlayer == (Object)null))
			{
				colorHex = ColorUtility.ToHtmlStringRGB(color);
				Save();
				SyncTitleToZdo();
			}
		}

		private static bool IsHexColor(string s)
		{
			return s != null && s.Length == 6 && s.All(Uri.IsHexDigit);
		}

		internal static string ColorOf(ZDO zdo)
		{
			string text = ((zdo != null) ? zdo.GetString("TitlesMod_Color", "") : "");
			return IsHexColor(text) ? text : "FFD27F";
		}

		internal static string Colorize(string text, string title, string hex)
		{
			if (string.IsNullOrEmpty(text) || string.IsNullOrEmpty(title))
			{
				return text;
			}
			int num = text.IndexOf(title, StringComparison.Ordinal);
			if (num < 0)
			{
				return text;
			}
			return text.Substring(0, num) + "<color=#" + hex + ">" + title + "</color>" + text.Substring(num + title.Length);
		}

		public static TitleDefinition GetEquipped(TitleSlot slot)
		{
			TitleDefinition title = TitleAPI.GetTitle(EquippedIds[(int)slot]);
			return (title != null && IsUnlocked(title)) ? title : null;
		}

		public static TitleSlot? SlotOf(TitleDefinition title)
		{
			TitleSlot[] slots = Slots;
			foreach (TitleSlot titleSlot in slots)
			{
				if (title != null && GetEquipped(titleSlot) == title)
				{
					return titleSlot;
				}
			}
			return null;
		}

		public static bool IsEquipped(TitleDefiniti