Decompiled source of ChallengingUnlocks v1.0.7

ChallengingUnlocks.dll

Decompiled 4 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using EnemiesReturns.ModdedEntityStates.Judgement.Mission;
using EntityStates;
using EntityStates.Captain.Weapon;
using EntityStates.TimedChest;
using EntityStates.VoidSurvivor.CorruptMode;
using HG.Reflection;
using HarmonyLib;
using RoR2;
using RoR2.Achievements;
using RoR2.ContentManagement;
using RoR2.Projectile;
using RoR2.Skills;
using RoR2.Stats;
using RoR2.UI;
using UnityEngine;
using UnityEngine.Networking;

[assembly: OptIn]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace ChallengingUnlocks;

[BepInPlugin("binma.challengingunlocks", "Challenging Unlocks", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
	public const string Guid = "binma.challengingunlocks";

	internal static ManualLogSource Log;

	internal static ConfigEntry<bool> AnointedEnabled;

	internal static readonly Dictionary<string, UnlockableDef> Unlockables = new Dictionary<string, UnlockableDef>();

	internal static readonly Dictionary<string, string> SkinToAchievement = new Dictionary<string, string>();

	internal static readonly Dictionary<string, string> Tokens = new Dictionary<string, string>();

	internal static readonly Dictionary<string, string> JudgementBodies = new Dictionary<string, string>();

	internal static readonly Dictionary<string, string> VoidRunBodies = new Dictionary<string, string>();

	internal static readonly Dictionary<string, string> NoirBodies = new Dictionary<string, string>();

	internal static event Action<CharacterMaster> OnSeedRevive;

	internal static event Action OnVoidRunComplete;

	internal static void RaiseSeedRevive(CharacterMaster m)
	{
		Plugin.OnSeedRevive?.Invoke(m);
	}

	internal static void RaiseVoidRunComplete()
	{
		Plugin.OnVoidRunComplete?.Invoke();
	}

	internal static void Define(string id, string name, string desc, params string[] skinTokens)
	{
		UnlockableDef val = ScriptableObject.CreateInstance<UnlockableDef>();
		val.cachedName = "Skins.Binma." + id;
		val.nameToken = ((skinTokens.Length <= 0) ? "" : skinTokens[0]);
		Unlockables[id] = val;
		foreach (string key in skinTokens)
		{
			SkinToAchievement[key] = id;
		}
		string text = id.ToUpperInvariant();
		Tokens["ACHIEVEMENT_" + text + "_NAME"] = name;
		Tokens["ACHIEVEMENT_" + text + "_DESCRIPTION"] = desc;
	}

	private void Awake()
	{
		//IL_05bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_05c5: Expected O, but got Unknown
		//IL_0605: Unknown result type (might be due to invalid IL or missing references)
		//IL_060b: Expected O, but got Unknown
		//IL_065f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0674: Unknown result type (might be due to invalid IL or missing references)
		//IL_0681: Expected O, but got Unknown
		//IL_0681: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		AnointedEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("EnemiesReturns", "Enable Anointed Skins", false, "EnemiesReturns' generated Anointed skins. Off by default. This mod controls EnemiesReturns' own Anointed setting, so change it here.");
		ApplyAnointedSetting();
		Define("BinmaMechaFiendDecompile", "「V??oid Fiend』: Leaked Memory", "As 「V??oid Fiend』, accept the offering of the Collective.", "KRONONCONPSIRATOR_SKIN_MECHAFIENDSKINDEF_NAME");
		Define("BinmaZenithFalseSon", "False Son: Zenith", "As False Son, survive The Judgement.", "CRAZYHAMSTER_SKIN_ZENITH_NAME");
		JudgementBodies["BinmaZenithFalseSon"] = "FalseSonBody";
		Define("BinmaBiomassFalseSon", "False Son: Second Bloom", "As False Son, return from death with a Seed of Life.", "ORBITAL_SKIN_FALSESON_NAME");
		Define("BinmaShackledAcrid", "Acrid: Shackled", "As Acrid, clear the Void Fields, pass through the Void Locus, and escape the Planetarium in a single run.", "ORBITAL_SKIN_SHACKLED_NAME");
		VoidRunBodies["BinmaShackledAcrid"] = "CrocoBody";
		Define("BinmaLunarVoidRex", "REX: Lunar Void", "As REX, clear the Void Fields, pass through the Void Locus, and escape the Planetarium in a single run.", "HILLIURN_SKIN_LUNARVOID_REX_SKIN_NAME");
		VoidRunBodies["BinmaLunarVoidRex"] = "TreebotBody";
		DefineNoir("BinmaNoirBandit", "Bandit", "Bandit2Body", "Hidden in Plain Sight", "open 3 Cloaked Chests in a single run.", "BIGBADPIGEON_SKIN_NOIRBANDIT_NAME");
		DefineNoir("BinmaNoirCommando", "Commando", "CommandoBody", "The Scoop", "open the Timed Security Chest.", "BIGBADPIGEON_SKIN_NOIRCOMMANDO_NAME");
		DefineNoir("BinmaNoirEngi", "Engineer", "EngiBody", "Surveillance", "use a Radar Scanner on 3 different stages in a single run.", "BIGBADPIGEON_SKIN_NOIRENGI_NAME");
		DefineNoir("BinmaNoirRex", "REX", "TreebotBody", "Stakeout", "ping 30 enemies in a single run.", "BIGBADPIGEON_SKIN_NOIRREX_NAME");
		DefineNoir("BinmaNoirHuntress", "Huntress", "HuntressBody", "On the Trail", "activate 3 Newt Altars in a single run.", "BIGBADPIGEON_SKIN_NOIRHUNTRESS_NAME");
		DefineNoir("BinmaNoirCaptain", "Captain", "CaptainBody", "The Family", "have 5 allies alive at once.", "BIGBADPIGEON_SKIN_NOIRCAPTAIN_NAME");
		DefineNoir("BinmaNoirLoader", "Loader", "LoaderBody", "Protection Detail", "finish a teleporter event without an ally dying.", "BIGBADPIGEON_SKIN_NOIRLOADER_NAME");
		DefineNoir("BinmaNoirMage", "Artificer", "MageBody", "Infiltration", "visit 2 hidden realms in a single run.", "BIGBADPIGEON_SKIN_NOIRMAGE_NAME");
		DefineNoir("BinmaNoirVoidfiend", "「V??oid Fiend』", "VoidSurvivorBody", "Unmasked", "stay corrupted for 60 seconds straight.", "BIGBADPIGEON_SKIN_NOIRVOIDFIEND_NAME");
		DefineNoir("BinmaNoirMerc", "Mercenary", "MercBody", "No Witnesses", "kill 20 enemies within 5 seconds.", "BIGBADPIGEON_SKIN_NOIRMERC_NAME");
		DefineNoir("BinmaNoirDrifter", "Drifter", "DrifterBody", "Sticky Fingers", "scrap 10 items in a single run.", "BIGBADPIGEON_SKIN_NOIRDRIFTER_NAME");
		DefineNoir("BinmaNoirDronetech", "Operator", "DroneTechBody", "Stolen Clearance", "buy or repair 5 drones in a single run.", "BIGBADPIGEON_SKIN_NOIRDRONETECH_NAME");
		DefineNoir("BinmaNoirToolbot", "MUL-T", "ToolbotBody", "Paper Trail", "open 3 Rusted Lockboxes in a single run.", "BIGBADPIGEON_SKIN_NOIRTOOLBOT_NAME");
		DefineNoir("BinmaNoirSeeker", "Seeker", "SeekerBody", "Second Sight", "use a Lunar Seer in the Bazaar Between Time.", "BIGBADPIGEON_SKIN_NOIRSEEKER_NAME");
		DefineNoir("BinmaNoirRailgunner", "Railgunner", "RailgunnerBody", "Long Lens", "kill a boss from over 100m away.", "BIGBADPIGEON_SKIN_NOIRRAILGUNNER_NAME");
		DefineNoir("BinmaNoirFalseson", "False Son", "FalseSonBody", "Examine the Evidence", "inspect 25 different items.", "BIGBADPIGEON_SKIN_NOIRFALSESON_NAME");
		DefineNoir("BinmaNoirAcrid", "Acrid", "CrocoBody", "Sniffing Around", "discover 5 environment logs.", "BIGBADPIGEON_SKIN_NOIRACRID_NAME");
		DefineNoir("BinmaNoirChef", "CHEF", "ChefBody", "Secret Recipe", "cook 3 meals in a single run.", "BIGBADPIGEON_SKIN_NOIRCHEF_NAME");
		Define("BinmaFenrisCaptainAtlas", "Captain: Fire for Effect", "As Captain, kill Mithrix with an orbital strike.");
		Define("BinmaFenrisRailPyro", "Railgunner: Trial by Fire", "As Railgunner, kill a boss that is burning.");
		Define("BinmaFenrisRailKinetic", "Railgunner: Kinetic Impact", "As Railgunner, kill a boss while airborne.");
		Define("BinmaSummerRailgunner", "Railgunner: Beach Day", "As Railgunner, open a Legendary Chest.", "BIGBADPIGEON_SKIN_SUMMERRAILGUNNER_NAME");
		Define("BinmaSummerVoidFiend", "「V??oid Fiend』: Beach Day", "As 「V??oid Fiend』, open a Legendary Chest.", "BIGBADPIGEON_SKIN_SUMMERVOIDFIEND_NAME");
		Define("BinmaSolusRailgunnerPurge", "Railgunner: Purge", "As Railgunner, reject the offering of the Collective.", "KRONONCONSPIRATOR_SKIN_SOLUSGUNNER_NAME");
		Define("BinmaSteelConvictionCaptain", "Captain: Steel Conviction", "As Captain, fight a Solus Control Unit or Alloy Worship Unit, an Alloy Hunter and a Solus Amalgamator in a single run.", "SHEPD_SKIN_TANIKSCAPTIAN_NAME");
		DefineJudgement("BinmaJudgementCommando", "Commando", "CommandoBody", "ORBITAL_SKIN_MKII_NAME");
		DefineJudgement("BinmaJudgementHuntress", "Huntress", "HuntressBody", "ORBITAL_SKIN_URBAN_NAME");
		DefineJudgement("BinmaJudgementAcrid", "Acrid", "CrocoBody", "ORBITAL_SKIN_CHIMAERA_NAME");
		DefineJudgement("BinmaJudgementLoader", "Loader", "LoaderBody", "ORBITAL_SKIN_REFURBISHED_NAME");
		DefineJudgement("BinmaJudgementEngi", "Engineer", "EngiBody", "ORBITAL_SKIN_CHRONTECH_NAME");
		DefineJudgement("BinmaJudgementMerc", "Mercenary", "MercBody", "ORBITAL_SKIN_HONOR_NAME", "ORBITAL_SKIN_MALICE_NAME");
		DefineJudgement("BinmaJudgementBandit", "Bandit", "Bandit2Body", "ORBITAL_SKIN_INFAMY_NAME");
		DefineJudgement("BinmaJudgementArtificer", "Artificer", "MageBody", "ORBITAL_SKIN_AMBER_NAME");
		DefineJudgement("BinmaJudgementDrifter", "Drifter", "DrifterBody", "ORBITAL_SKIN_VAGABOND_NAME");
		VoidRunTracker.Init();
		Noir.Init();
		FenrisLocks.Init();
		Summer.Init();
		ContentManager.collectContentPackProviders += (CollectContentPackProvidersDelegate)delegate(AddContentPackProviderDelegate add)
		{
			add.Invoke((IContentPackProvider)(object)new ContentProvider());
		};
		RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(AttachToSkins));
		Harmony val = new Harmony("binma.challengingunlocks");
		val.PatchAll(typeof(Plugin).Assembly);
		Type type = AccessTools.Inner(typeof(EquipmentSlot), "HealAndReviveLock");
		if (type != null)
		{
			val.Patch((MethodBase)AccessTools.Method(type, "FixedUpdate", (Type[])null, (Type[])null), new HarmonyMethod(typeof(SeedPatches), "LockPrefix", (Type[])null), new HarmonyMethod(typeof(SeedPatches), "LockPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		else
		{
			Log.LogWarning((object)"Couldn't find HealAndReviveLock; ally Seed of Life revives won't count.");
		}
	}

	private static void DefineNoir(string id, string survivor, string body, string title, string desc, string skin)
	{
		Define(id, survivor + ": " + title, "As " + survivor + ", " + desc, skin);
		NoirBodies[id] = body;
	}

	private static void ApplyAnointedSetting()
	{
		try
		{
			if (!Chainloader.PluginInfos.TryGetValue("com.Viliger.EnemiesReturns", out var value) || (Object)(object)value.Instance == (Object)null)
			{
				return;
			}
			foreach (ConfigDefinition key in value.Instance.Config.Keys)
			{
				if (!(key.Key != "Enable Anointed Skins") && value.Instance.Config[key] is ConfigEntry<bool> val && val.Value != AnointedEnabled.Value)
				{
					val.Value = AnointedEnabled.Value;
					Log.LogInfo((object)("EnemiesReturns Anointed skins " + ((!AnointedEnabled.Value) ? "disabled." : "enabled.")));
				}
			}
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("Couldn't change the Anointed skins setting: " + ex.Message));
		}
	}

	private static void DefineJudgement(string id, string survivor, string body, params string[] skins)
	{
		Define(id, survivor + ": Returned", "As " + survivor + ", survive The Judgement.", skins);
		JudgementBodies[id] = body;
	}

	private static void AttachToSkins()
	{
		bool flag = Chainloader.PluginInfos.ContainsKey("Wolfo.WolfoQoL_Client");
		int num = 0;
		for (int i = 0; i < BodyCatalog.bodyCount; i++)
		{
			SkinDef[] bodySkins = BodyCatalog.GetBodySkins((BodyIndex)i);
			if (bodySkins == null)
			{
				continue;
			}
			SkinDef[] array = bodySkins;
			foreach (SkinDef val in array)
			{
				if ((Object)(object)val == (Object)null || val.nameToken == null || !SkinToAchievement.TryGetValue(val.nameToken, out var value))
				{
					continue;
				}
				UnlockableDef val2 = (val.unlockableDef = Unlockables[value]);
				if (val.nameToken == "ORBITAL_SKIN_MALICE_NAME" && flag && !((Object)val).name.EndsWith("Red"))
				{
					((Object)val).name = ((Object)val).name + "Red";
				}
				if ((Object)(object)val2.achievementIcon == (Object)null && (Object)(object)val.icon != (Object)null)
				{
					val2.achievementIcon = val.icon;
					AchievementDef achievementDef = AchievementManager.GetAchievementDef(value);
					if (achievementDef != null)
					{
						achievementDef.SetAchievedIcon(val.icon);
					}
				}
				num++;
			}
		}
		foreach (KeyValuePair<string, UnlockableDef> unlockable in Unlockables)
		{
			string text = unlockable.Key.ToUpperInvariant();
			string nameTok = "ACHIEVEMENT_" + text + "_NAME";
			string descTok = "ACHIEVEMENT_" + text + "_DESCRIPTION";
			UnlockableDef value2 = unlockable.Value;
			value2.getHowToUnlockString = () => Language.GetStringFormatted("UNLOCK_VIA_ACHIEVEMENT_FORMAT", new object[2]
			{
				Language.GetString(nameTok),
				Language.GetString(descTok)
			});
			value2.getUnlockedString = () => Language.GetStringFormatted("UNLOCKED_FORMAT", new object[2]
			{
				Language.GetString(nameTok),
				Language.GetString(descTok)
			});
		}
		Log.LogInfo((object)("Locked " + num + " skins behind achievements."));
		FenrisLocks.Attach();
		Summer.DetectTropics();
	}
}
internal static class Ids
{
	public const string MechaFiend = "BinmaMechaFiendDecompile";

	public const string Zenith = "BinmaZenithFalseSon";

	public const string Biomass = "BinmaBiomassFalseSon";

	public const string Shackled = "BinmaShackledAcrid";

	public const string LunarVoidRex = "BinmaLunarVoidRex";

	public const string CaptainAtlas = "BinmaFenrisCaptainAtlas";

	public const string RailPyro = "BinmaFenrisRailPyro";

	public const string RailKinetic = "BinmaFenrisRailKinetic";

	public const string SummerRail = "BinmaSummerRailgunner";

	public const string SummerVoid = "BinmaSummerVoidFiend";

	public const string SolusRail = "BinmaSolusRailgunnerPurge";

	public const string SteelCaptain = "BinmaSteelConvictionCaptain";

	public const string JCommando = "BinmaJudgementCommando";

	public const string JHuntress = "BinmaJudgementHuntress";

	public const string JAcrid = "BinmaJudgementAcrid";

	public const string JLoader = "BinmaJudgementLoader";

	public const string JEngi = "BinmaJudgementEngi";

	public const string JMerc = "BinmaJudgementMerc";

	public const string JBandit = "BinmaJudgementBandit";

	public const string JArtificer = "BinmaJudgementArtificer";

	public const string JDrifter = "BinmaJudgementDrifter";
}
internal class ContentProvider : IContentPackProvider
{
	private readonly ContentPack pack = new ContentPack();

	public string identifier => "binma.challengingunlocks";

	public IEnumerator LoadStaticContentAsync(LoadStaticContentAsyncArgs args)
	{
		pack.unlockableDefs.Add(new List<UnlockableDef>(Plugin.Unlockables.Values).ToArray());
		args.ReportProgress(1f);
		yield break;
	}

	public IEnumerator GenerateContentPackAsync(GetContentPackAsyncArgs args)
	{
		ContentPack.Copy(pack, args.output);
		args.ReportProgress(1f);
		yield break;
	}

	public IEnumerator FinalizeAsync(FinalizeAsyncArgs args)
	{
		args.ReportProgress(1f);
		yield break;
	}
}
[HarmonyPatch(typeof(Language), "GetLocalizedStringByToken")]
internal static class LanguagePatch
{
	private static void Postfix(string __0, ref string __result)
	{
		if (__0 != null && (__result == null || __result == __0) && Plugin.Tokens.TryGetValue(__0, out var value))
		{
			__result = value;
		}
	}
}
internal static class Util2
{
	internal static bool PlaysAs(NetworkUser user, string bodyName)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Invalid comparison between Unknown and I4
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)user == (Object)null)
		{
			return false;
		}
		BodyIndex val = BodyCatalog.FindBodyIndex(bodyName);
		if ((int)val == -1)
		{
			return false;
		}
		CharacterBody currentBody = user.GetCurrentBody();
		if ((Object)(object)currentBody != (Object)null)
		{
			return currentBody.bodyIndex == val;
		}
		return user.bodyIndexPreference == val;
	}
}
[RegisterAchievement("BinmaMechaFiendDecompile", "Skins.Binma.BinmaMechaFiendDecompile", "CompleteVoidEnding", 5u, null)]
public class MechaFiendAchievement : BasePerSurvivorDecompileAchievement
{
	protected override BodyIndex LookUpRequiredBodyIndex()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		return BodyCatalog.FindBodyIndex("VoidSurvivorBody");
	}
}
[RegisterAchievement("BinmaZenithFalseSon", "Skins.Binma.BinmaZenithFalseSon", "UnlockFalseSon", 5u, typeof(JudgementServer))]
public class ZenithAchievement : ServerTrackedAchievement
{
}
public abstract class ServerTrackedAchievement : BaseAchievement
{
	public override void OnInstall()
	{
		((BaseAchievement)this).OnInstall();
		((BaseAchievement)this).SetServerTracked(true);
	}

	public override void OnUninstall()
	{
		((BaseAchievement)this).SetServerTracked(false);
		((BaseAchievement)this).OnUninstall();
	}
}
[RegisterAchievement("BinmaBiomassFalseSon", "Skins.Binma.BinmaBiomassFalseSon", "UnlockFalseSon", 5u, typeof(BiomassServer))]
public class BiomassAchievement : ServerTrackedAchievement
{
}
public class BiomassServer : BaseServerAchievement
{
	public override void OnInstall()
	{
		((BaseServerAchievement)this).OnInstall();
		Plugin.OnSeedRevive += Handle;
	}

	public override void OnUninstall()
	{
		Plugin.OnSeedRevive -= Handle;
		((BaseServerAchievement)this).OnUninstall();
	}

	private void Handle(CharacterMaster master)
	{
		if (!((Object)(object)master == (Object)null) && !((Object)(object)((BaseServerAchievement)this).networkUser == (Object)null) && !((Object)(object)((BaseServerAchievement)this).networkUser.master != (Object)(object)master) && Util2.PlaysAs(((BaseServerAchievement)this).networkUser, "FalseSonBody"))
		{
			((BaseServerAchievement)this).Grant();
		}
	}
}
internal static class SeedPatches
{
	internal static void LockPrefix(MonoBehaviour __instance, out bool __state)
	{
		__state = false;
		try
		{
			Traverse val = Traverse.Create((object)__instance);
			float value = val.Field("age").GetValue<float>();
			float value2 = val.Field("delayDuration").GetValue<float>();
			__state = value + Time.fixedDeltaTime > value2;
		}
		catch
		{
		}
	}

	internal static void LockPostfix(MonoBehaviour __instance, bool __state)
	{
		if (!__state || !NetworkServer.active)
		{
			return;
		}
		try
		{
			CharacterMaster component = ((Component)__instance).GetComponent<CharacterMaster>();
			if ((Object)(object)component != (Object)null && component.hasBody)
			{
				Plugin.RaiseSeedRevive(component);
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)ex);
		}
	}
}
[HarmonyPatch]
internal static class SeedSelfPatchHost
{
	[HarmonyPatch(typeof(CharacterMaster), "RespawnExtraLifeHealAndRevive")]
	[HarmonyPostfix]
	private static void Postfix(CharacterMaster __instance)
	{
		try
		{
			if (NetworkServer.active)
			{
				Plugin.RaiseSeedRevive(__instance);
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)ex);
		}
	}
}
internal static class Noir
{
	private static readonly Dictionary<string, Dictionary<CharacterMaster, int>> counts = new Dictionary<string, Dictionary<CharacterMaster, int>>();

	private static readonly Dictionary<CharacterMaster, HashSet<string>> scannerStages = new Dictionary<CharacterMaster, HashSet<string>>();

	private static readonly Dictionary<CharacterMaster, HashSet<int>> pingedEnemies = new Dictionary<CharacterMaster, HashSet<int>>();

	private static readonly Dictionary<CharacterMaster, Queue<float>> recentKills = new Dictionary<CharacterMaster, Queue<float>>();

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

	private static readonly HashSet<string> hiddenRealms = new HashSet<string> { "bazaar", "goldshores", "mysteryspace", "limbo", "arena" };

	private static bool teleporterCharging;

	private static bool allyDiedDuringTeleporter;

	internal static event Action<string, CharacterMaster> OnGrant;

	internal static void Grant(string id, CharacterMaster m)
	{
		Noir.OnGrant?.Invoke(id, m);
	}

	internal static void Count(string id, CharacterMaster m, int needed)
	{
		if (!((Object)(object)m == (Object)null) && NetworkServer.active)
		{
			if (!counts.TryGetValue(id, out var value))
			{
				value = (counts[id] = new Dictionary<CharacterMaster, int>());
			}
			value.TryGetValue(m, out var value2);
			value2 = (value[m] = value2 + 1);
			if (value2 >= needed)
			{
				Grant(id, m);
			}
		}
	}

	internal static CharacterMaster MasterOf(Interactor i)
	{
		if ((Object)(object)i == (Object)null)
		{
			return null;
		}
		CharacterBody component = ((Component)i).GetComponent<CharacterBody>();
		return (!((Object)(object)component != (Object)null)) ? null : component.master;
	}

	private static string CurrentScene()
	{
		SceneDef mostRecentSceneDef = SceneCatalog.mostRecentSceneDef;
		return (!((Object)(object)mostRecentSceneDef != (Object)null)) ? "" : mostRecentSceneDef.cachedName;
	}

	internal static void Init()
	{
		Run.onRunStartGlobal += delegate
		{
			counts.Clear();
			scannerStages.Clear();
			pingedEnemies.Clear();
			recentKills.Clear();
			realmsVisited.Clear();
			teleporterCharging = false;
		};
		GlobalEventManager.OnInteractionsGlobal += delegate(Interactor interactor, IInteractable interactable, GameObject obj)
		{
			if (NetworkServer.active && !((Object)(object)obj == (Object)null))
			{
				CharacterMaster val = MasterOf(interactor);
				if (!((Object)(object)val == (Object)null))
				{
					string text = ((Object)obj).name ?? "";
					if (text.Contains("Stealthed"))
					{
						Count("BinmaNoirBandit", val, 3);
					}
					if ((Object)(object)obj.GetComponent<PortalStatueBehavior>() != (Object)null)
					{
						Count("BinmaNoirHuntress", val, 3);
					}
					if ((Object)(object)obj.GetComponent<SummonMasterBehavior>() != (Object)null)
					{
						Count("BinmaNoirDronetech", val, 5);
					}
					if (text.StartsWith("Lockbox") && !text.Contains("Void"))
					{
						Count("BinmaNoirToolbot", val, 3);
					}
					if ((Object)(object)obj.GetComponent<SeerStationController>() != (Object)null && CurrentScene() == "bazaar")
					{
						Grant("BinmaNoirSeeker", val);
					}
				}
			}
		};
		Opening.onOpened += delegate
		{
			if (NetworkServer.active)
			{
				Grant("BinmaNoirCommando", null);
			}
		};
		Stage.onServerStageBegin += delegate(Stage stage)
		{
			if (!((Object)(object)stage == (Object)null) && !((Object)(object)stage.sceneDef == (Object)null))
			{
				string text = stage.sceneDef.cachedName ?? "";
				if (text.StartsWith("artifactworld"))
				{
					text = "artifactworld";
				}
				if (hiddenRealms.Contains(text) || !(text != "artifactworld"))
				{
					realmsVisited.Add(text);
					if (realmsVisited.Count >= 2)
					{
						Grant("BinmaNoirMage", null);
					}
				}
			}
		};
		TeleporterInteraction.onTeleporterBeginChargingGlobal += delegate
		{
			teleporterCharging = true;
			allyDiedDuringTeleporter = false;
		};
		TeleporterInteraction.onTeleporterChargedGlobal += delegate
		{
			if (NetworkServer.active && teleporterCharging && !allyDiedDuringTeleporter)
			{
				Grant("BinmaNoirLoader", null);
			}
			teleporterCharging = false;
		};
		GlobalEventManager.onDeathProcServer += delegate(DamageReport report)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Invalid comparison between Unknown and I4
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Invalid comparison between Unknown and I4
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkServer.active && report != null)
			{
				if (teleporterCharging && (int)report.victimTeamIndex == 1)
				{
					allyDiedDuringTeleporter = true;
				}
				CharacterMaster attackerMaster = report.attackerMaster;
				if (!((Object)(object)attackerMaster == (Object)null) && (int)report.victimTeamIndex != 1)
				{
					if (!recentKills.TryGetValue(attackerMaster, out var value))
					{
						value = (recentKills[attackerMaster] = new Queue<float>());
					}
					float time = Time.time;
					value.Enqueue(time);
					while (value.Count > 0 && time - value.Peek() > 5f)
					{
						value.Dequeue();
					}
					if (value.Count >= 20)
					{
						Grant("BinmaNoirMerc", attackerMaster);
					}
					if (report.victimIsBoss && (Object)(object)report.attackerBody != (Object)null && (Object)(object)report.victimBody != (Object)null && Vector3.Distance(report.attackerBody.corePosition, report.victimBody.corePosition) >= 100f)
					{
						Grant("BinmaNoirRailgunner", attackerMaster);
					}
				}
			}
		};
		CharacterBody.onBodyStartGlobal += delegate(CharacterBody body)
		{
			if (NetworkServer.active && !((Object)(object)body == (Object)null) && !((Object)(object)body.master == (Object)null))
			{
				MinionOwnership minionOwnership = body.master.minionOwnership;
				CharacterMaster val = ((!((Object)(object)minionOwnership != (Object)null)) ? null : minionOwnership.ownerMaster);
				if (!((Object)(object)val == (Object)null))
				{
					int num = 0;
					foreach (CharacterMaster readOnlyInstances in CharacterMaster.readOnlyInstancesList)
					{
						if (!((Object)(object)readOnlyInstances == (Object)null) && !((Object)(object)readOnlyInstances.minionOwnership == (Object)null) && !((Object)(object)readOnlyInstances.minionOwnership.ownerMaster != (Object)(object)val))
						{
							CharacterBody body2 = readOnlyInstances.GetBody();
							if ((Object)(object)body2 != (Object)null && (Object)(object)body2.healthComponent != (Object)null && body2.healthComponent.alive)
							{
								num++;
							}
						}
					}
					if (num >= 5)
					{
						Grant("BinmaNoirCaptain", val);
					}
				}
			}
		};
	}

	internal static void ScannerUsed(CharacterMaster m)
	{
		if (!((Object)(object)m == (Object)null))
		{
			if (!scannerStages.TryGetValue(m, out var value))
			{
				value = (scannerStages[m] = new HashSet<string>());
			}
			value.Add(CurrentScene());
			if (value.Count >= 3)
			{
				Grant("BinmaNoirEngi", m);
			}
		}
	}

	internal static void EnemyPinged(CharacterMaster m, CharacterBody target)
	{
		if (!((Object)(object)m == (Object)null) && !((Object)(object)target == (Object)null))
		{
			if (!pingedEnemies.TryGetValue(m, out var value))
			{
				value = (pingedEnemies[m] = new HashSet<int>());
			}
			value.Add(((Object)((Component)target).gameObject).GetInstanceID());
			if (value.Count >= 30)
			{
				Grant("BinmaNoirRex", m);
			}
		}
	}
}
public class NoirServer : BaseServerAchievement
{
	public override void OnInstall()
	{
		((BaseServerAchievement)this).OnInstall();
		Noir.OnGrant += Handle;
	}

	public override void OnUninstall()
	{
		Noir.OnGrant -= Handle;
		((BaseServerAchievement)this).OnUninstall();
	}

	private void Handle(string id, CharacterMaster master)
	{
		if (base.achievementDef != null && !(id != base.achievementDef.identifier) && !((Object)(object)((BaseServerAchievement)this).networkUser == (Object)null) && (!((Object)(object)master != (Object)null) || !((Object)(object)((BaseServerAchievement)this).networkUser.master != (Object)(object)master)) && Plugin.NoirBodies.TryGetValue(id, out var value) && Util2.PlaysAs(((BaseServerAchievement)this).networkUser, value))
		{
			((BaseServerAchievement)this).Grant();
		}
	}
}
[RegisterAchievement("BinmaNoirBandit", "Skins.Binma.BinmaNoirBandit", null, 5u, typeof(NoirServer))]
public class NoirBandit : ServerTrackedAchievement
{
}
[RegisterAchievement("BinmaNoirCommando", "Skins.Binma.BinmaNoirCommando", null, 5u, typeof(NoirServer))]
public class NoirCommando : ServerTrackedAchievement
{
}
[RegisterAchievement("BinmaNoirEngi", "Skins.Binma.BinmaNoirEngi", null, 5u, typeof(NoirServer))]
public class NoirEngi : ServerTrackedAchievement
{
}
[RegisterAchievement("BinmaNoirRex", "Skins.Binma.BinmaNoirRex", null, 5u, typeof(NoirServer))]
public class NoirRex : ServerTrackedAchievement
{
}
[RegisterAchievement("BinmaNoirHuntress", "Skins.Binma.BinmaNoirHuntress", null, 5u, typeof(NoirServer))]
public class NoirHuntress : ServerTrackedAchievement
{
}
[RegisterAchievement("BinmaNoirCaptain", "Skins.Binma.BinmaNoirCaptain", null, 5u, typeof(NoirServer))]
public class NoirCaptain : ServerTrackedAchievement
{
}
[RegisterAchievement("BinmaNoirLoader", "Skins.Binma.BinmaNoirLoader", null, 5u, typeof(NoirServer))]
public class NoirLoader : ServerTrackedAchievement
{
}
[RegisterAchievement("BinmaNoirMage", "Skins.Binma.BinmaNoirMage", null, 5u, typeof(NoirServer))]
public class NoirMage : ServerTrackedAchievement
{
}
[RegisterAchievement("BinmaNoirVoidfiend", "Skins.Binma.BinmaNoirVoidfiend", null, 5u, typeof(NoirServer))]
public class NoirVoidfiend : ServerTrackedAchievement
{
}
[RegisterAchievement("BinmaNoirMerc", "Skins.Binma.BinmaNoirMerc", null, 5u, typeof(NoirServer))]
public class NoirMerc : ServerTrackedAchievement
{
}
[RegisterAchievement("BinmaNoirDrifter", "Skins.Binma.BinmaNoirDrifter", null, 5u, typeof(NoirServer))]
public class NoirDrifter : ServerTrackedAchievement
{
}
[RegisterAchievement("BinmaNoirDronetech", "Skins.Binma.BinmaNoirDronetech", null, 5u, typeof(NoirServer))]
public class NoirDronetech : ServerTrackedAchievement
{
}
[RegisterAchievement("BinmaNoirToolbot", "Skins.Binma.BinmaNoirToolbot", null, 5u, typeof(NoirServer))]
public class NoirToolbot : ServerTrackedAchievement
{
}
[RegisterAchievement("BinmaNoirSeeker", "Skins.Binma.BinmaNoirSeeker", null, 5u, typeof(NoirServer))]
public class NoirSeeker : ServerTrackedAchievement
{
}
[RegisterAchievement("BinmaNoirRailgunner", "Skins.Binma.BinmaNoirRailgunner", null, 5u, typeof(NoirServer))]
public class NoirRailgunner : ServerTrackedAchievement
{
}
[RegisterAchievement("BinmaNoirChef", "Skins.Binma.BinmaNoirChef", null, 5u, typeof(NoirServer))]
public class NoirChef : ServerTrackedAchievement
{
}
[HarmonyPatch(typeof(EquipmentSlot), "FireScanner")]
internal static class ScannerPatch
{
	private static void Postfix(EquipmentSlot __instance, bool __result)
	{
		try
		{
			if (__result && NetworkServer.active && (Object)(object)__instance.characterBody != (Object)null)
			{
				Noir.ScannerUsed(__instance.characterBody.master);
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)ex);
		}
	}
}
[HarmonyPatch(typeof(PingerController), "CmdPing")]
internal static class PingPatch
{
	private static void Postfix(PingerController __instance, PingInfo __0)
	{
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Invalid comparison between Unknown and I4
		try
		{
			if (!NetworkServer.active)
			{
				return;
			}
			GameObject targetGameObject = ((PingInfo)(ref __0)).targetGameObject;
			if (!((Object)(object)targetGameObject == (Object)null))
			{
				CharacterBody component = targetGameObject.GetComponent<CharacterBody>();
				if (!((Object)(object)component == (Object)null) && !((Object)(object)component.teamComponent == (Object)null) && (int)component.teamComponent.teamIndex != 1)
				{
					Noir.EnemyPinged(((Component)__instance).GetComponent<CharacterMaster>(), component);
				}
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)ex);
		}
	}
}
[HarmonyPatch(typeof(ScrapperController), "BeginScrapping")]
internal static class ScrapPatch
{
	private static void Postfix(ScrapperController __instance)
	{
		try
		{
			if (NetworkServer.active)
			{
				Interactor value = Traverse.Create((object)__instance).Field("interactor").GetValue<Interactor>();
				Noir.Count("BinmaNoirDrifter", Noir.MasterOf(value), 10);
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)ex);
		}
	}
}
[HarmonyPatch(typeof(MealPrepController), "BeginCookingServer")]
internal static class CookPatch
{
	private static void Postfix(Interactor __0)
	{
		try
		{
			if (NetworkServer.active)
			{
				Noir.Count("BinmaNoirChef", Noir.MasterOf(__0), 3);
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)ex);
		}
	}
}
[HarmonyPatch(typeof(CorruptMode), "FixedUpdate")]
internal static class CorruptTimePatch
{
	private static readonly HashSet<EntityState> done = new HashSet<EntityState>();

	private static void Postfix(CorruptMode __instance)
	{
		try
		{
			if (!NetworkServer.active || done.Contains((EntityState)(object)__instance))
			{
				return;
			}
			float value = Traverse.Create((object)__instance).Property("fixedAge", (object[])null).GetValue<float>();
			if (!(value < 60f))
			{
				done.Add((EntityState)(object)__instance);
				CharacterBody value2 = Traverse.Create((object)__instance).Property("characterBody", (object[])null).GetValue<CharacterBody>();
				if ((Object)(object)value2 != (Object)null)
				{
					Noir.Grant("BinmaNoirVoidfiend", value2.master);
				}
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)ex);
		}
	}
}
[RegisterAchievement("BinmaNoirAcrid", "Skins.Binma.BinmaNoirAcrid", null, 5u, null)]
public class NoirAcrid : BaseAchievement
{
	protected override BodyIndex LookUpRequiredBodyIndex()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		return BodyCatalog.FindBodyIndex("CrocoBody");
	}

	protected override void OnBodyRequirementMet()
	{
		((BaseAchievement)this).OnBodyRequirementMet();
		UserProfile.onUnlockableGranted += OnUnlock;
	}

	protected override void OnBodyRequirementBroken()
	{
		UserProfile.onUnlockableGranted -= OnUnlock;
		((BaseAchievement)this).OnBodyRequirementBroken();
	}

	private void OnUnlock(UserProfile profile, UnlockableDef def)
	{
		if (profile != ((BaseAchievement)this).userProfile || (Object)(object)def == (Object)null || def.cachedName == null || !def.cachedName.StartsWith("Logs.Stages."))
		{
			return;
		}
		StatSheet statSheet = ((BaseAchievement)this).userProfile.statSheet;
		int num = 0;
		for (int i = 0; i < statSheet.GetUnlockableCount(); i++)
		{
			UnlockableDef unlockable = statSheet.GetUnlockable(i);
			if ((Object)(object)unlockable != (Object)null && unlockable.cachedName != null && unlockable.cachedName.StartsWith("Logs.Stages."))
			{
				num++;
			}
		}
		if (num >= 5)
		{
			((BaseAchievement)this).Grant();
		}
	}
}
[RegisterAchievement("BinmaNoirFalseson", "Skins.Binma.BinmaNoirFalseson", "UnlockFalseSon", 5u, null)]
public class NoirFalseSon : BaseAchievement
{
	internal static event Action<PickupIndex> OnInspect;

	internal static void RaiseInspect(PickupIndex p)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		NoirFalseSon.OnInspect?.Invoke(p);
	}

	protected override BodyIndex LookUpRequiredBodyIndex()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		return BodyCatalog.FindBodyIndex("FalseSonBody");
	}

	protected override void OnBodyRequirementMet()
	{
		((BaseAchievement)this).OnBodyRequirementMet();
		OnInspect += Handle;
	}

	protected override void OnBodyRequirementBroken()
	{
		OnInspect -= Handle;
		((BaseAchievement)this).OnBodyRequirementBroken();
	}

	private string SavePath()
	{
		string text = ((((BaseAchievement)this).userProfile == null || ((BaseAchievement)this).userProfile.fileName == null) ? "default" : ((BaseAchievement)this).userProfile.fileName);
		char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
		foreach (char oldChar in invalidFileNameChars)
		{
			text = text.Replace(oldChar, '_');
		}
		return Path.Combine(Paths.ConfigPath, "binma.challengingunlocks.inspected." + text + ".txt");
	}

	private void Handle(PickupIndex p)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Invalid comparison between Unknown and I4
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Invalid comparison between Unknown and I4
		try
		{
			PickupDef pickupDef = PickupCatalog.GetPickupDef(p);
			if (pickupDef != null && ((int)pickupDef.itemIndex != -1 || (int)pickupDef.equipmentIndex != -1))
			{
				string path = SavePath();
				HashSet<string> hashSet = new HashSet<string>((!File.Exists(path)) ? ((IEnumerable<string>)new string[0]) : ((IEnumerable<string>)File.ReadAllLines(path)));
				if (hashSet.Add(pickupDef.internalName))
				{
					File.WriteAllLines(path, new List<string>(hashSet).ToArray());
				}
				if (hashSet.Count >= 25)
				{
					((BaseAchievement)this).Grant();
				}
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)ex);
		}
	}
}
[HarmonyPatch]
internal static class InspectPatch
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		foreach (MethodInfo m in AccessTools.GetDeclaredMethods(typeof(InspectPanelController)))
		{
			ParameterInfo[] ps = m.GetParameters();
			if (m.Name == "Show" && ps.Length > 0 && ps[0].ParameterType == typeof(InspectInfo))
			{
				yield return m;
			}
		}
	}

	private static void Postfix(InspectInfo __0)
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (__0 != null && __0.isDynamicInspectInfo)
			{
				NoirFalseSon.RaiseInspect(__0.dynamicInspectPickupIndex);
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)ex);
		}
	}
}
internal static class VoidRunTracker
{
	private static bool clearedArena;

	private static bool visitedLocus;

	internal static void Init()
	{
		Run.onRunStartGlobal += delegate
		{
			clearedArena = false;
			visitedLocus = false;
		};
		ArenaMissionController.onBeatArena += delegate
		{
			if (NetworkServer.active)
			{
				clearedArena = true;
			}
		};
		Stage.onServerStageBegin += delegate(Stage stage)
		{
			if ((Object)(object)stage != (Object)null && (Object)(object)stage.sceneDef != (Object)null && stage.sceneDef.cachedName == "voidstage")
			{
				visitedLocus = true;
			}
		};
		Run.onServerGameOver += delegate(Run run, GameEndingDef ending)
		{
			if ((Object)(object)ending != (Object)null && ending.cachedName == "VoidEnding" && clearedArena && visitedLocus)
			{
				Plugin.RaiseVoidRunComplete();
			}
		};
	}
}
[RegisterAchievement("BinmaShackledAcrid", "Skins.Binma.BinmaShackledAcrid", "BeatArena", 5u, typeof(ShackledServer))]
public class ShackledAchievement : ServerTrackedAchievement
{
}
public class ShackledServer : BaseServerAchievement
{
	public override void OnInstall()
	{
		((BaseServerAchievement)this).OnInstall();
		Plugin.OnVoidRunComplete += Handle;
	}

	public override void OnUninstall()
	{
		Plugin.OnVoidRunComplete -= Handle;
		((BaseServerAchievement)this).OnUninstall();
	}

	private void Handle()
	{
		if (base.achievementDef != null && Plugin.VoidRunBodies.TryGetValue(base.achievementDef.identifier, out var value) && Util2.PlaysAs(((BaseServerAchievement)this).networkUser, value))
		{
			((BaseServerAchievement)this).Grant();
		}
	}
}
[RegisterAchievement("BinmaLunarVoidRex", "Skins.Binma.BinmaLunarVoidRex", null, 5u, typeof(ShackledServer))]
public class LunarVoidRexAchievement : ServerTrackedAchievement
{
}
internal static class FenrisLocks
{
	private static readonly HashSet<string> probePrefabs = new HashSet<string>();

	internal static event Action<string, CharacterMaster> OnGrant;

	internal static void NoteProbePrefab(GameObject prefab)
	{
		if ((Object)(object)prefab != (Object)null)
		{
			probePrefabs.Add(((Object)prefab).name);
		}
	}

	private static void Grant(string id, CharacterMaster m)
	{
		FenrisLocks.OnGrant?.Invoke(id, m);
	}

	private static void Lock(string bodyName, Func<Type, bool> match, string id)
	{
		GameObject val = BodyCatalog.FindBodyPrefab(bodyName);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		GenericSkill[] components = val.GetComponents<GenericSkill>();
		foreach (GenericSkill val2 in components)
		{
			SkillFamily skillFamily = val2.skillFamily;
			if ((Object)(object)skillFamily == (Object)null || skillFamily.variants == null)
			{
				continue;
			}
			for (int j = 0; j < skillFamily.variants.Length; j++)
			{
				SkillDef skillDef = skillFamily.variants[j].skillDef;
				if ((Object)(object)skillDef == (Object)null)
				{
					continue;
				}
				Type stateType = ((SerializableEntityStateType)(ref skillDef.activationState)).stateType;
				if (stateType == null || stateType.Namespace == null || !stateType.Namespace.StartsWith("FenrisSkills") || !match(stateType))
				{
					continue;
				}
				UnlockableDef val3 = Plugin.Unlockables[id];
				val3.nameToken = skillDef.skillNameToken;
				skillFamily.variants[j].unlockableDef = val3;
				if ((Object)(object)skillDef.icon != (Object)null)
				{
					val3.achievementIcon = skillDef.icon;
					AchievementDef achievementDef = AchievementManager.GetAchievementDef(id);
					if (achievementDef != null)
					{
						achievementDef.SetAchievedIcon(skillDef.icon);
					}
				}
				Plugin.Log.LogInfo((object)("Locked skill " + skillDef.skillName + " on " + bodyName + "."));
			}
		}
	}

	internal static void Attach()
	{
		try
		{
			Lock("CaptainBody", (Type t) => true, "BinmaFenrisCaptainAtlas");
			Lock("RailgunnerBody", (Type t) => t.Name == "FireMineExplosive", "BinmaFenrisRailKinetic");
			Lock("RailgunnerBody", (Type t) => t.Name != "FireMineExplosive", "BinmaFenrisRailPyro");
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)ex);
		}
	}

	internal static void Init()
	{
		GlobalEventManager.onDeathProcServer += delegate(DamageReport report)
		{
			try
			{
				if (NetworkServer.active && report != null && !((Object)(object)report.attackerMaster == (Object)null) && !((Object)(object)report.victimBody == (Object)null))
				{
					CharacterMaster attackerMaster = report.attackerMaster;
					if (((Object)report.victimBody).name.StartsWith("BrotherHurtBody") && report.damageInfo != null && (Object)(object)report.damageInfo.inflictor != (Object)null)
					{
						string name = ((Object)report.damageInfo.inflictor).name;
						bool flag = name.Contains("Airstrike");
						foreach (string probePrefab in probePrefabs)
						{
							if (name.StartsWith(probePrefab))
							{
								flag = true;
							}
						}
						if (flag)
						{
							Grant("BinmaFenrisCaptainAtlas", attackerMaster);
						}
					}
					if (report.victimIsBoss)
					{
						CharacterBody victimBody = report.victimBody;
						if (victimBody.HasBuff(Buffs.OnFire) || ((Object)(object)Buffs.StrongerBurn != (Object)null && victimBody.HasBuff(Buffs.StrongerBurn)))
						{
							Grant("BinmaFenrisRailPyro", attackerMaster);
						}
						CharacterBody attackerBody = report.attackerBody;
						if ((Object)(object)attackerBody != (Object)null && (Object)(object)attackerBody.characterMotor != (Object)null && !attackerBody.characterMotor.isGrounded)
						{
							Grant("BinmaFenrisRailKinetic", attackerMaster);
						}
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)ex);
			}
		};
	}
}
public class FenrisServer : BaseServerAchievement
{
	private static readonly Dictionary<string, string> bodies = new Dictionary<string, string>
	{
		{ "BinmaFenrisCaptainAtlas", "CaptainBody" },
		{ "BinmaFenrisRailPyro", "RailgunnerBody" },
		{ "BinmaFenrisRailKinetic", "RailgunnerBody" }
	};

	public override void OnInstall()
	{
		((BaseServerAchievement)this).OnInstall();
		FenrisLocks.OnGrant += Handle;
	}

	public override void OnUninstall()
	{
		FenrisLocks.OnGrant -= Handle;
		((BaseServerAchievement)this).OnUninstall();
	}

	private void Handle(string id, CharacterMaster master)
	{
		if (base.achievementDef != null && !(id != base.achievementDef.identifier) && !((Object)(object)((BaseServerAchievement)this).networkUser == (Object)null) && !((Object)(object)((BaseServerAchievement)this).networkUser.master != (Object)(object)master) && bodies.TryGetValue(id, out var value) && Util2.PlaysAs(((BaseServerAchievement)this).networkUser, value))
		{
			((BaseServerAchievement)this).Grant();
		}
	}
}
[RegisterAchievement("BinmaFenrisCaptainAtlas", "Skins.Binma.BinmaFenrisCaptainAtlas", "CompleteMainEnding", 5u, typeof(FenrisServer))]
public class CaptainAtlasAchievement : ServerTrackedAchievement
{
}
[RegisterAchievement("BinmaFenrisRailPyro", "Skins.Binma.BinmaFenrisRailPyro", null, 5u, typeof(FenrisServer))]
public class RailPyroAchievement : ServerTrackedAchievement
{
}
[RegisterAchievement("BinmaFenrisRailKinetic", "Skins.Binma.BinmaFenrisRailKinetic", null, 5u, typeof(FenrisServer))]
public class RailKineticAchievement : ServerTrackedAchievement
{
}
[HarmonyPatch(typeof(CallAirstrikeBase), "ModifyProjectile")]
internal static class ProbePrefabPatch
{
	private static void Postfix(ref FireProjectileInfo __0)
	{
		try
		{
			FenrisLocks.NoteProbePrefab(__0.projectilePrefab);
		}
		catch
		{
		}
	}
}
internal static class Summer
{
	internal static bool TropicsInstalled;

	private static readonly HashSet<string> tropicsScenes = new HashSet<string> { "tropics_wormsworms", "tropicsnight_wormsworms" };

	internal static event Action<CharacterMaster> OnLegendaryOpened;

	internal static void DetectTropics()
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Invalid comparison between Unknown and I4
		foreach (string tropicsScene in tropicsScenes)
		{
			if ((int)SceneCatalog.FindSceneIndex(tropicsScene) != -1)
			{
				TropicsInstalled = true;
			}
		}
		if (TropicsInstalled)
		{
			Plugin.Tokens["ACHIEVEMENT_" + "BinmaSummerRailgunner".ToUpperInvariant() + "_DESCRIPTION"] = "As Railgunner, open a Legendary Chest on Sunset Tropics or Midnight Tropics.";
			Plugin.Tokens["ACHIEVEMENT_" + "BinmaSummerVoidFiend".ToUpperInvariant() + "_DESCRIPTION"] = "As 「V??oid Fiend』, open a Legendary Chest on Sunset Tropics or Midnight Tropics.";
			Plugin.Log.LogInfo((object)"Sunset Tropics detected; Summer skins require the Tropics.");
		}
	}

	private static bool StageCounts()
	{
		if (TropicsInstalled)
		{
			SceneDef mostRecentSceneDef = SceneCatalog.mostRecentSceneDef;
			return (Object)(object)mostRecentSceneDef != (Object)null && tropicsScenes.Contains(mostRecentSceneDef.cachedName);
		}
		return true;
	}

	internal static void Init()
	{
		GlobalEventManager.OnInteractionsGlobal += delegate(Interactor interactor, IInteractable interactable, GameObject obj)
		{
			try
			{
				if (NetworkServer.active && !((Object)(object)obj == (Object)null) && !((Object)(object)obj.GetComponent<PurchaseInteraction>() == (Object)null) && ((Object)obj).name.Contains("GoldChest") && StageCounts())
				{
					CharacterMaster val = Noir.MasterOf(interactor);
					Action<CharacterMaster> onLegendaryOpened = Summer.OnLegendaryOpened;
					if ((Object)(object)val != (Object)null)
					{
						onLegendaryOpened?.Invoke(val);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)ex);
			}
		};
	}
}
public class SummerServer : BaseServerAchievement
{
	public override void OnInstall()
	{
		((BaseServerAchievement)this).OnInstall();
		Summer.OnLegendaryOpened += Handle;
	}

	public override void OnUninstall()
	{
		Summer.OnLegendaryOpened -= Handle;
		((BaseServerAchievement)this).OnUninstall();
	}

	private void Handle(CharacterMaster master)
	{
		if (!((Object)(object)((BaseServerAchievement)this).networkUser == (Object)null) && !((Object)(object)((BaseServerAchievement)this).networkUser.master != (Object)(object)master))
		{
			string bodyName = ((base.achievementDef == null || !(base.achievementDef.identifier == "BinmaSummerRailgunner")) ? "VoidSurvivorBody" : "RailgunnerBody");
			if (Util2.PlaysAs(((BaseServerAchievement)this).networkUser, bodyName))
			{
				((BaseServerAchievement)this).Grant();
			}
		}
	}
}
[RegisterAchievement("BinmaSummerRailgunner", "Skins.Binma.BinmaSummerRailgunner", null, 5u, typeof(SummerServer))]
public class SummerRailAchievement : ServerTrackedAchievement
{
}
[RegisterAchievement("BinmaSummerVoidFiend", "Skins.Binma.BinmaSummerVoidFiend", "CompleteVoidEnding", 5u, typeof(SummerServer))]
public class SummerVoidAchievement : ServerTrackedAchievement
{
}
[RegisterAchievement("BinmaSolusRailgunnerPurge", "Skins.Binma.BinmaSolusRailgunnerPurge", null, 5u, typeof(KillSolusHeartServer))]
public class SolusRailAchievement : BasePerSurvivorPurgeAchievement
{
	protected class KillSolusHeartServer : BasePerSurvivorKillSolusHeartServerAchievement
	{
	}

	protected override BodyIndex LookUpRequiredBodyIndex()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		return BodyCatalog.FindBodyIndex("RailgunnerBody");
	}
}
[RegisterAchievement("BinmaSteelConvictionCaptain", "Skins.Binma.BinmaSteelConvictionCaptain", "CompleteMainEnding", 5u, null)]
public class SteelCaptainAchievement : BaseAchievement
{
	internal static readonly string[] Bosses = new string[4] { "RoboBallBossBody", "SuperRoboBallBossBody", "VultureHunterBody", "SolusAmalgamatorBody" };

	private static readonly Dictionary<UserProfile, HashSet<string>> thisRun = new Dictionary<UserProfile, HashSet<string>>();

	private static bool hooked;

	internal static event Action<UserProfile, StatSheet> OnStatDelta;

	internal static void RaiseDelta(UserProfile p, StatSheet d)
	{
		SteelCaptainAchievement.OnStatDelta?.Invoke(p, d);
	}

	protected override BodyIndex LookUpRequiredBodyIndex()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		return BodyCatalog.FindBodyIndex("CaptainBody");
	}

	protected override void OnBodyRequirementMet()
	{
		((BaseAchievement)this).OnBodyRequirementMet();
		if (!hooked)
		{
			hooked = true;
			Run.onRunStartGlobal += delegate
			{
				thisRun.Clear();
			};
		}
		OnStatDelta += Handle;
	}

	protected override void OnBodyRequirementBroken()
	{
		OnStatDelta -= Handle;
		((BaseAchievement)this).OnBodyRequirementBroken();
	}

	private static double Get(StatSheet sheet, PerBodyStatDef def, string body)
	{
		StatDef val = def.FindStatDef(body);
		return (val == null) ? 0.0 : sheet.GetStatValueAsDouble(val);
	}

	private void Handle(UserProfile profile, StatSheet delta)
	{
		try
		{
			if (profile != ((BaseAchievement)this).userProfile || delta == null)
			{
				return;
			}
			if (!thisRun.TryGetValue(profile, out var value))
			{
				value = (thisRun[profile] = new HashSet<string>());
			}
			string[] bosses = Bosses;
			foreach (string text in bosses)
			{
				if (Get(delta, PerBodyStatDef.damageDealtTo, text) > 0.0 || Get(delta, PerBodyStatDef.killsAgainst, text) > 0.0)
				{
					value.Add(text);
				}
			}
			if ((value.Contains("RoboBallBossBody") || value.Contains("SuperRoboBallBossBody")) && value.Contains("VultureHunterBody") && value.Contains("SolusAmalgamatorBody"))
			{
				((BaseAchievement)this).Grant();
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)ex);
		}
	}
}
[HarmonyPatch(typeof(UserProfile), "ApplyDeltaStatSheet")]
internal static class StatDeltaPatch
{
	private static void Postfix(UserProfile __instance, StatSheet __0)
	{
		try
		{
			SteelCaptainAchievement.RaiseDelta(__instance, __0);
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)ex);
		}
	}
}
public abstract class JudgementAchievement : ServerTrackedAchievement
{
}
public class JudgementServer : BaseServerAchievement
{
	public override void OnInstall()
	{
		((BaseServerAchievement)this).OnInstall();
		Ending.onArraignDefeated += Handle;
	}

	public override void OnUninstall()
	{
		Ending.onArraignDefeated -= Handle;
		((BaseServerAchievement)this).OnUninstall();
	}

	private void Handle()
	{
		if (base.achievementDef != null && Plugin.JudgementBodies.TryGetValue(base.achievementDef.identifier, out var value) && Util2.PlaysAs(((BaseServerAchievement)this).networkUser, value))
		{
			((BaseServerAchievement)this).Grant();
		}
	}
}
[RegisterAchievement("BinmaJudgementCommando", "Skins.Binma.BinmaJudgementCommando", null, 5u, typeof(JudgementServer))]
public class JudgementCommando : JudgementAchievement
{
}
[RegisterAchievement("BinmaJudgementHuntress", "Skins.Binma.BinmaJudgementHuntress", null, 5u, typeof(JudgementServer))]
public class JudgementHuntress : JudgementAchievement
{
}
[RegisterAchievement("BinmaJudgementAcrid", "Skins.Binma.BinmaJudgementAcrid", null, 5u, typeof(JudgementServer))]
public class JudgementAcrid : JudgementAchievement
{
}
[RegisterAchievement("BinmaJudgementLoader", "Skins.Binma.BinmaJudgementLoader", null, 5u, typeof(JudgementServer))]
public class JudgementLoader : JudgementAchievement
{
}
[RegisterAchievement("BinmaJudgementEngi", "Skins.Binma.BinmaJudgementEngi", null, 5u, typeof(JudgementServer))]
public class JudgementEngi : JudgementAchievement
{
}
[RegisterAchievement("BinmaJudgementMerc", "Skins.Binma.BinmaJudgementMerc", null, 5u, typeof(JudgementServer))]
public class JudgementMerc : JudgementAchievement
{
}
[RegisterAchievement("BinmaJudgementBandit", "Skins.Binma.BinmaJudgementBandit", null, 5u, typeof(JudgementServer))]
public class JudgementBandit : JudgementAchievement
{
}
[RegisterAchievement("BinmaJudgementArtificer", "Skins.Binma.BinmaJudgementArtificer", null, 5u, typeof(JudgementServer))]
public class JudgementArtificer : JudgementAchievement
{
}
[RegisterAchievement("BinmaJudgementDrifter", "Skins.Binma.BinmaJudgementDrifter", null, 5u, typeof(JudgementServer))]
public class JudgementDrifter : JudgementAchievement
{
}