Decompiled source of Empress Achievements v2.0.1

BepInEx\plugins\Empress_Achievements\RepoAchievements.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;
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(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("Empress")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+79ae26948f15ddd0825c08f9c67eab7df2c0586c")]
[assembly: AssemblyProduct("RepoAchievements")]
[assembly: AssemblyTitle("RepoAchievements")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 Empress.REPO.Achievements
{
	[HarmonyPatch]
	internal static class EmpressAchievementsPlus
	{
		private readonly struct ThresholdAchievement
		{
			public readonly string Id;

			public readonly long Threshold;

			public readonly string Title;

			public readonly string Description;

			public ThresholdAchievement(string id, long threshold, string title, string description)
			{
				Id = id;
				Threshold = threshold;
				Title = title;
				Description = description;
			}
		}

		private readonly struct SpreeAchievement
		{
			public readonly string Id;

			public readonly int Count;

			public readonly float WindowSeconds;

			public readonly string Title;

			public readonly string Description;

			public SpreeAchievement(string id, int count, float windowSeconds, string title, string description)
			{
				Id = id;
				Count = count;
				WindowSeconds = windowSeconds;
				Title = title;
				Description = description;
			}
		}

		private readonly struct EnemyTypeInfo
		{
			public readonly string Id;

			public readonly string Label;

			public readonly string HundredTitle;

			public EnemyTypeInfo(string id, string label, string hundredTitle)
			{
				Id = id;
				Label = label;
				HundredTitle = hundredTitle;
			}
		}

		private static readonly Queue<float> KillTimestamps = new Queue<float>();

		private static bool Defined;

		private static readonly ThresholdAchievement[] MetaAchievements = new ThresholdAchievement[10]
		{
			new ThresholdAchievement("ach_meta_10", 10L, "Warmed Up", "Unlock 10 achievements."),
			new ThresholdAchievement("ach_meta_25", 25L, "On Your Way", "Unlock 25 achievements."),
			new ThresholdAchievement("ach_meta_50", 50L, "Certified Collector", "Unlock 50 achievements."),
			new ThresholdAchievement("ach_meta_75", 75L, "Overachiever", "Unlock 75 achievements."),
			new ThresholdAchievement("ach_meta_90", 90L, "No Brakes", "Unlock 90 achievements."),
			new ThresholdAchievement("ach_meta_100", 100L, "Triple Digits", "Unlock 100 achievements."),
			new ThresholdAchievement("ach_meta_125", 125L, "Badge Buffet", "Unlock 125 achievements."),
			new ThresholdAchievement("ach_meta_150", 150L, "Archive Monster", "Unlock 150 achievements."),
			new ThresholdAchievement("ach_meta_175", 175L, "Cabinet Crusher", "Unlock 175 achievements."),
			new ThresholdAchievement("ach_meta_200", 200L, "Empress Certified", "Unlock 200 achievements.")
		};

		private static readonly ThresholdAchievement[] ExtractionAchievements = new ThresholdAchievement[5]
		{
			new ThresholdAchievement("extract_300", 300L, "Night Shift", "Complete 300 extractions (lifetime)."),
			new ThresholdAchievement("extract_500", 500L, "Route Owned", "Complete 500 extractions (lifetime)."),
			new ThresholdAchievement("extract_750", 750L, "Platform Ghost", "Complete 750 extractions (lifetime)."),
			new ThresholdAchievement("extract_1000", 1000L, "Timetable Tyrant", "Complete 1,000 extractions (lifetime)."),
			new ThresholdAchievement("extract_2000", 2000L, "Terminal Deity", "Complete 2,000 extractions (lifetime).")
		};

		private static readonly ThresholdAchievement[] DiscoveryAchievements = new ThresholdAchievement[10]
		{
			new ThresholdAchievement("discover_5", 5L, "Shiny Thing", "Discover 5 valuables."),
			new ThresholdAchievement("discover_10", 10L, "Curio Finder", "Discover 10 valuables."),
			new ThresholdAchievement("discover_25", 25L, "Antiquarian", "Discover 25 valuables."),
			new ThresholdAchievement("discover_50", 50L, "Treasure Sleuth", "Discover 50 valuables."),
			new ThresholdAchievement("discover_75", 75L, "Display Case", "Discover 75 valuables."),
			new ThresholdAchievement("discover_100", 100L, "Museum Curator", "Discover 100 valuables."),
			new ThresholdAchievement("discover_150", 150L, "Treasure Map Brain", "Discover 150 valuables."),
			new ThresholdAchievement("discover_250", 250L, "Vault Tourist", "Discover 250 valuables."),
			new ThresholdAchievement("discover_500", 500L, "Curation Problem", "Discover 500 valuables."),
			new ThresholdAchievement("discover_1000", 1000L, "Relic Census", "Discover 1,000 valuables.")
		};

		private static readonly ThresholdAchievement[] LifetimePurchaseAchievements = new ThresholdAchievement[6]
		{
			new ThresholdAchievement("big_spender_5", 5L, "Browsing No More", "Purchase 5 items (lifetime)."),
			new ThresholdAchievement("big_spender_75", 75L, "Impulse Engine", "Purchase 75 items (lifetime)."),
			new ThresholdAchievement("big_spender_150", 150L, "Receipt Collector", "Purchase 150 items (lifetime)."),
			new ThresholdAchievement("big_spender_250", 250L, "Bag Secured", "Purchase 250 items (lifetime)."),
			new ThresholdAchievement("big_spender_500", 500L, "Market Mover", "Purchase 500 items (lifetime)."),
			new ThresholdAchievement("big_spender_1000", 1000L, "Checkout Monarch", "Purchase 1,000 items (lifetime).")
		};

		private static readonly ThresholdAchievement[] LifetimeDeathAchievements = new ThresholdAchievement[6]
		{
			new ThresholdAchievement("death_75", 75L, "Bruise Budget", "Die 75 times."),
			new ThresholdAchievement("death_150", 150L, "Frequent Flyer Home", "Die 150 times."),
			new ThresholdAchievement("death_250", 250L, "Ragdoll Royalty", "Die 250 times."),
			new ThresholdAchievement("death_750", 750L, "Pain Dividend", "Die 750 times."),
			new ThresholdAchievement("death_1000", 1000L, "Afterlife Residency", "Die 1,000 times."),
			new ThresholdAchievement("death_2500", 2500L, "Professional Corpse", "Die 2,500 times.")
		};

		private static readonly ThresholdAchievement[] LifetimeReviveAchievements = new ThresholdAchievement[6]
		{
			new ThresholdAchievement("revived_5", 5L, "Still Standing", "Be revived 5 times."),
			new ThresholdAchievement("revived_25", 25L, "Miracle Mileage", "Be revived 25 times."),
			new ThresholdAchievement("revived_100", 100L, "Defibrillator Darling", "Be revived 100 times."),
			new ThresholdAchievement("revived_250", 250L, "Return Policy", "Be revived 250 times."),
			new ThresholdAchievement("revived_500", 500L, "Unfinished Business", "Be revived 500 times."),
			new ThresholdAchievement("revived_1000", 1000L, "Too Stubborn To Die", "Be revived 1,000 times.")
		};

		private static readonly ThresholdAchievement[] LifetimeHaulAchievements = new ThresholdAchievement[12]
		{
			new ThresholdAchievement("life_haul_75k", 75000L, "Coin Pile", "Accumulate 75,000 haul (lifetime)."),
			new ThresholdAchievement("life_haul_150k", 150000L, "Payroll Problem", "Accumulate 150,000 haul (lifetime)."),
			new ThresholdAchievement("life_haul_300k", 300000L, "Treasure Warehouse", "Accumulate 300,000 haul (lifetime)."),
			new ThresholdAchievement("life_haul_750k", 750000L, "Bag Mountain", "Accumulate 750,000 haul (lifetime)."),
			new ThresholdAchievement("life_haul_1p5m", 1500000L, "Capital Gain", "Accumulate 1,500,000 haul (lifetime)."),
			new ThresholdAchievement("life_haul_3m", 3000000L, "Fortune Engine", "Accumulate 3,000,000 haul (lifetime)."),
			new ThresholdAchievement("life_haul_7p5m", 7500000L, "Vault Fever", "Accumulate 7,500,000 haul (lifetime)."),
			new ThresholdAchievement("life_haul_15m", 15000000L, "Estate Sale", "Accumulate 15,000,000 haul (lifetime)."),
			new ThresholdAchievement("life_haul_30m", 30000000L, "Treasure State", "Accumulate 30,000,000 haul (lifetime)."),
			new ThresholdAchievement("life_haul_75m", 75000000L, "Museum Theft", "Accumulate 75,000,000 haul (lifetime)."),
			new ThresholdAchievement("life_haul_100m", 100000000L, "Nine Digits", "Accumulate 100,000,000 haul (lifetime)."),
			new ThresholdAchievement("life_haul_250m", 250000000L, "Economic Event", "Accumulate 250,000,000 haul (lifetime).")
		};

		private static readonly ThresholdAchievement[] RunPurchaseAchievements = new ThresholdAchievement[9]
		{
			new ThresholdAchievement("run_purchases_5", 5L, "Bag Starter", "Buy 5 items in a single run."),
			new ThresholdAchievement("run_purchases_10", 10L, "Shopaholic (Run)", "Buy 10 items in a single run."),
			new ThresholdAchievement("run_purchases_15", 15L, "Basket Case", "Buy 15 items in a single run."),
			new ThresholdAchievement("run_purchases_20", 20L, "Receipt Storm", "Buy 20 items in a single run."),
			new ThresholdAchievement("run_purchases_25", 25L, "Retail Bender", "Buy 25 items in a single run."),
			new ThresholdAchievement("run_purchases_30", 30L, "Checkout Sprint", "Buy 30 items in a single run."),
			new ThresholdAchievement("run_purchases_40", 40L, "Mall Marathon", "Buy 40 items in a single run."),
			new ThresholdAchievement("run_purchases_50", 50L, "Store Sweep", "Buy 50 items in a single run."),
			new ThresholdAchievement("run_purchases_75", 75L, "Inventory Collapse", "Buy 75 items in a single run.")
		};

		private static readonly ThresholdAchievement[] RunDeathAchievements = new ThresholdAchievement[8]
		{
			new ThresholdAchievement("deaths_run_3", 3L, "Trip Hazard", "Die 3 times in a single run."),
			new ThresholdAchievement("deaths_run_5", 5L, "Learning Hurts", "Die 5 times in a single run."),
			new ThresholdAchievement("deaths_run_7", 7L, "Bruise Loop", "Die 7 times in a single run."),
			new ThresholdAchievement("deaths_run_10", 10L, "Pain Enthusiast", "Die 10 times in a single run."),
			new ThresholdAchievement("deaths_run_15", 15L, "Red Screen Residency", "Die 15 times in a single run."),
			new ThresholdAchievement("deaths_run_20", 20L, "Certified Masochist", "Die 20 times in a single run."),
			new ThresholdAchievement("deaths_run_25", 25L, "Spawn Tax", "Die 25 times in a single run."),
			new ThresholdAchievement("deaths_run_50", 50L, "Hazard Magnet", "Die 50 times in a single run.")
		};

		private static readonly ThresholdAchievement[] RunKillAchievements = new ThresholdAchievement[10]
		{
			new ThresholdAchievement("run_kills_5", 5L, "Warmup Violence", "Eliminate 5 enemies in a single run."),
			new ThresholdAchievement("run_kills_10", 10L, "Cleanup Crew", "Eliminate 10 enemies in a single run."),
			new ThresholdAchievement("run_kills_15", 15L, "Run Riot", "Eliminate 15 enemies in a single run."),
			new ThresholdAchievement("run_kills_25", 25L, "Bloody Hands", "Eliminate 25 enemies in a single run."),
			new ThresholdAchievement("run_kills_50", 50L, "Crowd Control", "Eliminate 50 enemies in a single run."),
			new ThresholdAchievement("run_kills_75", 75L, "Corridor Clearer", "Eliminate 75 enemies in a single run."),
			new ThresholdAchievement("run_kills_100", 100L, "Neighborhood Watch", "Eliminate 100 enemies in a single run."),
			new ThresholdAchievement("run_kills_150", 150L, "Run Terminator", "Eliminate 150 enemies in a single run."),
			new ThresholdAchievement("run_kills_250", 250L, "Room Zero", "Eliminate 250 enemies in a single run."),
			new ThresholdAchievement("run_kills_500", 500L, "Extinction Event", "Eliminate 500 enemies in a single run.")
		};

		private static readonly ThresholdAchievement[] LifetimeKillAchievements = new ThresholdAchievement[7]
		{
			new ThresholdAchievement("kills_750", 750L, "Bad Neighborhood", "Eliminate 750 enemies."),
			new ThresholdAchievement("kills_7500", 7500L, "Hazard Department", "Eliminate 7,500 enemies."),
			new ThresholdAchievement("kills_10000", 10000L, "Bureau of Population", "Eliminate 10,000 enemies."),
			new ThresholdAchievement("kills_15000", 15000L, "Local Legend", "Eliminate 15,000 enemies."),
			new ThresholdAchievement("kills_25000", 25000L, "Body Count Clerk", "Eliminate 25,000 enemies."),
			new ThresholdAchievement("kills_50000", 50000L, "Extinction Budget", "Eliminate 50,000 enemies."),
			new ThresholdAchievement("kills_100000", 100000L, "Disaster Economist", "Eliminate 100,000 enemies.")
		};

		private static readonly ThresholdAchievement[] ChargeSessionAchievements = new ThresholdAchievement[8]
		{
			new ThresholdAchievement("charge_session_1", 1L, "Juiced", "Start charging at a station."),
			new ThresholdAchievement("charge_session_5", 5L, "Outlet Friend", "Start charging at stations 5 times."),
			new ThresholdAchievement("charge_session_10", 10L, "Power User", "Start charging at stations 10 times."),
			new ThresholdAchievement("charge_session_25", 25L, "Grid Hog", "Start charging at stations 25 times."),
			new ThresholdAchievement("charge_session_50", 50L, "Socket Specialist", "Start charging at stations 50 times."),
			new ThresholdAchievement("charge_session_100", 100L, "Grid Romantic", "Start charging at stations 100 times."),
			new ThresholdAchievement("charge_session_250", 250L, "Transformer Whisperer", "Start charging at stations 250 times."),
			new ThresholdAchievement("charge_session_500", 500L, "Power Parasite", "Start charging at stations 500 times.")
		};

		private static readonly ThresholdAchievement[] ChargeTotalAchievements = new ThresholdAchievement[10]
		{
			new ThresholdAchievement("charge_total_50", 50L, "Spark Touched", "Accumulate 50 total station charge in a run."),
			new ThresholdAchievement("charge_total_100", 100L, "Watt About It", "Accumulate 100 total station charge in a run."),
			new ThresholdAchievement("charge_total_250", 250L, "Static Drinker", "Accumulate 250 total station charge in a run."),
			new ThresholdAchievement("charge_total_500", 500L, "Peak Demand", "Accumulate 500 total station charge in a run."),
			new ThresholdAchievement("charge_total_750", 750L, "Amp Appetite", "Accumulate 750 total station charge in a run."),
			new ThresholdAchievement("charge_total_1000", 1000L, "Brownout", "Accumulate 1,000 total station charge in a run."),
			new ThresholdAchievement("charge_total_1500", 1500L, "Voltage Appetite", "Accumulate 1,500 total station charge in a run."),
			new ThresholdAchievement("charge_total_2500", 2500L, "Overclocked Soul", "Accumulate 2,500 total station charge in a run."),
			new ThresholdAchievement("charge_total_5000", 5000L, "Grid Collapse", "Accumulate 5,000 total station charge in a run."),
			new ThresholdAchievement("charge_total_10000", 10000L, "Citywide Brownout", "Accumulate 10,000 total station charge in a run.")
		};

		private static readonly ThresholdAchievement[] RunMoneyAchievements = new ThresholdAchievement[10]
		{
			new ThresholdAchievement("run_money_125000", 125000L, "Loaded", "Reach 125,000 run currency."),
			new ThresholdAchievement("run_money_150000", 150000L, "High Roller", "Reach 150,000 run currency."),
			new ThresholdAchievement("run_money_200000", 200000L, "Cash Current", "Reach 200,000 run currency."),
			new ThresholdAchievement("run_money_250000", 250000L, "Mega Whale", "Reach 250,000 run currency."),
			new ThresholdAchievement("run_money_300000", 300000L, "Money Pit Boss", "Reach 300,000 run currency."),
			new ThresholdAchievement("run_money_400000", 400000L, "Wall of Bills", "Reach 400,000 run currency."),
			new ThresholdAchievement("run_money_500000", 500000L, "Infinite Wallet", "Reach 500,000 run currency."),
			new ThresholdAchievement("run_money_750000", 750000L, "Private Bank", "Reach 750,000 run currency."),
			new ThresholdAchievement("run_money_1000000", 1000000L, "Seven Digits", "Reach 1,000,000 run currency."),
			new ThresholdAchievement("run_money_2000000", 2000000L, "Money Printer", "Reach 2,000,000 run currency.")
		};

		private static readonly ThresholdAchievement[] RunHaulAchievements = new ThresholdAchievement[7]
		{
			new ThresholdAchievement("run_haul_75000", 75000L, "Packed Tight", "Reach 75,000 haul value in a run."),
			new ThresholdAchievement("run_haul_100000", 100000L, "Full Truck", "Reach 100,000 haul value in a run."),
			new ThresholdAchievement("run_haul_150000", 150000L, "Heavy Freight", "Reach 150,000 haul value in a run."),
			new ThresholdAchievement("run_haul_250000", 250000L, "Haul Beast", "Reach 250,000 haul value in a run."),
			new ThresholdAchievement("run_haul_500000", 500000L, "Warehouse On Legs", "Reach 500,000 haul value in a run."),
			new ThresholdAchievement("run_haul_750000", 750000L, "Museum Eviction", "Reach 750,000 haul value in a run."),
			new ThresholdAchievement("run_haul_1000000", 1000000L, "Everything Must Go", "Reach 1,000,000 haul value in a run.")
		};

		private static readonly ThresholdAchievement[] RunLevelAchievements = new ThresholdAchievement[11]
		{
			new ThresholdAchievement("run_level_2", 2L, "Second Stop", "Reach level 2 in a run."),
			new ThresholdAchievement("run_level_3", 3L, "Third Shift", "Reach level 3 in a run."),
			new ThresholdAchievement("run_level_4", 4L, "Fourth Wind", "Reach level 4 in a run."),
			new ThresholdAchievement("run_level_5", 5L, "Warm Depths", "Reach level 5 in a run."),
			new ThresholdAchievement("run_level_6", 6L, "Below Comfortable", "Reach level 6 in a run."),
			new ThresholdAchievement("run_level_7", 7L, "Further Down", "Reach level 7 in a run."),
			new ThresholdAchievement("run_level_8", 8L, "Depth Charge", "Reach level 8 in a run."),
			new ThresholdAchievement("run_level_10", 10L, "Deep Delver", "Reach level 10 in a run."),
			new ThresholdAchievement("run_level_12", 12L, "Dark Mileage", "Reach level 12 in a run."),
			new ThresholdAchievement("run_level_15", 15L, "Abyss Dweller", "Reach level 15 in a run."),
			new ThresholdAchievement("run_level_20", 20L, "No Sun Left", "Reach level 20 in a run.")
		};

		private static readonly ThresholdAchievement[] NoDeathStreakAchievements = new ThresholdAchievement[9]
		{
			new ThresholdAchievement("nodeath_streak_2", 2L, "Back-to-Back", "Extract deathless twice in a row."),
			new ThresholdAchievement("nodeath_streak_3", 3L, "Clean Hands", "Extract deathless 3 times in a row."),
			new ThresholdAchievement("nodeath_streak_5", 5L, "On Fire", "Extract deathless 5 times in a row."),
			new ThresholdAchievement("nodeath_streak_7", 7L, "Never Touched", "Extract deathless 7 times in a row."),
			new ThresholdAchievement("nodeath_streak_10", 10L, "Untouchable++", "Extract deathless 10 times in a row."),
			new ThresholdAchievement("nodeath_streak_15", 15L, "Ghost Route", "Extract deathless 15 times in a row."),
			new ThresholdAchievement("nodeath_streak_25", 25L, "Perfect Habit", "Extract deathless 25 times in a row."),
			new ThresholdAchievement("nodeath_streak_50", 50L, "Deathless Religion", "Extract deathless 50 times in a row."),
			new ThresholdAchievement("nodeath_streak_100", 100L, "Myth Of Safety", "Extract deathless 100 times in a row.")
		};

		private static readonly SpreeAchievement[] KillSpreeAchievements = new SpreeAchievement[5]
		{
			new SpreeAchievement("kill_spree_3_5s", 3, 5f, "Opening Flurry", "Eliminate 3 enemies within 5 seconds."),
			new SpreeAchievement("kill_spree_5_10s", 5, 10f, "Quick Hands", "Eliminate 5 enemies within 10 seconds."),
			new SpreeAchievement("kill_spree_7_10s", 7, 10f, "Chain Reaction", "Eliminate 7 enemies within 10 seconds."),
			new SpreeAchievement("kill_spree_10_15s", 10, 15f, "No Survivors Nearby", "Eliminate 10 enemies within 15 seconds."),
			new SpreeAchievement("kill_spree_15_20s", 15, 20f, "Screen Wipe", "Eliminate 15 enemies within 20 seconds.")
		};

		private static readonly EnemyTypeInfo[] EnemyTypes = new EnemyTypeInfo[5]
		{
			new EnemyTypeInfo("VeryLight", "Very Light", "Snack Extinction"),
			new EnemyTypeInfo("Light", "Light", "Light's Out"),
			new EnemyTypeInfo("Medium", "Medium", "Middle Management Axed"),
			new EnemyTypeInfo("Heavy", "Heavy", "Heavy Industry"),
			new EnemyTypeInfo("VeryHeavy", "Very Heavy", "Gravitational Collapse")
		};

		[HarmonyPostfix]
		[HarmonyPatch(typeof(AchievementBook), "DefineDefaults")]
		private static void PostDefineDefaults()
		{
			if (!Defined)
			{
				Defined = true;
				DefineMany(MetaAchievements);
				DefineMany(ExtractionAchievements);
				DefineMany(DiscoveryAchievements);
				DefineMany(LifetimePurchaseAchievements);
				DefineMany(LifetimeDeathAchievements);
				DefineMany(LifetimeReviveAchievements);
				DefineMany(LifetimeHaulAchievements);
				DefineMany(RunPurchaseAchievements);
				DefineMany(RunDeathAchievements);
				DefineMany(RunKillAchievements);
				DefineMany(LifetimeKillAchievements);
				DefineMany(ChargeSessionAchievements);
				DefineMany(ChargeTotalAchievements);
				DefineMany(RunMoneyAchievements);
				DefineMany(RunHaulAchievements);
				DefineMany(RunLevelAchievements);
				DefineMany(NoDeathStreakAchievements);
				Define("no_purchase_run", "Barebones", "Extract without buying anything that run.");
				DefineSpreeAchievements();
				DefineEnemyTypeAchievements();
				ManualLogSource log = EmpressAchievementsPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)("[ACH+] Extra definitions loaded: " + AchievementBook.All.Count));
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(RoundDirector), "StartRoundRPC")]
		private static void PostRoundStart()
		{
			ResetRunCounter("kills_run");
			ResetRunCounter("run_purchases");
			KillTimestamps.Clear();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ValuableObject), "DiscoverRPC")]
		private static void PostDiscover()
		{
			EmpressAchievementsPlugin.Store.AddToCounter("discoveries", 1L);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(StatsManager), "ItemPurchase")]
		private static void PostItemPurchase()
		{
			EmpressAchievementsPlugin.Store.AddToCounter("run_purchases", 1L);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ChargingStation), "StartChargeRPC")]
		private static void PostChargeStart()
		{
			EmpressAchievementsPlugin.Store.AddToCounter("charge_sessions", 1L);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(PunManager), "SetRunStatSet")]
		private static void PostRunStatSet(string statName, int value)
		{
			if (string.Equals(statName, "currency", StringComparison.OrdinalIgnoreCase))
			{
				UnlockThresholds(value, RunMoneyAchievements);
			}
			else if (string.Equals(statName, "level", StringComparison.OrdinalIgnoreCase))
			{
				UnlockThresholds(value, RunLevelAchievements);
			}
			else if (string.Equals(statName, "chargingStationChargeTotal", StringComparison.OrdinalIgnoreCase))
			{
				UnlockThresholds(value, ChargeTotalAchievements);
			}
			else if (string.Equals(statName, "totalHaul", StringComparison.OrdinalIgnoreCase))
			{
				UnlockThresholds(value, RunHaulAchievements);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(RoundDirector), "ExtractionCompleted")]
		private static void PostExtractionCompleted()
		{
			if (EmpressAchievementsPlugin.Store.GetCounter("run_purchases") == 0)
			{
				EmpressAchievementsPlugin.Unlock("no_purchase_run");
			}
			if (EmpressAchievementsPlugin.GetStat("run_deaths") == 0)
			{
				long value = EmpressAchievementsPlugin.Store.GetCounter("nodeath_streak") + 1;
				EmpressAchievementsPlugin.Store.SetCounter("nodeath_streak", value);
				UnlockThresholds(value, NoDeathStreakAchievements);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(PlayerAvatar), "PlayerDeathRPC")]
		private static void PostPlayerDeath(PlayerAvatar __instance)
		{
			PhotonView val = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponent<PhotonView>() : null);
			if (!((Object)(object)val != (Object)null) || val.IsMine)
			{
				EmpressAchievementsPlugin.Store.SetCounter("nodeath_streak", 0L);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(AchievementStore), "AddToCounter")]
		private static void PostAddToCounter(AchievementStore __instance, string key, long delta)
		{
			switch (key)
			{
			case "extractions":
				UnlockThresholds(__instance.GetCounter(key), ExtractionAchievements);
				break;
			case "discoveries":
				UnlockThresholds(__instance.GetCounter(key), DiscoveryAchievements);
				break;
			case "purchases":
				UnlockThresholds(__instance.GetCounter(key), LifetimePurchaseAchievements);
				break;
			case "deaths":
				UnlockThresholds(__instance.GetCounter(key), LifetimeDeathAchievements);
				break;
			case "revives":
				UnlockThresholds(__instance.GetCounter(key), LifetimeReviveAchievements);
				break;
			case "life_haul":
				UnlockThresholds(__instance.GetCounter(key), LifetimeHaulAchievements);
				break;
			case "run_purchases":
				UnlockThresholds(__instance.GetCounter(key), RunPurchaseAchievements);
				break;
			case "run_deaths":
				UnlockThresholds(__instance.GetCounter(key), RunDeathAchievements);
				break;
			case "kills_run":
				UnlockThresholds(__instance.GetCounter(key), RunKillAchievements);
				break;
			case "kills_total":
				if (delta > 0)
				{
					__instance.AddToCounter("kills_run", delta);
					RegisterKillTime(Time.unscaledTime);
				}
				UnlockThresholds(__instance.GetCounter(key), LifetimeKillAchievements);
				break;
			case "charge_sessions":
				UnlockThresholds(__instance.GetCounter(key), ChargeSessionAchievements);
				break;
			default:
				if (key.StartsWith("kills_type_", StringComparison.OrdinalIgnoreCase))
				{
					UnlockEnemyTypeThresholds(key.Substring("kills_type_".Length), __instance.GetCounter(key));
				}
				break;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(AchievementStore), "Unlock")]
		private static void PostUnlock(AchievementStore __instance, string id)
		{
			AchievementStore __instance2 = __instance;
			try
			{
				int num = AchievementBook.All.Keys.Count((string k) => __instance2.IsUnlocked(k));
				UnlockThresholds(num, MetaAchievements);
			}
			catch (Exception ex)
			{
				ManualLogSource log = EmpressAchievementsPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[ACH+] Meta unlock check failed: " + ex));
				}
			}
		}

		private static void ResetRunCounter(string key)
		{
			long counter = EmpressAchievementsPlugin.Store.GetCounter(key);
			if (counter != 0)
			{
				EmpressAchievementsPlugin.Store.AddToCounter(key, -counter);
			}
		}

		private static void RegisterKillTime(float now)
		{
			KillTimestamps.Enqueue(now);
			float num = 0f;
			SpreeAchievement[] killSpreeAchievements = KillSpreeAchievements;
			for (int i = 0; i < killSpreeAchievements.Length; i++)
			{
				SpreeAchievement spreeAchievement = killSpreeAchievements[i];
				if (spreeAchievement.WindowSeconds > num)
				{
					num = spreeAchievement.WindowSeconds;
				}
			}
			while (KillTimestamps.Count > 0 && now - KillTimestamps.Peek() > num)
			{
				KillTimestamps.Dequeue();
			}
			float[] array = KillTimestamps.ToArray();
			SpreeAchievement[] killSpreeAchievements2 = KillSpreeAchievements;
			for (int j = 0; j < killSpreeAchievements2.Length; j++)
			{
				SpreeAchievement spreeAchievement2 = killSpreeAchievements2[j];
				int num2 = 0;
				int num3 = array.Length - 1;
				while (num3 >= 0 && !(now - array[num3] > spreeAchievement2.WindowSeconds))
				{
					num2++;
					num3--;
				}
				if (num2 >= spreeAchievement2.Count)
				{
					EmpressAchievementsPlugin.Unlock(spreeAchievement2.Id);
				}
			}
		}

		private static void DefineMany(IEnumerable<ThresholdAchievement> achievements)
		{
			foreach (ThresholdAchievement achievement in achievements)
			{
				Define(achievement.Id, achievement.Title, achievement.Description);
			}
		}

		private static void DefineSpreeAchievements()
		{
			SpreeAchievement[] killSpreeAchievements = KillSpreeAchievements;
			for (int i = 0; i < killSpreeAchievements.Length; i++)
			{
				SpreeAchievement spreeAchievement = killSpreeAchievements[i];
				Define(spreeAchievement.Id, spreeAchievement.Title, spreeAchievement.Description);
			}
		}

		private static void DefineEnemyTypeAchievements()
		{
			EnemyTypeInfo[] enemyTypes = EnemyTypes;
			for (int i = 0; i < enemyTypes.Length; i++)
			{
				EnemyTypeInfo enemyTypeInfo = enemyTypes[i];
				Define("kill_type_" + enemyTypeInfo.Id + "_10", enemyTypeInfo.Label + " Hunter I", "Eliminate 10 " + enemyTypeInfo.Label + " enemies.");
				Define("kill_type_" + enemyTypeInfo.Id + "_50", enemyTypeInfo.Label + " Hunter II", "Eliminate 50 " + enemyTypeInfo.Label + " enemies.");
				Define("kill_type_" + enemyTypeInfo.Id + "_100", enemyTypeInfo.HundredTitle, "Eliminate 100 " + enemyTypeInfo.Label + " enemies.");
				Define("kill_type_" + enemyTypeInfo.Id + "_250", enemyTypeInfo.Label + " Hunter III", "Eliminate 250 " + enemyTypeInfo.Label + " enemies.");
				Define("kill_type_" + enemyTypeInfo.Id + "_500", enemyTypeInfo.Label + " Hunter IV", "Eliminate 500 " + enemyTypeInfo.Label + " enemies.");
			}
		}

		private static void UnlockEnemyTypeThresholds(string typeId, long value)
		{
			if (value >= 10)
			{
				EmpressAchievementsPlugin.Unlock("kill_type_" + typeId + "_10");
			}
			if (value >= 50)
			{
				EmpressAchievementsPlugin.Unlock("kill_type_" + typeId + "_50");
			}
			if (value >= 100)
			{
				EmpressAchievementsPlugin.Unlock("kill_type_" + typeId + "_100");
			}
			if (value >= 250)
			{
				EmpressAchievementsPlugin.Unlock("kill_type_" + typeId + "_250");
			}
			if (value >= 500)
			{
				EmpressAchievementsPlugin.Unlock("kill_type_" + typeId + "_500");
			}
		}

		private static void UnlockThresholds(long value, IEnumerable<ThresholdAchievement> achievements)
		{
			foreach (ThresholdAchievement achievement in achievements)
			{
				if (value >= achievement.Threshold)
				{
					EmpressAchievementsPlugin.Unlock(achievement.Id);
				}
			}
		}

		private static void Define(string id, string title, string description)
		{
			AchievementBook.All[id] = new AchievementDef(id, title, description);
		}
	}
	[BepInPlugin("empress.repo.achievements", "Empress Achievements", "1.3.8")]
	public class EmpressAchievementsPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "empress.repo.achievements";

		public const string PluginName = "Empress Achievements";

		public const string PluginVersion = "1.3.8";

		private Harmony _harmony;

		internal static ConfigEntry<KeyCode> ToggleUiKey;

		internal static ConfigEntry<bool> EnableSound;

		internal static ConfigEntry<string> SoundFileName;

		internal static ConfigEntry<float> SoundVolume;

		internal static ConfigEntry<float> floatToastSeconds;

		internal static ConfigEntry<int> UiScalePercent;

		internal static ConfigEntry<bool> DebugLogJsonPreview;

		internal static ManualLogSource Log;

		internal static EmpressAchievementsPlugin Instance;

		internal static EmpressAchievementsRuntime Runtime;

		internal static ToastUi Toast;

		internal static AchievementsUi AchievementsPanel;

		internal static AchievementStore Store;

		internal static bool TalliedExtractionThisRound = false;

		internal static float LastLocalDeathTime = -999f;

		internal static float LastPurchaseTime = -999f;

		internal static HashSet<int> ProcessedKillHashes = new HashSet<int>();

		private static int LastUiUpdateFrame = -1;

		private void Awake()
		{
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Expected O, but got Unknown
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			ToggleUiKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("UI", "ToggleKey", (KeyCode)289, "Key to open/close achievements panel");
			UiScalePercent = ((BaseUnityPlugin)this).Config.Bind<int>("UI", "UiScalePercent", 100, "UI scale percentage (100=default)");
			floatToastSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "ToastSeconds", 4f, "Seconds a toast stays visible");
			DebugLogJsonPreview = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogJsonPreview", false, "Log first ~300 chars of JSON after save.");
			EnableSound = ((BaseUnityPlugin)this).Config.Bind<bool>("Sound", "EnableSound", true, "Play a sound when an achievement pops");
			SoundFileName = ((BaseUnityPlugin)this).Config.Bind<string>("Sound", "SoundFileName", "empress_achievement.ogg", "Audio file placed next to the DLL (wav/ogg/mp3)");
			SoundVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Sound", "Volume", 70f, new ConfigDescription("Toast sound volume percent (0-100). Older 0-1 values are auto-converted.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			SoundVolume.SettingChanged += delegate
			{
				ClampSoundVolumeConfig();
			};
			ClampSoundVolumeConfig();
			string pluginFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? Paths.PluginPath;
			Store = new AchievementStore(pluginFolder, "empress_achievements.json");
			Log.LogInfo((object)("[ACH] Canonical save => " + Store.CanonicalFile));
			Store.Load();
			DumpFileMap("Boot");
			_harmony = new Harmony("empress.repo.achievements");
			_harmony.PatchAll(Assembly.GetExecutingAssembly());
			EnsureRuntimeHost();
			BootstrapUi();
			AchievementBook.DefineDefaults();
			Log.LogInfo((object)("Empress Achievements v1.3.8 loaded. Achievements: " + AchievementBook.All.Count));
		}

		private static void EnsureRuntimeHost()
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			if ((Object)(object)Runtime != (Object)null)
			{
				Runtime.EmpressBoot();
				return;
			}
			Runtime = Object.FindObjectOfType<EmpressAchievementsRuntime>();
			if ((Object)(object)Runtime != (Object)null)
			{
				Runtime.EmpressBoot();
				return;
			}
			GameObject val = new GameObject("Empress_AchievementsRuntime");
			val.transform.SetParent((Transform)null);
			((Object)val).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)val);
			Runtime = val.AddComponent<EmpressAchievementsRuntime>();
			Runtime.EmpressBoot();
		}

		private static bool InitializeUIComponents()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				EnsureRuntimeHost();
				GameObject val = (GameObject)(((Object)(object)Runtime != (Object)null) ? ((object)((Component)Runtime).gameObject) : ((object)new GameObject("Empress_AchievementUI_Root")));
				if ((Object)(object)Runtime == (Object)null)
				{
					Object.DontDestroyOnLoad((Object)(object)val);
				}
				Toast = val.GetComponent<ToastUi>();
				if ((Object)(object)Toast == (Object)null)
				{
					Toast = val.AddComponent<ToastUi>();
				}
				Toast.Duration = floatToastSeconds.Value;
				Toast.Volume = GetSoundVolume01();
				Toast.EnableSound = EnableSound.Value;
				string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? Paths.PluginPath;
				Toast.SoundFilePath = (Path.IsPathRooted(SoundFileName.Value) ? SoundFileName.Value : Path.Combine(path, SoundFileName.Value));
				Toast.UiScale = (float)UiScalePercent.Value / 100f;
				AchievementsPanel = val.GetComponent<AchievementsUi>();
				if ((Object)(object)AchievementsPanel == (Object)null)
				{
					AchievementsPanel = val.AddComponent<AchievementsUi>();
				}
				AchievementsPanel.UiScale = Toast.UiScale;
				return true;
			}
			catch (Exception ex)
			{
				Log.LogError((object)("[ACH] UI init failed: " + ex));
				return false;
			}
		}

		private static bool EnsureUiReady()
		{
			EnsureRuntimeHost();
			bool flag = (Object)(object)Toast != (Object)null && Object.op_Implicit((Object)(object)Toast);
			bool flag2 = (Object)(object)AchievementsPanel != (Object)null && Object.op_Implicit((Object)(object)AchievementsPanel);
			if (!flag || !flag2)
			{
				Toast = null;
				AchievementsPanel = null;
				if (!InitializeUIComponents())
				{
					return false;
				}
			}
			Toast.Duration = floatToastSeconds.Value;
			Toast.Volume = GetSoundVolume01();
			Toast.EnableSound = EnableSound.Value;
			Toast.UiScale = (float)UiScalePercent.Value / 100f;
			string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? Paths.PluginPath;
			Toast.SoundFilePath = (Path.IsPathRooted(SoundFileName.Value) ? SoundFileName.Value : Path.Combine(path, SoundFileName.Value));
			AchievementsPanel.UiScale = Toast.UiScale;
			RequestToastSoundLoad();
			return true;
		}

		private static void RequestToastSoundLoad()
		{
			if (!((Object)(object)Toast == (Object)null) && Toast.NeedsSoundLoad())
			{
				if ((Object)(object)Instance != (Object)null && Object.op_Implicit((Object)(object)Instance))
				{
					((MonoBehaviour)Instance).StartCoroutine(Toast.LoadSoundCoroutine());
				}
				else if ((Object)(object)Runtime != (Object)null && Object.op_Implicit((Object)(object)Runtime))
				{
					Runtime.StartManagedCoroutine(Toast.LoadSoundCoroutine());
				}
			}
		}

		private void OnDestroy()
		{
			if (Instance == this)
			{
				Instance = null;
			}
			try
			{
				Store?.Save();
			}
			catch
			{
			}
		}

		private void OnApplicationQuit()
		{
			try
			{
				Store?.Save();
			}
			catch
			{
			}
		}

		private void Update()
		{
			RuntimeUpdate();
		}

		internal static void RuntimeUpdate()
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			int frameCount = Time.frameCount;
			if (LastUiUpdateFrame == frameCount)
			{
				return;
			}
			LastUiUpdateFrame = frameCount;
			if (EnsureUiReady())
			{
				RequestToastSoundLoad();
				if (Input.GetKeyDown(ToggleUiKey.Value) || Input.GetKeyDown((KeyCode)289))
				{
					AchievementsPanel.Toggle();
				}
				float num = (float)UiScalePercent.Value / 100f;
				if (Mathf.Abs(num - Toast.UiScale) > 0.001f)
				{
					Toast.UiScale = num;
					AchievementsPanel.UiScale = num;
					Toast.RefreshScale();
					AchievementsPanel.RefreshScale();
				}
			}
		}

		private static void BootstrapUi()
		{
			if (EnsureUiReady())
			{
				AchievementsPanel.Prime();
				RequestToastSoundLoad();
			}
		}

		private static float GetSoundVolume01()
		{
			ClampSoundVolumeConfig();
			return Mathf.Clamp(SoundVolume.Value, 0f, 100f) / 100f;
		}

		private static void ClampSoundVolumeConfig()
		{
			if (SoundVolume != null)
			{
				float num = SoundVolume.Value;
				if (num > 0f && num <= 1.01f)
				{
					num *= 100f;
				}
				float num2 = Mathf.Clamp(num, 0f, 100f);
				if (Math.Abs(SoundVolume.Value - num2) > 0.001f)
				{
					SoundVolume.Value = num2;
				}
			}
		}

		internal static void DumpFileMap(string tag)
		{
			try
			{
				string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? Paths.PluginPath;
				string[] source = new string[3]
				{
					Path.Combine(Paths.ConfigPath, "EmpressAchievements", "empress_achievements.json"),
					Path.Combine(path, "empress_achievements.json"),
					Path.Combine(Paths.ConfigPath, "empress.repo.achievements.json")
				};
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)("[ACH][FileMap/" + tag + "] Scanning known locations:"));
				}
				foreach (string item in source.Distinct())
				{
					if (File.Exists(item))
					{
						FileInfo fileInfo = new FileInfo(item);
						ManualLogSource log2 = Log;
						if (log2 != null)
						{
							log2.LogInfo((object)$"[ACH][FileMap/{tag}] {item} | size={fileInfo.Length} | modified={fileInfo.LastWriteTimeUtc:O}");
						}
					}
					else
					{
						ManualLogSource log3 = Log;
						if (log3 != null)
						{
							log3.LogInfo((object)("[ACH][FileMap/" + tag + "] (missing) " + item));
						}
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log4 = Log;
				if (log4 != null)
				{
					log4.LogWarning((object)("[ACH][FileMap] " + ex));
				}
			}
		}

		public static void Pop(string title, string body)
		{
			if (EnsureUiReady())
			{
				Toast.Pop(title, body);
			}
		}

		public static void Unlock(string id)
		{
			AchievementDef achievementDef = AchievementBook.Get(id);
			if (achievementDef != null && !Store.IsUnlocked(id))
			{
				Store.Unlock(id);
				Pop(achievementDef.Title, achievementDef.Description);
				if ((Object)(object)AchievementsPanel != (Object)null && Object.op_Implicit((Object)(object)AchievementsPanel))
				{
					AchievementsPanel.RefreshAllIfOpen();
				}
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)("[ACH] Unlocked: " + achievementDef.Id + " - " + achievementDef.Title));
				}
				Store.Save();
			}
		}

		public static void BumpStat(string key, int delta = 1)
		{
			Store.AddToCounter(key, delta);
			if ((Object)(object)AchievementsPanel != (Object)null && Object.op_Implicit((Object)(object)AchievementsPanel))
			{
				AchievementsPanel.RefreshStatsIfOpen();
			}
		}

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

		internal static string FormatK(long value)
		{
			long num = Math.Abs(value);
			if (num >= 1000)
			{
				float num2 = (float)value / 1000f;
				string text = ((Mathf.Abs(num2 - Mathf.Round(num2)) < 0.05f) ? num2.ToString("0") : num2.ToString("0.#"));
				return text + "K";
			}
			return value.ToString("N0");
		}
	}
	internal sealed class EmpressAchievementsRuntime : MonoBehaviour
	{
		private bool _booted;

		internal void EmpressBoot()
		{
			if (!_booted)
			{
				_booted = true;
				EmpressAchievementsPlugin.RuntimeUpdate();
			}
		}

		internal Coroutine StartManagedCoroutine(IEnumerator routine)
		{
			return ((MonoBehaviour)this).StartCoroutine(routine);
		}

		private void Update()
		{
			EmpressAchievementsPlugin.RuntimeUpdate();
		}
	}
	[Serializable]
	public class AchievementState
	{
		public string Id;

		public bool Unlocked;

		public int UnlockedAtUnix;
	}
	[Serializable]
	public class CounterKV
	{
		public string Key;

		public int Value;
	}
	[Serializable]
	public class AchievementsSave
	{
		public List<AchievementState> Achievements = new List<AchievementState>();

		public List<CounterKV> Counters = new List<CounterKV>();

		public int SchemaVersion = 2;
	}
	internal static class SaveJson
	{
		private static string Esc(string s)
		{
			if (s == null)
			{
				return "";
			}
			StringBuilder stringBuilder = new StringBuilder(s.Length + 8);
			foreach (char c in s)
			{
				switch (c)
				{
				case '"':
					stringBuilder.Append("\\\"");
					continue;
				case '\\':
					stringBuilder.Append("\\\\");
					continue;
				case '\b':
					stringBuilder.Append("\\b");
					continue;
				case '\f':
					stringBuilder.Append("\\f");
					continue;
				case '\n':
					stringBuilder.Append("\\n");
					continue;
				case '\r':
					stringBuilder.Append("\\r");
					continue;
				case '\t':
					stringBuilder.Append("\\t");
					continue;
				}
				if (c < ' ')
				{
					StringBuilder stringBuilder2 = stringBuilder.Append("\\u");
					int num = c;
					stringBuilder2.Append(num.ToString("x4"));
				}
				else
				{
					stringBuilder.Append(c);
				}
			}
			return stringBuilder.ToString();
		}

		public static string Serialize(AchievementsSave data)
		{
			StringBuilder stringBuilder = new StringBuilder(Mathf.Max(1024, (data.Achievements.Count + data.Counters.Count) * 64));
			stringBuilder.Append("{\n  \"Achievements\": [");
			for (int i = 0; i < data.Achievements.Count; i++)
			{
				AchievementState achievementState = data.Achievements[i];
				if (i > 0)
				{
					stringBuilder.Append(',');
				}
				stringBuilder.Append("\n    {").Append("\"Id\":\"").Append(Esc(achievementState.Id ?? ""))
					.Append("\",")
					.Append("\"Unlocked\":")
					.Append(achievementState.Unlocked ? "true" : "false")
					.Append(',')
					.Append("\"UnlockedAtUnix\":")
					.Append(achievementState.UnlockedAtUnix)
					.Append('}');
			}
			stringBuilder.Append("\n  ],\n  \"Counters\": [");
			for (int j = 0; j < data.Counters.Count; j++)
			{
				CounterKV counterKV = data.Counters[j];
				if (j > 0)
				{
					stringBuilder.Append(',');
				}
				stringBuilder.Append("\n    {").Append("\"Key\":\"").Append(Esc(counterKV.Key ?? ""))
					.Append("\",")
					.Append("\"Value\":")
					.Append(counterKV.Value)
					.Append('}');
			}
			stringBuilder.Append("\n  ],\n  \"SchemaVersion\": ").Append(data.SchemaVersion).Append("\n}");
			return stringBuilder.ToString();
		}
	}
	internal static class LoadJsonFallback
	{
		private static bool ArrayLooksPopulated(string json, string key)
		{
			Regex regex = new Regex("\"" + Regex.Escape(key) + "\"\\s*:\\s*\\[\\s*\\{", RegexOptions.Singleline);
			return regex.IsMatch(json);
		}

		private static string ExtractArray(string json, string key)
		{
			int num = json.IndexOf("\"" + key + "\"", StringComparison.Ordinal);
			if (num < 0)
			{
				return null;
			}
			int num2 = json.IndexOf('[', num);
			if (num2 < 0)
			{
				return null;
			}
			int num3 = 0;
			for (int i = num2; i < json.Length; i++)
			{
				switch (json[i])
				{
				case '[':
					num3++;
					break;
				case ']':
					num3--;
					if (num3 == 0)
					{
						return json.Substring(num2, i - num2 + 1);
					}
					break;
				}
			}
			return null;
		}

		public static bool JsonIndicatesItems(string json, out bool hasA, out bool hasC)
		{
			hasA = ArrayLooksPopulated(json, "Achievements");
			hasC = ArrayLooksPopulated(json, "Counters");
			return hasA | hasC;
		}

		public static bool TryParse(string json, out AchievementsSave save)
		{
			save = new AchievementsSave();
			try
			{
				string text = ExtractArray(json, "Achievements");
				string text2 = ExtractArray(json, "Counters");
				if (!string.IsNullOrEmpty(text))
				{
					Regex regex = new Regex("\\{\\s*\"Id\"\\s*:\\s*\"(?<id>.*?)\"\\s*,\\s*\"Unlocked\"\\s*:\\s*(?<u>true|false)\\s*,\\s*\"UnlockedAtUnix\"\\s*:\\s*(?<t>-?\\d+)\\s*\\}", RegexOptions.Singleline);
					foreach (Match item in regex.Matches(text))
					{
						int result;
						AchievementState achievementState = new AchievementState
						{
							Id = item.Groups["id"].Value,
							Unlocked = (item.Groups["u"].Value == "true"),
							UnlockedAtUnix = (int.TryParse(item.Groups["t"].Value, out result) ? result : 0)
						};
						if (!string.IsNullOrEmpty(achievementState.Id))
						{
							save.Achievements.Add(achievementState);
						}
					}
				}
				if (!string.IsNullOrEmpty(text2))
				{
					Regex regex2 = new Regex("\\{\\s*\"Key\"\\s*:\\s*\"(?<k>.*?)\"\\s*,\\s*\"Value\"\\s*:\\s*(?<v>-?\\d+)\\s*\\}", RegexOptions.Singleline);
					foreach (Match item2 in regex2.Matches(text2))
					{
						int result2;
						CounterKV counterKV = new CounterKV
						{
							Key = item2.Groups["k"].Value,
							Value = (int.TryParse(item2.Groups["v"].Value, out result2) ? result2 : 0)
						};
						if (!string.IsNullOrEmpty(counterKV.Key))
						{
							save.Counters.Add(counterKV);
						}
					}
				}
				Regex regex3 = new Regex("\"SchemaVersion\"\\s*:\\s*(?<s>\\d+)");
				Match match3 = regex3.Match(json);
				if (match3.Success && int.TryParse(match3.Groups["s"].Value, out var result3))
				{
					save.SchemaVersion = result3;
				}
				return true;
			}
			catch
			{
				save = new AchievementsSave();
				return false;
			}
		}
	}
	public class AchievementStore
	{
		private readonly string _pluginFolder;

		private readonly string _pluginFile;

		private AchievementsSave _data = new AchievementsSave();

		private readonly Dictionary<string, long> _counters = new Dictionary<string, long>();

		public string CanonicalFolder => Path.Combine(Paths.ConfigPath, "EmpressAchievements");

		public string CanonicalFile => Path.Combine(CanonicalFolder, "empress_achievements.json");

		private string PluginOldFile => _pluginFile;

		private string LegacyConfigFile => Path.Combine(Paths.ConfigPath, "empress.repo.achievements.json");

		public AchievementStore(string pluginFolder, string filename)
		{
			_pluginFolder = pluginFolder;
			_pluginFile = Path.Combine(pluginFolder, filename);
		}

		public bool IsUnlocked(string id)
		{
			string id2 = id;
			return _data.Achievements.Any((AchievementState a) => a.Id == id2 && a.Unlocked);
		}

		public long GetCounter(string key)
		{
			long value;
			return _counters.TryGetValue(key, out value) ? value : 0;
		}

		public void AddToCounter(string key, long delta)
		{
			if (!_counters.ContainsKey(key))
			{
				_counters[key] = 0L;
			}
			_counters[key] += delta;
			Save();
		}

		public void SetCounter(string key, long value)
		{
			_counters[key] = value;
			Save();
		}

		public void Unlock(string id)
		{
			string id2 = id;
			AchievementState achievementState = _data.Achievements.FirstOrDefault((AchievementState a) => a.Id == id2);
			if (achievementState == null)
			{
				achievementState = new AchievementState
				{
					Id = id2
				};
				_data.Achievements.Add(achievementState);
			}
			achievementState.Unlocked = true;
			long num = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
			achievementState.UnlockedAtUnix = (int)((num > int.MaxValue) ? int.MaxValue : num);
			Save();
		}

		public void Load()
		{
			try
			{
				EnsureCanonicalDir();
				List<string> list = new List<string>();
				if (File.Exists(CanonicalFile))
				{
					list.Add(CanonicalFile);
				}
				if (File.Exists(PluginOldFile))
				{
					list.Add(PluginOldFile);
				}
				if (File.Exists(LegacyConfigFile))
				{
					list.Add(LegacyConfigFile);
				}
				string text = ((list.Count > 0) ? list.OrderByDescending(SafeGetWriteTimeUtc).First() : null);
				if (text == null)
				{
					PersistCanonical(SaveJson.Serialize(_data), verify: true, "Fresh");
					ManualLogSource log = EmpressAchievementsPlugin.Log;
					if (log != null)
					{
						log.LogInfo((object)"[ACH] Created fresh save.");
					}
					return;
				}
				string text2 = File.ReadAllText(text, Encoding.UTF8);
				AchievementsSave achievementsSave = null;
				bool flag = false;
				try
				{
					if (!string.IsNullOrWhiteSpace(text2))
					{
						achievementsSave = JsonUtility.FromJson<AchievementsSave>(text2);
					}
				}
				catch
				{
					achievementsSave = null;
				}
				LoadJsonFallback.JsonIndicatesItems(text2, out var hasA, out var hasC);
				if ((achievementsSave == null || achievementsSave.Achievements == null || achievementsSave.Counters == null || (achievementsSave.Achievements != null && achievementsSave.Achievements.Count == 0 && hasA) || (achievementsSave.Counters != null && achievementsSave.Counters.Count == 0 && hasC)) && LoadJsonFallback.TryParse(text2, out AchievementsSave save))
				{
					achievementsSave = save;
					flag = true;
				}
				if (achievementsSave != null)
				{
					_data = achievementsSave;
					AchievementsSave data = _data;
					if (data.Achievements == null)
					{
						data.Achievements = new List<AchievementState>();
					}
					data = _data;
					if (data.Counters == null)
					{
						data.Counters = new List<CounterKV>();
					}
					_counters.Clear();
					foreach (CounterKV counter in _data.Counters)
					{
						if (counter != null && !string.IsNullOrEmpty(counter.Key))
						{
							_counters[counter.Key] = counter.Value;
						}
					}
					bool flag2 = text != CanonicalFile;
					if (flag2 || flag)
					{
						PersistCanonical(SaveJson.Serialize(_data), verify: true, flag2 ? "Migrate" : "Normalize");
					}
					if (text != CanonicalFile)
					{
						TryDelete(text);
					}
					ManualLogSource log2 = EmpressAchievementsPlugin.Log;
					if (log2 != null)
					{
						log2.LogInfo((object)("[ACH] Loaded save from: " + text));
					}
				}
				else
				{
					_data = new AchievementsSave();
					_counters.Clear();
					ManualLogSource log3 = EmpressAchievementsPlugin.Log;
					if (log3 != null)
					{
						log3.LogWarning((object)("[ACH] Load parse failed for " + text + ". Keeping file on disk unchanged; in-memory starts fresh."));
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log4 = EmpressAchievementsPlugin.Log;
				if (log4 != null)
				{
					log4.LogWarning((object)("[ACH] Load exception: " + ex));
				}
				_data = new AchievementsSave();
				_counters.Clear();
			}
		}

		public void Save()
		{
			try
			{
				AchievementsSave data = _data;
				if (data.Achievements == null)
				{
					data.Achievements = new List<AchievementState>();
				}
				_data.Counters = _counters.Select<KeyValuePair<string, long>, CounterKV>((KeyValuePair<string, long> kv) => new CounterKV
				{
					Key = kv.Key,
					Value = (int)((kv.Value > int.MaxValue) ? int.MaxValue : ((kv.Value < int.MinValue) ? int.MinValue : kv.Value))
				}).ToList();
				if (_data.Achievements.Count == 0 && _data.Counters.Count == 0 && OnDiskLooksPopulated())
				{
					ManualLogSource log = EmpressAchievementsPlugin.Log;
					if (log != null)
					{
						log.LogWarning((object)"[ACH] Save skipped to avoid clobber: memory is empty but disk has items.");
					}
					return;
				}
				string text = SaveJson.Serialize(_data);
				PersistCanonical(text, verify: true, "Save");
				long num = _data.Achievements.Count;
				long num2 = _data.Counters.Count;
				long num3 = SafeGetLength(CanonicalFile);
				if ((Object)(object)EmpressAchievementsPlugin.Instance != (Object)null && EmpressAchievementsPlugin.DebugLogJsonPreview.Value)
				{
					string text2 = ((text.Length > 300) ? (text.Substring(0, 300) + "...") : text);
					ManualLogSource log2 = EmpressAchievementsPlugin.Log;
					if (log2 != null)
					{
						log2.LogInfo((object)("[ACH] JSON preview: " + text2.Replace("\n", "\\n")));
					}
				}
				ManualLogSource log3 = EmpressAchievementsPlugin.Log;
				if (log3 != null)
				{
					log3.LogInfo((object)$"[ACH] Saved {num} achievements, {num2} counters -> {CanonicalFile} ({num3} bytes) [verify OK]");
				}
				EmpressAchievementsPlugin.DumpFileMap("AfterSave");
			}
			catch (Exception ex)
			{
				ManualLogSource log4 = EmpressAchievementsPlugin.Log;
				if (log4 != null)
				{
					log4.LogWarning((object)("[ACH] Save failed: " + ex));
				}
			}
		}

		private bool OnDiskLooksPopulated()
		{
			try
			{
				if (!File.Exists(CanonicalFile))
				{
					return false;
				}
				string json = File.ReadAllText(CanonicalFile, Encoding.UTF8);
				bool hasA;
				bool hasC;
				return LoadJsonFallback.JsonIndicatesItems(json, out hasA, out hasC) && (hasA || hasC);
			}
			catch
			{
				return false;
			}
		}

		private void EnsureCanonicalDir()
		{
			try
			{
				Directory.CreateDirectory(CanonicalFolder);
			}
			catch
			{
			}
		}

		private void PersistCanonical(string json, bool verify, string context)
		{
			EnsureCanonicalDir();
			string text = CanonicalFile + ".tmp";
			try
			{
				using FileStream fileStream = new FileStream(text, FileMode.Create, FileAccess.Write, FileShare.None, 4096, FileOptions.WriteThrough);
				using StreamWriter streamWriter = new StreamWriter(fileStream, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
				streamWriter.Write(json);
				streamWriter.Flush();
				fileStream.Flush(flushToDisk: true);
			}
			catch (Exception arg)
			{
				ManualLogSource log = EmpressAchievementsPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)$"[ACH] {context} tmp write failed: {arg}");
				}
				throw;
			}
			try
			{
				if (File.Exists(CanonicalFile))
				{
					try
					{
						File.Replace(text, CanonicalFile, CanonicalFile + ".bak");
					}
					catch
					{
						try
						{
							File.Delete(CanonicalFile);
						}
						catch
						{
						}
						File.Move(text, CanonicalFile);
					}
				}
				else
				{
					File.Move(text, CanonicalFile);
				}
			}
			catch (Exception arg2)
			{
				ManualLogSource log2 = EmpressAchievementsPlugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)$"[ACH] {context} replace failed: {arg2}");
				}
				throw;
			}
			if (!verify)
			{
				return;
			}
			try
			{
				string text2 = File.ReadAllText(CanonicalFile, Encoding.UTF8);
				if (!string.Equals(text2, json, StringComparison.Ordinal))
				{
					string text3 = ((text2.Length > 300) ? (text2.Substring(0, 300) + "...") : text2);
					ManualLogSource log3 = EmpressAchievementsPlugin.Log;
					if (log3 != null)
					{
						log3.LogWarning((object)$"[ACH] VERIFY STRING MISMATCH after {context}: lenWritten={json.Length}, lenRead={text2.Length}");
					}
					ManualLogSource log4 = EmpressAchievementsPlugin.Log;
					if (log4 != null)
					{
						log4.LogWarning((object)("[ACH] On-disk head: " + text3.Replace("\n", "\\n")));
					}
				}
			}
			catch (Exception arg3)
			{
				ManualLogSource log5 = EmpressAchievementsPlugin.Log;
				if (log5 != null)
				{
					log5.LogWarning((object)$"[ACH] Verify read failed after {context}: {arg3}");
				}
			}
		}

		private static DateTime SafeGetWriteTimeUtc(string path)
		{
			try
			{
				return File.GetLastWriteTimeUtc(path);
			}
			catch
			{
				return DateTime.MinValue;
			}
		}

		private static long SafeGetLength(string path)
		{
			try
			{
				return new FileInfo(path).Length;
			}
			catch
			{
				return 0L;
			}
		}

		private static void TryDelete(string path)
		{
			try
			{
				if (File.Exists(path))
				{
					File.Delete(path);
				}
			}
			catch
			{
			}
		}
	}
	public class AchievementDef
	{
		public string Id;

		public string Title;

		public string Description;

		public AchievementDef(string id, string title, string description)
		{
			Id = id;
			Title = title;
			Description = description;
		}
	}
	public static class AchievementBook
	{
		public static readonly Dictionary<string, AchievementDef> All = new Dictionary<string, AchievementDef>();

		public static AchievementDef Get(string id)
		{
			AchievementDef value;
			return All.TryGetValue(id, out value) ? value : null;
		}

		public static IEnumerable<AchievementDef> AllOrdered()
		{
			return All.Values.OrderBy((AchievementDef d) => d.Title);
		}

		public static void DefineDefaults()
		{
			All.Clear();
			Add("first_extract", "First Extraction", "Complete any extraction.");
			Add("extract_5", "Commuter", "Complete 5 extractions (lifetime).");
			Add("extract_20", "Frequent Flyer", "Complete 20 extractions (lifetime).");
			Add("extract_50", "Shuttle Regular", "Complete 50 extractions (lifetime).");
			Add("extract_100", "Season Pass Holder", "Complete 100 extractions (lifetime).");
			Add("extract_200", "Lives Here Now", "Complete 200 extractions (lifetime).");
			Add("run_money_10000", "Cash Flash", "Reach 10,000 run currency.");
			Add("run_money_25000", "Bankroller", "Reach 25,000 run currency.");
			Add("run_money_50000", "Whale", "Reach 50,000 run currency.");
			Add("run_money_100000", "Making It Rain", "Reach 100,000 run currency.");
			Add("run_haul_10000", "Hauler", "Reach 10,000 haul value in a run.");
			Add("run_haul_25000", "Mover", "Reach 25,000 haul value in a run.");
			Add("run_haul_50000", "Freight Lord", "Reach 50,000 haul value in a run.");
			Add("life_haul_50k", "Thrifty Tycoon", "Accumulate 50,000 haul (lifetime).");
			Add("life_haul_100k", "Millionaire-ish", "Accumulate 100,000 haul (lifetime).");
			Add("life_haul_250k", "Quarter Mil", "Accumulate 250,000 haul (lifetime).");
			Add("life_haul_500k", "Half Ticket", "Accumulate 500,000 haul (lifetime).");
			Add("life_haul_1m", "Seven Figures", "Accumulate 1,000,000 haul (lifetime).");
			Add("life_haul_2m", "Eight-ish", "Accumulate 2,000,000 haul (lifetime).");
			Add("life_haul_5m", "Big Bags", "Accumulate 5,000,000 haul (lifetime).");
			Add("life_haul_10m", "Dragon Hoard", "Accumulate 10,000,000 haul (lifetime).");
			Add("life_haul_20m", "Vault Dweller", "Accumulate 20,000,000 haul (lifetime).");
			Add("life_haul_50m", "Scrooge McDuck", "Accumulate 50,000,000 haul (lifetime).");
			Add("first_purchase", "Window Shopper No More", "Purchase your first item.");
			Add("big_spender_10", "Bulk Buyer", "Purchase 10 items (lifetime).");
			Add("big_spender_25", "Cart Commander", "Purchase 25 items (lifetime).");
			Add("big_spender_50", "Mall Rat", "Purchase 50 items (lifetime).");
			Add("big_spender_100", "Retail Therapy", "Purchase 100 items (lifetime).");
			Add("first_death", "Oops", "Die for the first time.");
			Add("death_5", "Oops, I Did It Again", "Die 5 times.");
			Add("death_10", "Try, Try Again", "Die 10 times.");
			Add("death_20", "Professional Victim", "Die 20 times.");
			Add("death_30", "Speedrun to the Afterlife", "Die 30 times.");
			Add("death_40", "Grave Connoisseur", "Die 40 times.");
			Add("death_50", "Certified Floor Tester", "Die 50 times.");
			Add("death_100", "Immortal (In Theory)", "Die 100 times.");
			Add("death_200", "Groundhog Day", "Die 200 times.");
			Add("death_500", "The Floor Is My Home", "Die 500 times.");
			Add("revived", "Back On Your Feet", "Get revived.");
			Add("revived_10", "Serial Resurrectee", "Be revived 10 times.");
			Add("revived_50", "Phoenix Program", "Be revived 50 times.");
			Add("nodeath_run", "Untouchable", "Complete an extraction without dying.");
			Add("first_discover", "Treasure Hunter", "Discover your first valuable.");
			Add("kills_10", "First Bloodbath", "Eliminate 10 enemies.");
			Add("kills_50", "Pest Control", "Eliminate 50 enemies.");
			Add("kills_100", "Exterminator", "Eliminate 100 enemies.");
			Add("kills_250", "Reaper Intern", "Eliminate 250 enemies.");
			Add("kills_500", "Reaper Associate", "Eliminate 500 enemies.");
			Add("kills_1000", "Full-Time Reaper", "Eliminate 1,000 enemies.");
			Add("kills_2000", "Warfare Dept.", "Eliminate 2,000 enemies.");
			Add("kills_5000", "Population Control", "Eliminate 5,000 enemies.");
			Add("kill_type_VeryLight", "Light Snack", "Eliminate a Very Light enemy.");
			Add("kill_type_Light", "Featherweight Fighter", "Eliminate a Light enemy.");
			Add("kill_type_Medium", "Middle Management", "Eliminate a Medium enemy.");
			Add("kill_type_Heavy", "Heavy Metal", "Eliminate a Heavy enemy.");
			Add("kill_type_VeryHeavy", "Heaviest Hand", "Eliminate a Very Heavy enemy.");
			Add("kill_type_VeryLight_25", "Snack Attack", "Eliminate 25 Very Light enemies.");
			Add("kill_type_Light_25", "Light Work", "Eliminate 25 Light enemies.");
			Add("kill_type_Medium_25", "Middle Manager", "Eliminate 25 Medium enemies.");
			Add("kill_type_Heavy_25", "Heavy Lifter", "Eliminate 25 Heavy enemies.");
			Add("kill_type_VeryHeavy_25", "Atlas", "Eliminate 25 Very Heavy enemies.");
		}

		private static void Add(string id, string title, string desc)
		{
			All[id] = new AchievementDef(id, title, desc);
		}
	}
	internal class ToastMessage
	{
		public string Title;

		public string Body;

		public ToastMessage(string t, string b)
		{
			Title = t;
			Body = b;
		}
	}
	public class ToastUi : MonoBehaviour
	{
		public float Duration = 3f;

		public float UiScale = 1f;

		public bool EnableSound = true;

		public string SoundFilePath;

		public float Volume = 0.7f;

		private Canvas _canvas;

		private RectTransform _root;

		private AudioSource _audio;

		private AudioClip _clip;

		private readonly Queue<ToastMessage> _queue = new Queue<ToastMessage>();

		private bool _busy;

		private bool _soundLoadRequested;

		private string _lastSoundFilePath;

		public void RefreshScale()
		{
			//IL_0016: 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)
			if (Object.op_Implicit((Object)(object)_root))
			{
				((Transform)_root).localScale = Vector3.one * UiScale;
			}
		}

		private void Ensure()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)_canvas))
			{
				EmpressAchievementsPlugin.Log.LogInfo((object)"[ACH] Creating Toast Canvas...");
				_canvas = new GameObject("Empress_AchievementToastCanvas").AddComponent<Canvas>();
				Object.DontDestroyOnLoad((Object)(object)_canvas);
				_canvas.renderMode = (RenderMode)0;
				_canvas.sortingOrder = 32760;
				CanvasScaler val = ((Component)_canvas).gameObject.AddComponent<CanvasScaler>();
				val.uiScaleMode = (ScaleMode)1;
				val.referenceResolution = new Vector2(1920f, 1080f);
				val.screenMatchMode = (ScreenMatchMode)0;
				val.matchWidthOrHeight = 0.5f;
				((Component)_canvas).gameObject.AddComponent<GraphicRaycaster>();
				_root = new GameObject("ToastRoot").AddComponent<RectTransform>();
				((Transform)_root).SetParent(((Component)_canvas).transform, false);
				_root.anchorMin = new Vector2(0.5f, 0f);
				_root.anchorMax = new Vector2(0.5f, 0f);
				_root.pivot = new Vector2(0.5f, 0f);
				_root.anchoredPosition = new Vector2(0f, 80f);
				((Transform)_root).localScale = Vector3.one * UiScale;
				_audio = ((Component)_canvas).gameObject.AddComponent<AudioSource>();
				_audio.playOnAwake = false;
				_audio.spatialBlend = 0f;
				_audio.loop = false;
				_audio.ignoreListenerPause = true;
				_audio.volume = 1f;
				EmpressAchievementsPlugin.Log.LogInfo((object)"[ACH] Toast Canvas ready");
			}
		}

		public IEnumerator LoadSoundCoroutine()
		{
			Ensure();
			_clip = null;
			_soundLoadRequested = true;
			_lastSoundFilePath = SoundFilePath;
			if (!EnableSound)
			{
				yield break;
			}
			if (string.IsNullOrEmpty(SoundFilePath) || !File.Exists(SoundFilePath))
			{
				EmpressAchievementsPlugin.Log.LogInfo((object)("[ACH] No sound file at: " + (SoundFilePath ?? "null")));
				_soundLoadRequested = false;
				yield break;
			}
			EmpressAchievementsPlugin.Log.LogInfo((object)("[ACH] Loading sound from: " + SoundFilePath));
			string uri = "file://" + SoundFilePath.Replace("\\", "/");
			UnityWebRequest req = UnityWebRequestMultimedia.GetAudioClip(uri, GetAudioType(SoundFilePath));
			yield return req.SendWebRequest();
			if (!req.isNetworkError && !req.isHttpError)
			{
				_clip = DownloadHandlerAudioClip.GetContent(req);
				if ((Object)(object)_clip != (Object)null && !_clip.preloadAudioData)
				{
					_clip.LoadAudioData();
				}
				ManualLogSource log = EmpressAchievementsPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)"[ACH] Sound ready");
				}
			}
			else
			{
				ManualLogSource log2 = EmpressAchievementsPlugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("[ACH] Audio load failed: " + req.error));
				}
				_soundLoadRequested = false;
			}
			req.Dispose();
		}

		public bool NeedsSoundLoad()
		{
			if (!EnableSound)
			{
				return false;
			}
			if ((Object)(object)_clip != (Object)null)
			{
				return false;
			}
			if (!string.Equals(_lastSoundFilePath, SoundFilePath, StringComparison.OrdinalIgnoreCase))
			{
				_soundLoadRequested = false;
			}
			return !_soundLoadRequested;
		}

		private static AudioType GetAudioType(string path)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			return (AudioType)(Path.GetExtension(path)?.ToLowerInvariant() switch
			{
				".wav" => 20, 
				".ogg" => 14, 
				".mp3" => 13, 
				_ => 20, 
			});
		}

		public void Pop(string title, string body)
		{
			EmpressAchievementsPlugin.Log.LogInfo((object)("[ACH] Toast: " + title));
			Ensure();
			_queue.Enqueue(new ToastMessage(title, body));
			if (!_busy)
			{
				if ((Object)(object)EmpressAchievementsPlugin.Runtime != (Object)null && Object.op_Implicit((Object)(object)EmpressAchievementsPlugin.Runtime))
				{
					EmpressAchievementsPlugin.Runtime.StartManagedCoroutine(Run());
				}
				else
				{
					((MonoBehaviour)this).StartCoroutine(Run());
				}
			}
		}

		private IEnumerator Run()
		{
			_busy = true;
			while (_queue.Count > 0)
			{
				ToastMessage msg = _queue.Dequeue();
				yield return ShowToast(msg.Title, msg.Body);
			}
			_busy = false;
		}

		private IEnumerator ShowToast(string title, string body)
		{
			GameObject go = new GameObject("Toast");
			RectTransform rt = go.AddComponent<RectTransform>();
			((Transform)rt).SetParent((Transform)(object)_root, false);
			rt.sizeDelta = new Vector2(520f, 100f);
			Image bg = go.AddComponent<Image>();
			((Graphic)bg).color = new Color(0.05f, 0.05f, 0.05f, 0.9f);
			((Graphic)bg).raycastTarget = false;
			Outline outline = go.AddComponent<Outline>();
			((Shadow)outline).effectDistance = new Vector2(2f, -2f);
			((Shadow)outline).effectColor = new Color(0.9f, 0.7f, 0.2f, 0.85f);
			GameObject titleGO = new GameObject("Title");
			RectTransform titleRT = titleGO.AddComponent<RectTransform>();
			((Transform)titleRT).SetParent((Transform)(object)rt, false);
			titleRT.anchorMin = new Vector2(0f, 0.5f);
			titleRT.anchorMax = new Vector2(1f, 1f);
			titleRT.offsetMin = new Vector2(15f, -5f);
			titleRT.offsetMax = new Vector2(-15f, -5f);
			TextMeshProUGUI titleTMP = titleGO.AddComponent<TextMeshProUGUI>();
			((TMP_Text)titleTMP).text = title;
			((TMP_Text)titleTMP).fontSize = 24f;
			((Graphic)titleTMP).color = new Color(1f, 0.93f, 0.6f);
			((TMP_Text)titleTMP).alignment = (TextAlignmentOptions)4097;
			((TMP_Text)titleTMP).enableWordWrapping = true;
			((TMP_Text)titleTMP).overflowMode = (TextOverflowModes)1;
			((TMP_Text)titleTMP).fontStyle = (FontStyles)1;
			((Graphic)titleTMP).raycastTarget = false;
			GameObject bodyGO = new GameObject("Body");
			RectTransform bodyRT = bodyGO.AddComponent<RectTransform>();
			((Transform)bodyRT).SetParent((Transform)(object)rt, false);
			bodyRT.anchorMin = new Vector2(0f, 0f);
			bodyRT.anchorMax = new Vector2(1f, 0.5f);
			bodyRT.offsetMin = new Vector2(15f, 5f);
			bodyRT.offsetMax = new Vector2(-15f, 5f);
			TextMeshProUGUI bodyTMP = bodyGO.AddComponent<TextMeshProUGUI>();
			((TMP_Text)bodyTMP).text = body;
			((TMP_Text)bodyTMP).fontSize = 16f;
			((Graphic)bodyTMP).color = new Color(0.9f, 0.9f, 0.9f);
			((TMP_Text)bodyTMP).alignment = (TextAlignmentOptions)4097;
			((TMP_Text)bodyTMP).enableWordWrapping = true;
			((TMP_Text)bodyTMP).overflowMode = (TextOverflowModes)1;
			((Graphic)bodyTMP).raycastTarget = false;
			float usableWidth = rt.sizeDelta.x - 30f;
			Vector2 titlePref = ((TMP_Text)titleTMP).GetPreferredValues(((TMP_Text)titleTMP).text, usableWidth, 0f);
			Vector2 bodyPref = ((TMP_Text)bodyTMP).GetPreferredValues(((TMP_Text)bodyTMP).text, usableWidth, 0f);
			float newHeight = Mathf.Max(90f, titlePref.y + bodyPref.y + 28f);
			rt.sizeDelta = new Vector2(rt.sizeDelta.x, newHeight);
			float t2 = 0f;
			Vector2 start = new Vector2(0f, -150f);
			Vector2 mid = new Vector2(0f, 0f);
			Vector2 end = new Vector2(0f, -150f);
			rt.anchoredPosition = start;
			CanvasGroup cg = go.AddComponent<CanvasGroup>();
			cg.alpha = 0f;
			if (EnableSound && (Object)(object)_clip != (Object)null && (Object)(object)_audio != (Object)null)
			{
				_audio.Stop();
				_audio.PlayOneShot(_clip, Mathf.Clamp01(Volume));
			}
			float inDur = 0.25f;
			while (t2 < inDur)
			{
				t2 += Time.unscaledDeltaTime;
				float p = t2 / inDur;
				float e = 1f - (1f - p) * (1f - p);
				cg.alpha = p;
				rt.anchoredPosition = Vector2.Lerp(start, mid, e);
				yield return null;
			}
			cg.alpha = 1f;
			rt.anchoredPosition = mid;
			yield return (object)new WaitForSecondsRealtime(Mathf.Max(1f, Duration));
			t2 = 0f;
			float outDur = 0.25f;
			while (t2 < outDur)
			{
				t2 += Time.unscaledDeltaTime;
				float p2 = t2 / outDur;
				float e2 = p2 * p2;
				cg.alpha = 1f - p2;
				rt.anchoredPosition = Vector2.Lerp(mid, end, e2);
				yield return null;
			}
			Object.Destroy((Object)(object)go);
		}
	}
	public class AchievementsUi : MonoBehaviour
	{
		private enum AchievementListMode
		{
			All,
			Unlocked,
			Locked
		}

		private sealed class FilterTab
		{
			public AchievementListMode Mode { get; }

			public Image Background { get; }

			public TextMeshProUGUI Label { get; }

			public FilterTab(AchievementListMode mode, Image background, TextMeshProUGUI label)
			{
				Mode = mode;
				Background = background;
				Label = label;
			}
		}

		public float UiScale = 1f;

		private Canvas _canvas;

		private RectTransform _root;

		private GameObject _panel;

		private RectTransform _listRoot;

		private ScrollRect _scroll;

		private RectTransform _scrollRT;

		private RectTransform _scrollbarRT;

		private Scrollbar _scrollbar;

		private TextMeshProUGUI _statsLabel;

		private RectTransform _statsRT;

		private RectTransform _headerRT;

		private RectTransform _tabsRT;

		private bool _open;

		private float _nextStatsTick;

		private readonly List<FilterTab> _tabs = new List<FilterTab>();

		private AchievementListMode _listMode = AchievementListMode.All;

		private bool _cursorCaptured;

		private bool _previousCursorVisible;

		private CursorLockMode _previousCursorLockState;

		private Texture2D _empressCursorTexture;

		private const float HeaderHeight = 66f;

		private const float TabsHeight = 44f;

		public void RefreshScale()
		{
			//IL_0016: 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)
			if (Object.op_Implicit((Object)(object)_root))
			{
				((Transform)_root).localScale = Vector3.one * UiScale;
			}
			if ((Object)(object)_panel != (Object)null && _panel.activeSelf)
			{
				RefreshList();
				RecomputeTopLayout();
				Canvas.ForceUpdateCanvases();
			}
		}

		private void Ensure()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)_canvas))
			{
				EmpressAchievementsPlugin.Log.LogInfo((object)"[ACH] Building Achievements Panel...]");
				_canvas = new GameObject("Empress_AchievementPanelCanvas").AddComponent<Canvas>();
				Object.DontDestroyOnLoad((Object)(object)_canvas);
				_canvas.renderMode = (RenderMode)0;
				_canvas.sortingOrder = 32700;
				CanvasScaler val = ((Component)_canvas).gameObject.AddComponent<CanvasScaler>();
				val.uiScaleMode = (ScaleMode)1;
				val.referenceResolution = new Vector2(1920f, 1080f);
				val.screenMatchMode = (ScreenMatchMode)0;
				val.matchWidthOrHeight = 0.5f;
				((Component)_canvas).gameObject.AddComponent<GraphicRaycaster>();
				_root = new GameObject("PanelRoot").AddComponent<RectTransform>();
				((Transform)_root).SetParent(((Component)_canvas).transform, false);
				_root.anchorMin = new Vector2(0.5f, 0.5f);
				_root.anchorMax = new Vector2(0.5f, 0.5f);
				_root.pivot = new Vector2(0.5f, 0.5f);
				_root.sizeDelta = new Vector2(1000f, 700f);
				((Transform)_root).localScale = Vector3.one * UiScale;
				_panel = BuildPanel(_root);
				_panel.SetActive(false);
			}
		}

		public void Toggle()
		{
			Ensure();
			_open = !_open;
			_panel.SetActive(_open);
			if (_open)
			{
				ApplyUiCursor();
				RefreshList(resetScroll: true);
				UpdateStatsLabel();
				RecomputeTopLayout();
				_nextStatsTick = Time.unscaledTime + 0.5f;
				Canvas.ForceUpdateCanvases();
			}
			else
			{
				RestoreCursorState();
			}
		}

		public void Prime()
		{
			Ensure();
		}

		public void RefreshAllIfOpen()
		{
			if ((Object)(object)_panel != (Object)null && _panel.activeSelf)
			{
				UpdateStatsLabel();
				RecomputeTopLayout();
				RefreshList();
			}
		}

		public void RefreshStatsIfOpen()
		{
			if ((Object)(object)_panel != (Object)null && _panel.activeSelf)
			{
				UpdateStatsLabel();
				RecomputeTopLayout();
			}
		}

		public void RefreshList(bool resetScroll = false)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			Ensure();
			if ((Object)(object)_panel == (Object)null)
			{
				return;
			}
			foreach (Transform item in (Transform)_listRoot)
			{
				Transform val = item;
				Object.Destroy((Object)(object)((Component)val).gameObject);
			}
			foreach (AchievementDef item2 in AchievementBook.AllOrdered())
			{
				bool unlocked = EmpressAchievementsPlugin.Store.IsUnlocked(item2.Id);
				if (ShouldShowAchievement(unlocked))
				{
					BuildEntry(_listRoot, item2, unlocked);
				}
			}
			LayoutRebuilder.ForceRebuildLayoutImmediate(_listRoot);
			RefreshTabVisuals();
			if (resetScroll && (Object)(object)_scroll != (Object)null)
			{
				Canvas.ForceUpdateCanvases();
				_scroll.verticalNormalizedPosition = 1f;
			}
		}

		private void Update()
		{
			if ((Object)(object)_panel == (Object)null || !_panel.activeSelf)
			{
				if (_cursorCaptured)
				{
					RestoreCursorState();
				}
				return;
			}
			ApplyUiCursor();
			ApplyUiControlLock();
			if (Time.unscaledTime >= _nextStatsTick)
			{
				UpdateStatsLabel();
				RecomputeTopLayout();
				_nextStatsTick = Time.unscaledTime + 0.5f;
			}
		}

		private void UpdateStatsLabel()
		{
			if (!((Object)(object)_statsLabel == (Object)null))
			{
				int count = AchievementBook.All.Count;
				int num = AchievementBook.All.Values.Count((AchievementDef def) => EmpressAchievementsPlugin.Store.IsUnlocked(def.Id));
				int num2 = AchievementBook.All.Values.Count((AchievementDef def) => ShouldShowAchievement(EmpressAchievementsPlugin.Store.IsUnlocked(def.Id)));
				int stat = EmpressAchievementsPlugin.GetStat("extractions");
				int stat2 = EmpressAchievementsPlugin.GetStat("purchases");
				int stat3 = EmpressAchievementsPlugin.GetStat("deaths");
				int stat4 = EmpressAchievementsPlugin.GetStat("revives");
				long counter = EmpressAchievementsPlugin.Store.GetCounter("life_haul");
				long counter2 = EmpressAchievementsPlugin.Store.GetCounter("kills_total");
				string text = "$" + EmpressAchievementsPlugin.FormatK(counter);
				((TMP_Text)_statsLabel).text = $"Showing {num2}  |  Unlocked {num}/{count}\n" + $"Extractions {stat}  |  Purchases {stat2}  |  Deaths {stat3}  |  Revives {stat4}  |  Lifetime Haul {text}  |  Kills {counter2}";
			}
		}

		private GameObject BuildPanel(RectTransform parent)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_001e: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Expected O, but got Unknown
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0322: Unknown result type (might be due to invalid IL or missing references)
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c0: Expected O, but got Unknown
			//IL_03eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0406: Unknown result type (might be due to invalid IL or missing references)
			//IL_0421: Unknown result type (might be due to invalid IL or missing references)
			//IL_043c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0457: Unknown result type (might be due to invalid IL or missing references)
			//IL_0481: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e1: Expected O, but got Unknown
			//IL_0554: Unknown result type (might be due to invalid IL or missing references)
			//IL_055b: Expected O, but got Unknown
			//IL_0586: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_05bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0601: Unknown result type (might be due to invalid IL or missing references)
			//IL_0617: Unknown result type (might be due to invalid IL or missing references)
			//IL_068a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0691: Expected O, but got Unknown
			//IL_06c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_06dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0709: Unknown result type (might be due to invalid IL or missing references)
			//IL_071a: Unknown result type (might be due to invalid IL or missing references)
			//IL_072b: Unknown result type (might be due to invalid IL or missing references)
			//IL_077a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0784: Expected O, but got Unknown
			//IL_07c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_07c7: Expected O, but got Unknown
			//IL_07f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_080d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0828: Unknown result type (might be due to invalid IL or missing references)
			//IL_0843: Unknown result type (might be due to invalid IL or missing references)
			//IL_086d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0897: Unknown result type (might be due to invalid IL or missing references)
			//IL_089e: Expected O, but got Unknown
			//IL_08b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_08c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_08dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_08f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0903: Unknown result type (might be due to invalid IL or missing references)
			//IL_090a: Expected O, but got Unknown
			//IL_092a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0941: Unknown result type (might be due to invalid IL or missing references)
			//IL_094e: Unknown result type (might be due to invalid IL or missing references)
			//IL_095b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0985: Unknown result type (might be due to invalid IL or missing references)
			//IL_09c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_09ca: Expected O, but got Unknown
			//IL_09e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a00: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a17: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a2e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a45: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a6f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a91: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a9b: Expected O, but got Unknown
			//IL_0aa1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0aa8: Expected O, but got Unknown
			//IL_0ac3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ad0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0add: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b1a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Panel");
			RectTransform val2 = val.AddComponent<RectTransform>();
			((Transform)val2).SetParent((Transform)(object)parent, false);
			val2.sizeDelta = parent.sizeDelta;
			Image val3 = val.AddComponent<Image>();
			((Graphic)val3).color = new Color(0.02f, 0.02f, 0.02f, 0.9f);
			((Graphic)val3).raycastTarget = true;
			GameObject val4 = new GameObject("Header");
			_headerRT = val4.AddComponent<RectTransform>();
			((Transform)_headerRT).SetParent((Transform)(object)val2, false);
			_headerRT.anchorMin = new Vector2(0f, 1f);
			_headerRT.anchorMax = new Vector2(1f, 1f);
			_headerRT.pivot = new Vector2(0.5f, 1f);
			_headerRT.anchoredPosition = new Vector2(0f, -10f);
			_headerRT.sizeDelta = new Vector2(-20f, 66f);
			Image val5 = val4.AddComponent<Image>();
			((Graphic)val5).color = new Color(0.24f, 0.11f, 0.03f, 0.98f);
			TextMeshProUGUI val6 = new GameObject("Title").AddComponent<TextMeshProUGUI>();
			RectTransform rectTransform = ((TMP_Text)val6).rectTransform;
			((Transform)rectTransform).SetParent((Transform)(object)_headerRT, false);
			rectTransform.anchorMin = Vector2.zero;
			rectTransform.anchorMax = Vector2.one;
			rectTransform.offsetMin = new Vector2(20f, 0f);
			rectTransform.offsetMax = new Vector2(-70f, 0f);
			((TMP_Text)val6).text = "EMPRESS Achievements";
			((TMP_Text)val6).fontSize = 36f;
			((Graphic)val6).color = new Color(1f, 0.92f, 0.6f);
			((TMP_Text)val6).alignment = (TextAlignmentOptions)4097;
			((TMP_Text)val6).fontStyle = (FontStyles)1;
			((Graphic)val6).raycastTarget = false;
			GameObject val7 = new GameObject("Stats");
			_statsRT = val7.AddComponent<RectTransform>();
			((Transform)_statsRT).SetParent((Transform)(object)val2, false);
			_statsRT.anchorMin = new Vector2(0f, 1f);
			_statsRT.anchorMax = new Vector2(1f, 1f);
			_statsRT.pivot = new Vector2(0.5f, 1f);
			_statsRT.anchoredPosition = new Vector2(0f, -82f);
			_statsRT.sizeDelta = new Vector2(-20f, 92f);
			Image val8 = val7.AddComponent<Image>();
			((Graphic)val8).color = new Color(0.08f, 0.08f, 0.08f, 0.92f);
			_statsLabel = new GameObject("StatsText").AddComponent<TextMeshProUGUI>();
			RectTransform rectTransform2 = ((TMP_Text)_statsLabel).rectTransform;
			((Transform)rectTransform2).SetParent((Transform)(object)_statsRT, false);
			rectTransform2.anchorMin = Vector2.zero;
			rectTransform2.anchorMax = Vector2.one;
			rectTransform2.offsetMin = new Vector2(16f, 12f);
			rectTransform2.offsetMax = new Vector2(-16f, -12f);
			((TMP_Text)_statsLabel).fontSize = 18f;
			((TMP_Text)_statsLabel).alignment = (TextAlignmentOptions)257;
			((TMP_Text)_statsLabel).enableWordWrapping = true;
			((TMP_Text)_statsLabel).overflowMode = (TextOverflowModes)0;
			((Graphic)_statsLabel).color = new Color(0.85f, 0.85f, 0.85f);
			((Graphic)_statsLabel).raycastTarget = false;
			UpdateStatsLabel();
			GameObject val9 = new GameObject("Tabs");
			_tabsRT = val9.AddComponent<RectTransform>();
			((Transform)_tabsRT).SetParent((Transform)(object)val2, false);
			_tabsRT.anchorMin = new Vector2(0f, 1f);
			_tabsRT.anchorMax = new Vector2(1f, 1f);
			_tabsRT.pivot = new Vector2(0.5f, 1f);
			_tabsRT.anchoredPosition = new Vector2(0f, -170f);
			_tabsRT.sizeDelta = new Vector2(-20f, 44f);
			Image val10 = val9.AddComponent<Image>();
			((Graphic)val10).color = new Color(0.06f, 0.06f, 0.06f, 0.92f);
			HorizontalLayoutGroup val11 = val9.AddComponent<HorizontalLayoutGroup>();
			((LayoutGroup)val11).childAlignment = (TextAnchor)3;
			((HorizontalOrVerticalLayoutGroup)val11).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)val11).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)val11).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)val11).childForceExpandHeight = true;
			((HorizontalOrVerticalLayoutGroup)val11).spacing = 10f;
			((LayoutGroup)val11).padding = new RectOffset(10, 10, 6, 6);
			_tabs.Clear();
			_tabs.Add(BuildTabButton(_tabsRT, "ALL", AchievementListMode.All));
			_tabs.Add(BuildTabButton(_tabsRT, "UNLOCKED", AchievementListMode.Unlocked));
			_tabs.Add(BuildTabButton(_tabsRT, "LOCKED", AchievementListMode.Locked));
			RefreshTabVisuals();
			GameObject val12 = new GameObject("ScrollViewport");
			_scrollRT = val12.AddComponent<RectTransform>();
			((Transform)_scrollRT).SetParent((Transform)(object)val2, false);
			_scrollRT.anchorMin = new Vector2(0f, 0f);
			_scrollRT.anchorMax = new Vector2(1f, 1f);
			_scrollRT.offsetMin = new Vector2(20f, 20f);
			_scrollRT.offsetMax = new Vector2(-52f, -220f);
			Image val13 = val12.AddComponent<Image>();
			((Graphic)val13).color = new Color(0.08f, 0.08f, 0.08f, 0.96f);
			RectMask2D val14 = val12.AddComponent<RectMask2D>();
			val14.padding = Vector4.zero;
			_scroll = val12.AddComponent<ScrollRect>();
			_scroll.horizontal = false;
			_scroll.vertical = true;
			_scroll.movementType = (MovementType)2;
			_scroll.scrollSensitivity = 32f;
			_scroll.verticalScrollbarSpacing = 10f;
			_scroll.verticalScrollbarVisibility = (ScrollbarVisibility)0;
			GameObject val15 = new GameObject("Content");
			_listRoot = val15.AddComponent<RectTransform>();
			((Transform)_listRoot).SetParent(val12.transform, false);
			_listRoot.anchorMin = new Vector2(0f, 1f);
			_listRoot.anchorMax = new Vector2(1f, 1f);
			_listRoot.pivot = new Vector2(0.5f, 1f);
			_listRoot.offsetMin = Vector2.zero;
			_listRoot.offsetMax = Vector2.zero;
			_listRoot.anchoredPosition = Vector2.zero;
			VerticalLayoutGroup val16 = val15.AddComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)val16).childForceExpandHeight = false;
			((HorizontalOrVerticalLayoutGroup)val16).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)val16).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)val16).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)val16).spacing = 8f;
			((LayoutGroup)val16).padding = new RectOffset(12, 12, 12, 12);
			ContentSizeFitter val17 = val15.AddComponent<ContentSizeFitter>();
			val17.verticalFit = (FitMode)2;
			_scroll.content = _listRoot;
			_scroll.viewport = _scrollRT;
			GameObject val18 = new GameObject("Scrollbar");
			_scrollbarRT = val18.AddComponent<RectTransform>();
			((Transform)_scrollbarRT).SetParent((Transform)(object)val2, false);
			_scrollbarRT.anchorMin = new Vector2(1f, 0f);
			_scrollbarRT.anchorMax = new Vector2(1f, 1f);
			_scrollbarRT.offsetMin = new Vector2(-36f, 20f);
			_scrollbarRT.offsetMax = new Vector2(-18f, -220f);
			Image val19 = val18.AddComponent<Image>();
			((Graphic)val19).color = new Color(0.23f, 0.12f, 0.05f, 0.95f);
			_scrollbar = val18.AddComponent<Scrollbar>();
			_scrollbar.direction = (Direction)2;
			GameObject val20 = new GameObject("SlidingArea");
			RectTransform val21 = val20.AddComponent<RectTransform>();
			((Transform)val21).SetParent((Transform)(object)_scrollbarRT, false);
			val21.anchorMin = Vector2.zero;
			val21.anchorMax = Vector2.one;
			val21.offsetMin = new Vector2(3f, 3f);
			val21.offsetMax = new Vector2(-3f, -3f);
			GameObject val22 = new GameObject("Handle");
			RectTransform val23 = val22.AddComponent<RectTransform>();
			((Transform)val23).SetParent((Transform)(object)val21, false);
			val23.anchorMin = new Vector2(0f, 0f);
			val23.anchorMax = new Vector2(1f, 1f);
			val23.offsetMin = Vector2.zero;
			val23.offsetMax = Vector2.zero;
			Image val24 = val22.AddComponent<Image>();
			((Graphic)val24).color = new Color(1f, 0.62f, 0.25f, 0.98f);
			((Selectable)_scrollbar).targetGraphic = (Graphic)(object)val24;
			_scrollbar.handleRect = val23;
			_scroll.verticalScrollbar = _scrollbar;
			GameObject val25 = new GameObject("CloseButton");
			RectTransform val26 = val25.AddComponent<RectTransform>();
			((Transform)val26).SetParent((Transform)(object)val2, false);
			val26.anchorMin = new Vector2(1f, 1f);
			val26.anchorMax = new Vector2(1f, 1f);
			val26.pivot = new Vector2(1f, 1f);
			val26.anchoredPosition = new Vector2(-18f, -18f);
			val26.sizeDelta = new Vector2(42f, 42f);
			Image val27 = val25.AddComponent<Image>();
			((Graphic)val27).color = new Color(0.75f, 0.18f, 0.14f, 0.95f);
			Button val28 = val25.AddComponent<Button>();
			((UnityEvent)val28.onClick).AddListener((UnityAction)delegate
			{
				Toggle();
			});
			GameObject val29 = new GameObject("X");
			RectTransform val30 = val29.AddComponent<RectTransform>();
			((Transform)val30).SetParent(val25.transform, false);
			val30.sizeDelta = Vector2.zero;
			val30.anchorMin = Vector2.zero;
			val30.anchorMax = Vector2.one;
			TextMeshProUGUI val31 = val29.AddComponent<TextMeshProUGUI>();
			((TMP_Text)val31).text = "×";
			((TMP_Text)val31).fontSize = 22f;
			((TMP_Text)val31).alignment = (TextAlignmentOptions)4098;
			((Graphic)val31).color = Color.white;
			((TMP_Text)val31).fontStyle = (FontStyles)1;
			((Graphic)val31).raycastTarget = false;
			return val;
		}

		private float GetContentWidth()
		{
			//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)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			float num;
			Rect rect;
			if (!((Object)(object)_scrollRT != (Object)null))
			{
				if (!((Object)(object)_root != (Object)null))
				{
					num = 920f;
				}
				else
				{
					rect = _root.rect;
					num = ((Rect)(ref rect)).width - 80f;
				}
			}
			else
			{
				rect = _scrollRT.rect;
				num = ((Rect)(ref rect)).width;
			}
			float num2 = num;
			return Mathf.Max(100f, num2 - 30f);
		}

		private void RecomputeTopLayout()
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_statsLabel == (Object)null) && !((Object)(object)_statsRT == (Object)null) && !((Object)(object)_headerRT == (Object)null) && !((Object)(object)_scrollRT == (Object)null) && !((Object)(object)_tabsRT == (Object)null) && !((Object)(object)_scrollbarRT == (Object)null))
			{
				float num;
				if (!((Object)(object)_root != (Object)null))
				{
					num = 1000f;
				}
				else
				{
					Rect rect = _root.rect;
					num = ((Rect)(ref rect)).width;
				}
				float num2 = Mathf.Max(240f, num - 100f);
				Vector2 preferredValues = ((TMP_Text)_statsLabel).GetPreferredValues(((TMP_Text)_statsLabel).text, num2, 0f);
				float num3 = Mathf.Clamp(preferredValues.y + 24f, 72f, 150f);
				_statsRT.sizeDelta = new Vector2(-20f, num3);
				_statsRT.anchoredPosition = new Vector2(0f, -82f);
				_tabsRT.anchoredPosition = new Vector2(0f, 0f - (66f + num3 + 22f));
				float num4 = 66f + num3 + 44f + 30f;
				_scrollRT.offsetMax = new Vector2(-52f, 0f - num4);
				_scrollbarRT.offsetMax = new Vector2(-18f, 0f - num4);
			}
		}

		private void BuildEntry(RectTransform parent, AchievementDef def, bool unlocked)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			//IL_005e: 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_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Expected O, but got Unknown
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing