Decompiled source of VanillaPlusPlus v0.1.0

BepInEx/plugins/VanillaPlusPlus/Olligame.VanillaVoidQuality.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using EntityStates;
using EntityStates.DeepVoidPortalBattery;
using ItemQualities;
using ItemQualities.ContentManagement;
using Mono.Cecil;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using MonoMod.RuntimeDetour;
using On.RoR2;
using On.RoR2.Projectile;
using R2API;
using RoR2;
using RoR2.Projectile;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Networking;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.SceneManagement;
using vanillaVoid.Items;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace OlligameVoidQuality;

[BepInPlugin("Olligame.VanillaVoidQuality", "Vanilla Void Quality", "0.1.0")]
[BepInDependency("Olligame.SeparateVoidDonation", "1.7.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency("com.Gorakh.ItemQualities", "0.8.5")]
[BepInDependency("com.Zenithrium.vanillaVoid", "1.7.2")]
public sealed class Plugin : BaseUnityPlugin
{
	private delegate bool OriginalDelivery(VoidShell self, bool original, Charged state);

	private delegate bool ReplaceDelivery(OriginalDelivery orig, VoidShell self, bool original, Charged state);

	internal static Plugin Instance;

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

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

	internal static BuffDef DashRefund;

	internal static BuffDef WatchHits;

	private static GameObject largeRocket;

	private readonly List<IDisposable> hooks = new List<IDisposable>();

	internal static readonly float[] Strength = new float[4] { 1f, 2f, 4f, 6f };

	private static readonly string[] ids = new string[15]
	{
		"AbyssalAdze", "ClockworkMechanism", "EnhancementVials", "ExtraterrestrialExhaust", "CryoCanister", "VoidShell", "CorrosiveCore", "CrystalLotus", "ExeBlade", "DashQuill",
		"VoidFin", "LensOrrery", "ConsumedClockworkMechanism", "EmptyVials", "ShatteredVials"
	};

	private void Awake()
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Expected O, but got Unknown
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0176: Expected O, but got Unknown
		//IL_017e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Expected O, but got Unknown
		//IL_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_019a: Expected O, but got Unknown
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ac: Expected O, but got Unknown
		//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01be: Expected O, but got Unknown
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		Instance = this;
		List<string> list = new List<string>(NetworkModCompatibilityHelper.networkModList);
		list.Add("Olligame.VanillaVoidQuality;0.1.0");
		NetworkModCompatibilityHelper.networkModList = list;
		QualityContentManager.LoadContentAsync += new LoadContentAsyncDelegate(LoadContent);
		((ResourceAvailability)(ref QualityCatalog.Availability)).CallWhenAvailable((Action)ValidateCatalog);
		DashRefund = ScriptableObject.CreateInstance<BuffDef>();
		((Object)DashRefund).name = "OlligameVoidQualityDashRefund";
		DashRefund.canStack = true;
		DashRefund.isHidden = true;
		ContentAddition.AddBuffDef(DashRefund);
		WatchHits = ScriptableObject.CreateInstance<BuffDef>();
		((Object)WatchHits).name = "OlligameVoidQualityWatchHits";
		WatchHits.canStack = true;
		WatchHits.isHidden = true;
		ContentAddition.AddBuffDef(WatchHits);
		if (Object.op_Implicit((Object)(object)ExtraterrestrialExhaust.RocketProjectile))
		{
			largeRocket = PrefabAPI.InstantiateClone(ExtraterrestrialExhaust.RocketProjectile, "OlligameQualityRocketProjectile", true);
			Transform transform = largeRocket.transform;
			transform.localScale *= 1.5f;
			ProjectileImpactExplosion component = largeRocket.GetComponent<ProjectileImpactExplosion>();
			if (Object.op_Implicit((Object)(object)component))
			{
				((ProjectileExplosion)component).blastRadius = ((ProjectileExplosion)component).blastRadius * 1.5f;
			}
			ContentAddition.AddProjectile(largeRocket);
		}
		CharacterBody.onBodyStartGlobal += BodyStarted;
		GlobalEventManager.onCharacterDeathGlobal += Death;
		HealthComponent.TakeDamage += new hook_TakeDamage(TakeDamage);
		GlobalEventManager.OnHitEnemy += new hook_OnHitEnemy(Hit);
		ProjectileManager.FireProjectile_FireProjectileInfo += new hook_FireProjectile_FireProjectileInfo(Fire);
		HoldoutZoneController.Awake += new hook_Awake(Holdout);
		RecalculateStatsAPI.GetStatCoefficients += new StatHookEventHandler(Stats);
		InstallSpecificHooks();
		ConsumableSupport.Install(hooks);
		ScrapCompatibility.Install(hooks);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Vanilla Void Quality 0.1.0: custom quality groups and item-specific bonuses enabled.");
	}

	private void ValidateCatalog()
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Invalid comparison between Unknown and I4
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Invalid comparison between Unknown and I4
		int num = 0;
		foreach (KeyValuePair<string, ItemQualityGroup> group in Groups)
		{
			for (int i = 0; i < 4; i++)
			{
				ItemIndex itemIndex = group.Value.GetItemIndex((QualityTier)i);
				if ((int)itemIndex == -1 || itemIndex == group.Value.BaseItemIndex || (int)QualityCatalog.GetQualityTier(itemIndex) != i)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("Missing quality variant: " + group.Key + " / " + (object)(QualityTier)i));
				}
				else
				{
					num++;
				}
			}
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Vanilla Void Quality ready: " + Groups.Count + " groups, " + num + " quality variants. Void Scrap names and Mark for Scrap compatibility enabled when installed."));
	}

	private IEnumerator LoadContent(QualityContentLoadArgs args)
	{
		_ = typeof(ItemBase).Assembly;
		BaseUnityPlugin plugin = Chainloader.PluginInfos["com.Zenithrium.vanillaVoid"].Instance;
		IEnumerable all = (IEnumerable)((object)plugin).GetType().GetField("Items", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(plugin);
		foreach (ItemBase item in all)
		{
			ItemBase val = item;
			string name = ((object)val).GetType().Name;
			if (Array.IndexOf(ids, name) >= 0 && Object.op_Implicit((Object)(object)val.ItemDef))
			{
				Items[name] = val;
				Groups[name] = args.CreateItemQualityGroup(val.ItemDef);
				for (int i = 0; i < 4; i++)
				{
					string text = "ITEM_" + ((Object)val.ItemDef).name.ToUpperInvariant() + "_" + ((object)(QualityTier)i).ToString().ToUpperInvariant();
					string text2 = Description(name, i);
					LanguageAPI.Add(text + "_PICKUP", "{0}\n<sprite name=\"Quality\"> " + text2);
					LanguageAPI.Add(text + "_DESC", "{0}\n<sprite name=\"Quality\"> " + text2);
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Registered quality variants: " + val.ItemName));
			}
		}
		yield return ScrapCompatibility.LoadContent(args);
	}

	internal static float Power(Inventory inventory, string id)
	{
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Invalid comparison between Unknown and I4
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)inventory) || !Groups.TryGetValue(id, out var value))
		{
			return 0f;
		}
		float num = 0f;
		for (int i = 0; i < 4; i++)
		{
			ItemIndex itemIndex = value.GetItemIndex((QualityTier)i);
			if ((int)itemIndex != -1)
			{
				num += (float)inventory.GetItemCountEffective(itemIndex) * Strength[i];
			}
		}
		return num;
	}

	internal static float Power(CharacterBody body, string id)
	{
		return Object.op_Implicit((Object)(object)body) ? Power(body.inventory, id) : 0f;
	}

	internal static int Highest(CharacterBody body, string id)
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Invalid comparison between Unknown and I4
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)body.inventory) || !Groups.TryGetValue(id, out var value))
		{
			return -1;
		}
		for (int num = 3; num >= 0; num--)
		{
			if ((int)value.GetItemIndex((QualityTier)num) != -1 && body.inventory.GetItemCountEffective(value.GetItemIndex((QualityTier)num)) > 0)
			{
				return num;
			}
		}
		return -1;
	}

	internal static bool Roll(float percent, CharacterBody body)
	{
		return percent > 0f && Util.CheckRoll(Mathf.Min(100f, percent), Object.op_Implicit((Object)(object)body) ? body.master : null);
	}

	internal static BodyState State(CharacterBody body)
	{
		BodyState component = ((Component)body).GetComponent<BodyState>();
		return Object.op_Implicit((Object)(object)component) ? component : ((Component)body).gameObject.AddComponent<BodyState>();
	}

	private void BodyStarted(CharacterBody body)
	{
		if (body.isPlayerControlled)
		{
			State(body);
		}
	}

	private void TakeDamage(orig_TakeDamage orig, HealthComponent self, DamageInfo info)
	{
		if (!NetworkServer.active)
		{
			orig.Invoke(self, info);
			return;
		}
		CharacterBody val = (Object.op_Implicit((Object)(object)info.attacker) ? info.attacker.GetComponent<CharacterBody>() : null);
		if (Object.op_Implicit((Object)(object)self.body) && self.body.isPlayerControlled && info.damage > 0f && info.procCoefficient > 0f)
		{
			BodyState bodyState = State(self.body);
			bodyState.ResetStage();
			if (self.body.GetBuffCount(WatchHits) < 25)
			{
				self.body.AddBuff(WatchHits);
			}
		}
		if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)self.body) && self.alive && info.damage > 0f)
		{
			Vulnerable component = ((Component)self).GetComponent<Vulnerable>();
			if (Object.op_Implicit((Object)(object)component) && component.Until > Time.fixedTime)
			{
				info.damage *= 1f + component.Bonus;
			}
			float num = Power(val, "AbyssalAdze");
			if (num > 0f && info.procCoefficient > 0f && self.combinedHealthFraction < 0.5f)
			{
				BodyState bodyState2 = State(val);
				if (++bodyState2.WoundedHits >= 10)
				{
					bodyState2.WoundedHits = 0;
					info.damage *= 1f + 0.5f * num;
				}
			}
		}
		orig.Invoke(self, info);
	}

	private void Hit(orig_OnHitEnemy orig, GlobalEventManager self, DamageInfo info, GameObject victim)
	{
		//IL_0165: Unknown result type (might be due to invalid IL or missing references)
		//IL_0200: Unknown result type (might be due to invalid IL or missing references)
		//IL_0207: Expected O, but got Unknown
		orig.Invoke(self, info, victim);
		if (!NetworkServer.active || info.rejected || info.procCoefficient <= 0f || !Object.op_Implicit((Object)(object)info.attacker) || !Object.op_Implicit((Object)(object)victim))
		{
			return;
		}
		CharacterBody component = info.attacker.GetComponent<CharacterBody>();
		CharacterBody component2 = victim.GetComponent<CharacterBody>();
		if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component2))
		{
			return;
		}
		float num = Power(component, "CorrosiveCore");
		if (num > 0f && info.crit)
		{
			component2.AddTimedBuff(Buffs.Slow50, Mathf.Min(12f, 2f + num));
		}
		float num2 = Power(component, "EnhancementVials");
		float num3 = Power(component, "LensOrrery");
		if (num2 <= 0f && num3 <= 0f)
		{
			return;
		}
		BodyState bodyState = State(component);
		if (num2 > 0f && Time.fixedTime >= bodyState.NextVial && Roll((5f + (float)Mathf.Min(20, ConsumedCount(component.inventory)) * 0.5f) * info.procCoefficient, component))
		{
			bodyState.NextVial = Time.fixedTime + 0.5f;
			Area(component, component2.corePosition, 10f, 2.5f * num2, 3f);
		}
		if (!(num3 > 0f) || info.crit || !(Time.fixedTime >= bodyState.NextOrrery) || !Roll(20f * num3 * info.procCoefficient, component))
		{
			return;
		}
		if (Items.TryGetValue("LensOrrery", out var value))
		{
			BuffDef val = (BuffDef)((object)value).GetType().GetProperty("OrreryDamageBonus", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).GetValue(value, null);
			LensOrrery val2 = (LensOrrery)(object)((value is LensOrrery) ? value : null);
			if (Object.op_Implicit((Object)(object)val) && val2 != null && val2.itemVariant.Value == 0 && component.GetBuffCount(val) < LensOrrery.buffStacksPerCount.Value * component.inventory.GetItemCountEffective(value.ItemDef))
			{
				component.AddBuff(val);
			}
		}
		bodyState.NextOrrery = Time.fixedTime + 0.1f;
	}

	private static int ConsumedCount(Inventory inventory)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		int num = 0;
		foreach (ItemIndex item in inventory.itemAcquisitionOrder)
		{
			ItemDef itemDef = ItemCatalog.GetItemDef(item);
			if (Object.op_Implicit((Object)(object)itemDef) && itemDef.isConsumed)
			{
				num += inventory.GetItemCountEffective(item);
			}
			if (num >= 20)
			{
				return 20;
			}
		}
		return num;
	}

	private void Fire(orig_FireProjectile_FireProjectileInfo orig, ProjectileManager self, FireProjectileInfo info)
	{
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		if (NetworkServer.active && Object.op_Implicit((Object)(object)info.projectilePrefab) && ((Object)info.projectilePrefab).name == "RocketProjectile" && Object.op_Implicit((Object)(object)info.owner))
		{
			CharacterBody component = info.owner.GetComponent<CharacterBody>();
			float num = Power(component, "ExtraterrestrialExhaust");
			if (num > 0f && Roll(15f * num, component))
			{
				info.damage *= 2f + 0.25f * num;
				if (Object.op_Implicit((Object)(object)largeRocket))
				{
					info.projectilePrefab = largeRocket;
				}
			}
		}
		orig.Invoke(self, info);
	}

	private void Death(DamageReport report)
	{
		if (!NetworkServer.active || !Object.op_Implicit((Object)(object)report.attackerBody) || !Object.op_Implicit((Object)(object)report.victimBody))
		{
			return;
		}
		CharacterBody attackerBody = report.attackerBody;
		float num = Power(attackerBody, "CryoCanister");
		float num2 = Power(attackerBody, "DashQuill");
		if (!(num <= 0f) || !(num2 <= 0f))
		{
			BodyState bodyState = State(attackerBody);
			if (num > 0f && (report.victimBody.HasBuff(Buffs.Slow50) || report.victimBody.HasBuff(Buffs.Slow80) || IsVanillaVoidSlowed(report.victimBody)))
			{
				bodyState.FrostUntil = Time.fixedTime + Mathf.Min(12f, 3f + num);
				bodyState.FrostRadius = Mathf.Min(20f, bodyState.FrostRadius + 2f);
			}
			if (num2 > 0f && Object.op_Implicit((Object)(object)attackerBody.characterMotor) && !attackerBody.characterMotor.isGrounded && (float)bodyState.AirRefunds < Mathf.Min(20f, 2f * num2))
			{
				bodyState.AirRefunds++;
				attackerBody.AddBuff(DashRefund);
			}
		}
	}

	internal static bool IsVanillaVoidSlowed(CharacterBody body)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < BuffCatalog.buffCount; i++)
		{
			BuffIndex val = (BuffIndex)i;
			if (body.HasBuff(val))
			{
				BuffDef buffDef = BuffCatalog.GetBuffDef(val);
				if (Object.op_Implicit((Object)(object)buffDef) && (((Object)buffDef).name.IndexOf("Slow", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)buffDef).name.IndexOf("Freeze", StringComparison.OrdinalIgnoreCase) >= 0))
				{
					return true;
				}
			}
		}
		return false;
	}

	internal static void Area(CharacterBody owner, Vector3 position, float radius, float coefficient, float slowDuration)
	{
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Expected O, but got Unknown
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Invalid comparison between Unknown and I4
		if (!NetworkServer.active || !Object.op_Implicit((Object)(object)owner) || !Object.op_Implicit((Object)(object)owner.teamComponent))
		{
			return;
		}
		List<CharacterBody> list = new List<CharacterBody>(CharacterBody.readOnlyInstancesList);
		foreach (CharacterBody item in list)
		{
			if (!Object.op_Implicit((Object)(object)item) || !Object.op_Implicit((Object)(object)item.healthComponent) || !item.healthComponent.alive || !Object.op_Implicit((Object)(object)item.teamComponent) || item.teamComponent.teamIndex == owner.teamComponent.teamIndex || (int)item.teamComponent.teamIndex == 0)
			{
				continue;
			}
			Vector3 val = item.corePosition - position;
			if (!(((Vector3)(ref val)).sqrMagnitude > radius * radius))
			{
				item.AddTimedBuff(Buffs.Slow50, slowDuration);
				if (coefficient > 0f)
				{
					HealthComponent healthComponent = item.healthComponent;
					DamageInfo val2 = new DamageInfo();
					val2.attacker = ((Component)owner).gameObject;
					val2.damage = owner.damage * coefficient;
					val2.position = item.corePosition;
					val2.procCoefficient = 0f;
					val2.damageColorIndex = (DamageColorIndex)9;
					healthComponent.TakeDamage(val2);
				}
			}
		}
	}

	private void Stats(CharacterBody body, StatHookEventArgs args)
	{
		int num = Highest(body, "ClockworkMechanism");
		if (num >= 0)
		{
			BodyState bodyState = State(body);
			bodyState.ResetStage();
			int[] array = new int[4] { 12, 15, 20, 25 };
			if (body.GetBuffCount(WatchHits) < array[num])
			{
				args.damageMultAdd += 0.1f * Power(body, "ClockworkMechanism");
			}
		}
	}

	private void Holdout(orig_Awake orig, HoldoutZoneController self)
	{
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Expected O, but got Unknown
		orig.Invoke(self);
		self.calcChargeRate += (CalcChargeRateDelegate)delegate(ref float rate)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Invalid comparison between Unknown and I4
			float num = 0f;
			foreach (CharacterBody readOnlyInstances in CharacterBody.readOnlyInstancesList)
			{
				if (Object.op_Implicit((Object)(object)readOnlyInstances) && readOnlyInstances.isPlayerControlled && Object.op_Implicit((Object)(object)readOnlyInstances.teamComponent) && (int)readOnlyInstances.teamComponent.teamIndex == 1 && self.IsBodyInChargingRadius(readOnlyInstances))
				{
					num += Power(readOnlyInstances, "CrystalLotus");
				}
			}
			rate *= 1f + Mathf.Min(2f, num * 0.2f);
		};
	}

	private void InstallSpecificHooks()
	{
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Expected O, but got Unknown
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Expected O, but got Unknown
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Expected O, but got Unknown
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Expected O, but got Unknown
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Expected O, but got Unknown
		//IL_0177: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Expected O, but got Unknown
		//IL_0166: Unknown result type (might be due to invalid IL or missing references)
		//IL_0170: Expected O, but got Unknown
		Assembly assembly = typeof(ItemBase).Assembly;
		MethodInfo method = assembly.GetType("vanillaVoid.Items.ExeBlade").GetMethod("ExeBladeExtraDeath", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		hooks.Add((IDisposable)new ILHook((MethodBase)method, (Manipulator)delegate(ILContext il)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(il);
			if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
			{
				(Instruction i) => i.OpCode == OpCodes.Ldfld && ((MemberReference)(FieldReference)i.Operand).Name == "victimIsElite"
			}))
			{
				throw new Exception("Blade elite condition not found");
			}
			val.Emit(OpCodes.Ldarg_1);
			val.EmitDelegate<Func<bool, DamageReport, bool>>((Func<bool, DamageReport, bool>)((bool elite, DamageReport r) => elite || (Object.op_Implicit((Object)(object)r.victimBody) && r.victimBody.isBoss && Power(r.attackerBody, "ExeBlade") > 0f)));
		}));
		MethodInfo method2 = assembly.GetType("vanillaVoid.Misc.ClutchNetBehavior").GetMethod("ServerClutchEffects", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		hooks.Add((IDisposable)new ILHook((MethodBase)method2, (Manipulator)delegate(ILContext il)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			ILCursor val = new ILCursor(il);
			int num2 = 0;
			while (val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1]
			{
				(Instruction i) => IsCall(i, "RoR2.HealthComponent", "TakeDamage")
			}))
			{
				val.EmitDelegate<Action<HealthComponent, DamageInfo>>((Action<HealthComponent, DamageInfo>)ClutchDamage);
				val.Remove();
				num2++;
			}
			if (num2 != 2)
			{
				throw new Exception("Expected both Clutch damage paths in Vanilla Void 1.7.2");
			}
		}));
		MethodInfo method3 = assembly.GetType("vanillaVoid.Items.VoidShell").GetMethod("<OverrideBatteryChargedEnter>b__51_2", BindingFlags.Instance | BindingFlags.NonPublic);
		hooks.Add((IDisposable)new Hook((MethodBase)method3, (Delegate)(ReplaceDelivery)delegate(OriginalDelivery orig, VoidShell self, bool original, Charged state)
		{
			bool result = orig(self, original, state);
			BonusDelivery(state);
			return result;
		}));
		Type type = assembly.GetType("vanillaVoid.Items.SwordToken");
		Type[] nestedTypes = type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic);
		foreach (Type type2 in nestedTypes)
		{
			MethodInfo method4 = type2.GetMethod("MoveNext", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method4 == null || type2.Name.IndexOf("ExeBladeDelayedExecutions", StringComparison.Ordinal) < 0)
			{
				continue;
			}
			hooks.Add((IDisposable)new ILHook((MethodBase)method4, (Manipulator)delegate(ILContext il)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Expected O, but got Unknown
				ILCursor val = new ILCursor(il);
				if (!val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1]
				{
					(Instruction i) => IsCall(i, "RoR2.HealthComponent", "TakeDamage")
				}))
				{
					throw new Exception("Blade burst damage call not found");
				}
				val.EmitDelegate<Action<HealthComponent, DamageInfo>>((Action<HealthComponent, DamageInfo>)delegate(HealthComponent target, DamageInfo info)
				{
					CharacterBody body = (Object.op_Implicit((Object)(object)info.attacker) ? info.attacker.GetComponent<CharacterBody>() : null);
					info.damage *= 1f + 0.25f * Power(body, "ExeBlade");
					target.TakeDamage(info);
				});
				val.Remove();
			}));
		}
	}

	private static bool IsCall(Instruction i, string type, string name)
	{
		object operand = i.Operand;
		MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null);
		return val != null && ((MemberReference)((MemberReference)val).DeclaringType).FullName == type && ((MemberReference)val).Name == name;
	}

	private static void ClutchDamage(HealthComponent target, DamageInfo info)
	{
		CharacterBody body = (Object.op_Implicit((Object)(object)info.attacker) ? info.attacker.GetComponent<CharacterBody>() : null);
		float num = Power(body, "VoidFin");
		if (NetworkServer.active && Object.op_Implicit((Object)(object)target) && num > 0f)
		{
			Vulnerable vulnerable = ((Component)target).GetComponent<Vulnerable>();
			if (!Object.op_Implicit((Object)(object)vulnerable))
			{
				vulnerable = ((Component)target).gameObject.AddComponent<Vulnerable>();
			}
			vulnerable.Bonus = Mathf.Max((vulnerable.Until > Time.fixedTime) ? vulnerable.Bonus : 0f, Mathf.Min(1f, 0.15f * num));
			vulnerable.Until = Time.fixedTime + 5f;
		}
		target.TakeDamage(info);
	}

	private static void BonusDelivery(Charged state)
	{
		//IL_01be: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0206: Unknown result type (might be due to invalid IL or missing references)
		//IL_020b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0210: Unknown result type (might be due to invalid IL or missing references)
		//IL_021a: Unknown result type (might be due to invalid IL or missing references)
		if (!NetworkServer.active || !Object.op_Implicit((Object)(object)((EntityState)state).outer) || !Object.op_Implicit((Object)(object)((Component)((EntityState)state).outer).gameObject.GetComponent(typeof(ItemBase).Assembly.GetType("vanillaVoid.Items.VoidShellIdentifierToken"))) || Object.op_Implicit((Object)(object)((Component)((EntityState)state).outer).gameObject.GetComponent<DeliveryDone>()))
		{
			return;
		}
		((Component)((EntityState)state).outer).gameObject.AddComponent<DeliveryDone>();
		if (!Object.op_Implicit((Object)(object)Run.instance) || !Items.TryGetValue("VoidShell", out var value))
		{
			return;
		}
		FieldInfo field = ((object)value).GetType().GetField("dropTable", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		object? value2 = field.GetValue(value);
		PickupDropTable val = (PickupDropTable)((value2 is PickupDropTable) ? value2 : null);
		if (!Object.op_Implicit((Object)(object)val))
		{
			return;
		}
		foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
		{
			if (!Object.op_Implicit((Object)(object)instance.master))
			{
				continue;
			}
			float num = Mathf.Min(300f, 50f * Power(instance.master.inventory, "VoidShell"));
			int num2 = (int)(num / 100f) + (Util.CheckRoll(num % 100f, instance.master) ? 1 : 0);
			for (int i = 0; i < num2; i++)
			{
				PickupIndex[] array = (PickupIndex[])((object)val).GetType().GetMethod("GenerateUniqueDropsPreReplacement", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Invoke(val, new object[2]
				{
					1,
					Run.instance.treasureRng
				});
				if (array != null && array.Length > 0 && array[0] != PickupIndex.none)
				{
					PickupDropletController.CreatePickupDroplet(new UniquePickup(array[0]), ((Component)((EntityState)state).outer).transform.position + Vector3.up * 3f, Vector3.up * 10f);
				}
			}
		}
	}

	private static string Description(string id, int tier)
	{
		float num = Strength[tier];
		return id switch
		{
			"AbyssalAdze" => "Every 10th proc-capable hit against an enemy below 50% health deals +" + 50f * num + "% total damage per stack of this quality.", 
			"ClockworkMechanism" => "+" + 10f * num + "% damage per stack until hit " + (new int[4] { 12, 15, 20, 25 })[tier] + " times this stage (highest quality determines hit limit).", 
			"EnhancementVials" => "5% proc-scaled chance on hit to burst for " + 250f * num + "% damage per stack, slowing enemies within 10m for 3s. +0.5% chance per consumed item, capped at +10%. Maximum 2 bursts/s; bursts cannot proc.", 
			"ExtraterrestrialExhaust" => 15f * num + "% chance per stack for a rocket to deal " + (2f + 0.25f * num) * 100f + "% of its normal damage. No extra rockets. Mixed qualities add their power.", 
			"CryoCanister" => "Killing slowed enemies creates a frost aura for " + Math.Min(12f, 3f + num) + "s. Deals " + 100f * num + "% damage per second per stack and slows. Kills grow radius from 6m up to 20m. No proc chains.", 
			"VoidShell" => 50f * num + "% chance per stack for an extra reward at each Cornucopia delivery. 100% guarantees one; capped at 3 extra rewards per player/delivery.", 
			"CorrosiveCore" => "Critical hits slow enemies for " + Math.Min(12f, 2f + num) + "s, enabling corrosion. Stacks extend duration, capped at 12s.", 
			"CrystalLotus" => "+" + 20f * num + "% holdout charging speed per stack while inside (team cap +200%). In special boss arenas, pulse every 15s within 20m: slow enemies for " + Math.Min(10f, 2f + num) + "s.", 
			"ExeBlade" => "Boss kills also trigger the blade. Its existing burst deals +" + 25f * num + "% damage per stack. Does not add extra death triggers beyond the item's normal behavior.", 
			"DashQuill" => "Airborne kills restore one used air dash, up to " + 2f * num + " per stack per airtime (cap 20). Landing resets the allowance.", 
			"VoidFin" => "Kicked enemies take +" + Math.Min(100f, 15f * num) + "% damage for 5s. Stacks raise the bonus, capped at +100%; repeated kicks refresh duration.", 
			"LensOrrery" => 20f * num + "% proc-scaled chance per stack for non-critical hits to add an extra Orrery damage stack. Maximum 10 triggers/s. Intended for original item variant 0.", 
			_ => "Consumed form retains its quality for restoration; no active quality bonus.", 
		};
	}
}
public sealed class Vulnerable : MonoBehaviour
{
	public float Bonus;

	public float Until;
}
public sealed class DeliveryDone : MonoBehaviour
{
}
public sealed class BodyState : MonoBehaviour
{
	private CharacterBody body;

	public int HitsTaken;

	public int WoundedHits;

	public int AirRefunds;

	public float NextVial;

	public float NextOrrery;

	public float FrostUntil;

	public float FrostRadius = 6f;

	private float nextPulse;

	private float nextLotus;

	private int stage = -1;

	private int seenRefunds;

	private void Awake()
	{
		body = ((Component)this).GetComponent<CharacterBody>();
		seenRefunds = (Object.op_Implicit((Object)(object)body) ? body.GetBuffCount(Plugin.DashRefund) : 0);
	}

	public void ResetStage()
	{
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		int num = (Object.op_Implicit((Object)(object)Run.instance) ? Run.instance.stageClearCount : (-1));
		if (stage != num)
		{
			stage = num;
			HitsTaken = 0;
			if (NetworkServer.active && Object.op_Implicit((Object)(object)body))
			{
				body.SetBuffCount(Plugin.WatchHits.buffIndex, 0);
			}
		}
	}

	private void FixedUpdate()
	{
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01da: Unknown result type (might be due to invalid IL or missing references)
		//IL_01df: Unknown result type (might be due to invalid IL or missing references)
		//IL_0273: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)body))
		{
			return;
		}
		int buffCount = body.GetBuffCount(Plugin.DashRefund);
		if (buffCount > seenRefunds && ((NetworkBehaviour)body).hasAuthority)
		{
			Component component = ((Component)body).GetComponent(typeof(ItemBase).Assembly.GetType("vanillaVoid.Items.DashQuill+AirdashToken"));
			if (Object.op_Implicit((Object)(object)component))
			{
				Type type = ((object)component).GetType();
				FieldInfo field = type.GetField("dashCurrent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo field2 = type.GetField("dashMax", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				field.SetValue(component, Math.Min((int)field2.GetValue(component), (int)field.GetValue(component) + buffCount - seenRefunds));
			}
		}
		seenRefunds = buffCount;
		if (!NetworkServer.active)
		{
			return;
		}
		if (Object.op_Implicit((Object)(object)body.characterMotor) && body.characterMotor.isGrounded)
		{
			AirRefunds = 0;
		}
		if (Time.fixedTime < nextPulse)
		{
			return;
		}
		nextPulse = Time.fixedTime + 0.5f;
		ResetStage();
		float num = Plugin.Power(body, "CryoCanister");
		if (num > 0f && FrostUntil > Time.fixedTime)
		{
			Plugin.Area(body, body.corePosition, FrostRadius, num * 0.5f, 1f);
		}
		else
		{
			FrostRadius = 6f;
		}
		num = Plugin.Power(body, "CrystalLotus");
		Scene activeScene = SceneManager.GetActiveScene();
		string name = ((Scene)(ref activeScene)).name;
		if (!(num > 0f) || !(Time.fixedTime >= nextLotus))
		{
			return;
		}
		switch (name)
		{
		default:
			if (!(name == "artifactworld"))
			{
				break;
			}
			goto case "moon2";
		case "moon2":
		case "limbo":
		case "voidraid":
		case "meridian":
			nextLotus = Time.fixedTime + 15f;
			Plugin.Area(body, body.corePosition, 20f, 0f, Mathf.Min(10f, 2f + num));
			break;
		}
	}
}
internal static class ScrapCompatibility
{
	private delegate bool OriginalScrappable(ItemIndex item);

	private delegate bool ReplacementScrappable(OriginalScrappable orig, ItemIndex item);

	public static void Install(List<IDisposable> hooks)
	{
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Expected O, but got Unknown
		//IL_010a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Expected O, but got Unknown
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: Expected O, but got Unknown
		if (!Chainloader.PluginInfos.TryGetValue("com.eviegc.MarkForScrap", out var value))
		{
			return;
		}
		MethodInfo method = ((object)value.Instance).GetType().Assembly.GetType("MarkForScrap.Utils.ItemUtils").GetMethod("IsScrappable", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		hooks.Add((IDisposable)new Hook((MethodBase)method, (Delegate)new ReplacementScrappable(IsScrappable)));
		string[] array = new string[2] { "MarkForScrap.InventoryScrapCounter", "MarkForScrap.MarkForScrapPlugin" };
		foreach (string name in array)
		{
			MethodInfo[] methods = ((object)value.Instance).GetType().Assembly.GetType(name).GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo methodInfo in methods)
			{
				if (methodInfo.Name != "SyncScrapCountWithInventory" && methodInfo.Name != "Interactor_PerformInteraction")
				{
					continue;
				}
				hooks.Add((IDisposable)new ILHook((MethodBase)methodInfo, (Manipulator)delegate(ILContext il)
				{
					//IL_0002: Unknown result type (might be due to invalid IL or missing references)
					//IL_0008: Expected O, but got Unknown
					ILCursor val = new ILCursor(il);
					while (val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1]
					{
						delegate(Instruction instruction)
						{
							object operand = instruction.Operand;
							MethodReference val2 = (MethodReference)((operand is MethodReference) ? operand : null);
							return val2 != null && ((MemberReference)val2).FullName == "System.Int32 RoR2.Inventory::GetItemCountPermanent(RoR2.ItemIndex)";
						}
					}))
					{
						val.Remove();
						val.EmitDelegate<Func<Inventory, ItemIndex, int>>((Func<Inventory, ItemIndex, int>)PhysicalCount);
					}
				}));
			}
		}
	}

	private static int PhysicalCount(Inventory inventory, ItemIndex index)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Invalid comparison between Unknown and I4
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Invalid comparison between Unknown and I4
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		int num = inventory.GetItemCountPermanent(index);
		ItemDef itemDef = ItemCatalog.GetItemDef(index);
		if (!Object.op_Implicit((Object)(object)itemDef) || !IsVoid(itemDef.tier) || (int)QualityCatalog.GetQualityTier(index) != -1)
		{
			return num;
		}
		for (int i = 0; i < 4; i++)
		{
			ItemIndex itemIndexOfQuality = QualityCatalog.GetItemIndexOfQuality(index, (QualityTier)i);
			if (itemIndexOfQuality != index && (int)itemIndexOfQuality != -1)
			{
				num -= inventory.GetItemCountPermanent(itemIndexOfQuality);
			}
		}
		return Math.Max(0, num);
	}

	private static bool IsScrappable(OriginalScrappable orig, ItemIndex index)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		ItemDef itemDef = ItemCatalog.GetItemDef(index);
		if (!Object.op_Implicit((Object)(object)itemDef))
		{
			return false;
		}
		if (!IsVoid(itemDef.tier))
		{
			return orig(index);
		}
		return itemDef.canRemove && !itemDef.ContainsTag((ItemTag)10) && !itemDef.ContainsTag((ItemTag)33);
	}

	private static bool IsVoid(ItemTier tier)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Invalid comparison between Unknown and I4
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Invalid comparison between Unknown and I4
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Invalid comparison between Unknown and I4
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Invalid comparison between Unknown and I4
		return (int)tier == 6 || (int)tier == 7 || (int)tier == 8 || (int)tier == 9;
	}

	public static IEnumerator LoadContent(QualityContentLoadArgs args)
	{
		string[] colors = new string[3] { "White", "Green", "Red" };
		try
		{
			string[] array = colors;
			foreach (string color in array)
			{
				string name = "Scrap" + color + "Suppressed";
				AsyncOperationHandle<ItemDef> handle = Addressables.LoadAssetAsync<ItemDef>((object)("RoR2/DLC1/ScrapVoid/" + name + ".asset"));
				yield return handle;
				if ((int)handle.Status != 1 || !Object.op_Implicit((Object)(object)handle.Result))
				{
					throw new InvalidOperationException("Could not load Void Scrap item " + name);
				}
				ItemDef item = handle.Result;
				string display = "Void Scrap (" + color + ")";
				LanguageAPI.Add(item.nameToken, display);
				LanguageAPI.Add(item.pickupToken, "Scrap from Void items. Accepted by the Void donation altar.");
				LanguageAPI.Add(item.descriptionToken, "Scrap from Void items. The Void donation altar consumes scrap before useful items. Each scrap counts as one item, regardless of quality.");
				Plugin.Groups[name] = args.CreateItemQualityGroup(item);
				for (int j = 0; j < 4; j++)
				{
					string text = "ITEM_" + name.ToUpperInvariant() + "_" + ((object)(QualityTier)j).ToString().ToUpperInvariant();
					LanguageAPI.Add(text + "_PICKUP", "{0}\nRetains the quality of the scrapped item.");
					LanguageAPI.Add(text + "_DESC", "{0}\n<sprite name=\"Quality\"> Retains the quality of the scrapped item. Quality does not multiply its donation value or guarantee a quality reward.");
				}
			}
		}
		finally
		{
		}
	}
}
internal static class ConsumableSupport
{
	private sealed class Transfer
	{
		public string Source;

		public readonly float[] Quantities = new float[5];

		public bool Temporary;
	}

	private static readonly ConditionalWeakTable<Inventory, Transfer> pending = new ConditionalWeakTable<Inventory, Transfer>();

	public static void Install(List<IDisposable> hooks)
	{
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: Expected O, but got Unknown
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Expected O, but got Unknown
		Type[] types = typeof(ItemBase).Assembly.GetTypes();
		foreach (Type type in types)
		{
			if (type.Name != "ClockworkMechanism" && type.Name != "EnhancementVials" && type.Name != "EmptyVials" && type.Name != "ShatteredVials")
			{
				continue;
			}
			MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo methodInfo in methods)
			{
				if (methodInfo.GetMethodBody() != null && !methodInfo.Name.StartsWith("Create") && !methodInfo.Name.StartsWith("get_") && !(methodInfo.Name == "Init") && !(methodInfo.Name == "Hooks"))
				{
					hooks.Add((IDisposable)new ILHook((MethodBase)methodInfo, new Manipulator(Patch)));
				}
			}
		}
	}

	private static void Patch(ILContext il)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Expected O, but got Unknown
		ILCursor val = new ILCursor(il);
		while (val.Next != null)
		{
			object operand = val.Next.Operand;
			MethodReference val2 = (MethodReference)((operand is MethodReference) ? operand : null);
			if (val2 == null || ((MemberReference)((MemberReference)val2).DeclaringType).FullName != "RoR2.Inventory")
			{
				val.Index += 1;
				continue;
			}
			string name = ((MemberReference)val2).Name;
			bool flag = val2.Parameters.Count > 0 && ((MemberReference)((ParameterReference)val2.Parameters[0]).ParameterType).FullName == "RoR2.ItemDef";
			bool flag2 = val2.Parameters.Count > 0 && ((MemberReference)((ParameterReference)val2.Parameters[0]).ParameterType).FullName == "RoR2.ItemIndex";
			if ((flag || flag2) && val2.Parameters.Count == 2 && ((MemberReference)((ParameterReference)val2.Parameters[1]).ParameterType).FullName == "System.Int32" && (name == "RemoveItemPermanent" || name == "GiveItemPermanent" || name == "GiveItem"))
			{
				val.Remove();
				if (name == "RemoveItemPermanent")
				{
					if (flag)
					{
						val.EmitDelegate<Action<Inventory, ItemDef, int>>((Action<Inventory, ItemDef, int>)delegate(Inventory inv, ItemDef item, int count)
						{
							//IL_0002: Unknown result type (might be due to invalid IL or missing references)
							Remove(inv, item.itemIndex, count);
						});
					}
					else
					{
						val.EmitDelegate<Action<Inventory, ItemIndex, int>>((Action<Inventory, ItemIndex, int>)Remove);
					}
				}
				else if (flag)
				{
					val.EmitDelegate<Action<Inventory, ItemDef, int>>((Action<Inventory, ItemDef, int>)delegate(Inventory inv, ItemDef item, int count)
					{
						//IL_0002: Unknown result type (might be due to invalid IL or missing references)
						Give(inv, item.itemIndex, count);
					});
				}
				else
				{
					val.EmitDelegate<Action<Inventory, ItemIndex, int>>((Action<Inventory, ItemIndex, int>)Give);
				}
			}
			else if (flag2 && name == "GetTempItemDecayValue")
			{
				val.Remove();
				val.EmitDelegate<Func<Inventory, ItemIndex, float>>((Func<Inventory, ItemIndex, float>)TempValue);
			}
			else if (flag2 && name == "RemoveItemTemp" && val2.Parameters.Count == 2 && ((MemberReference)((ParameterReference)val2.Parameters[1]).ParameterType).FullName == "System.Single")
			{
				val.Remove();
				val.EmitDelegate<Action<Inventory, ItemIndex, float>>((Action<Inventory, ItemIndex, float>)RemoveTemp);
			}
			else if (flag2 && name == "GiveItemTemp" && val2.Parameters.Count == 2 && ((MemberReference)((ParameterReference)val2.Parameters[1]).ParameterType).FullName == "System.Single")
			{
				val.Remove();
				val.EmitDelegate<Action<Inventory, ItemIndex, float>>((Action<Inventory, ItemIndex, float>)GiveTemp);
			}
			else
			{
				val.Index += 1;
			}
		}
	}

	private static string Group(ItemIndex index, out ItemQualityGroup group)
	{
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		foreach (KeyValuePair<string, ItemQualityGroup> group2 in Plugin.Groups)
		{
			if (group2.Key != "ClockworkMechanism" && group2.Key != "ConsumedClockworkMechanism" && group2.Key != "EnhancementVials" && group2.Key != "EmptyVials" && group2.Key != "ShatteredVials")
			{
				continue;
			}
			if (group2.Value.BaseItemIndex == index)
			{
				group = group2.Value;
				return group2.Key;
			}
			for (int i = 0; i < 4; i++)
			{
				if (group2.Value.GetItemIndex((QualityTier)i) == index)
				{
					group = group2.Value;
					return group2.Key;
				}
			}
		}
		group = null;
		return null;
	}

	private static bool IsPartner(string source, string target)
	{
		return (source == "ClockworkMechanism" && target == "ConsumedClockworkMechanism") || (source == "ConsumedClockworkMechanism" && target == "ClockworkMechanism") || (source == "EnhancementVials" && (target == "EmptyVials" || target == "ShatteredVials")) || (target == "EnhancementVials" && (source == "EmptyVials" || source == "ShatteredVials"));
	}

	private static void Remove(Inventory inv, ItemIndex item, int count)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: 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_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		pending.Remove(inv);
		ItemQualityGroup group;
		string text = Group(item, out group);
		if (text == null || count <= 0)
		{
			inv.RemoveItemPermanent(item, count);
			return;
		}
		int[] array = new int[5];
		int num = 0;
		for (int i = 1; i < 5; i++)
		{
			ItemIndex itemIndex = group.GetItemIndex((QualityTier)(i - 1));
			array[i] = ((item == group.BaseItemIndex || item == itemIndex) ? inv.GetItemCountPermanent(itemIndex) : 0);
			num += array[i];
		}
		array[0] = ((item == group.BaseItemIndex) ? Math.Max(0, inv.GetItemCountPermanent(item) - num) : 0);
		Transfer transfer = new Transfer();
		transfer.Source = text;
		Transfer transfer2 = transfer;
		for (int i = 0; i < 5; i++)
		{
			if (count <= 0)
			{
				break;
			}
			int num2 = Math.Min(count, array[i]);
			if (num2 > 0)
			{
				inv.RemoveItemPermanent(group.GetItemIndex((QualityTier)(i - 1)), num2);
				transfer2.Quantities[i] = num2;
				count -= num2;
			}
		}
		pending.Add(inv, transfer2);
	}

	private static void Give(Inventory inv, ItemIndex item, int count)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		ItemQualityGroup group;
		string target = Group(item, out group);
		if (pending.TryGetValue(inv, out var value) && !value.Temporary && IsPartner(value.Source, target))
		{
			pending.Remove(inv);
			for (int i = 0; i < 5; i++)
			{
				if (count <= 0)
				{
					break;
				}
				int num = Math.Min(count, (int)value.Quantities[i]);
				if (num > 0)
				{
					inv.GiveItemPermanent(group.GetItemIndex((QualityTier)(i - 1)), num);
					count -= num;
				}
			}
		}
		else
		{
			pending.Remove(inv);
		}
		if (count > 0)
		{
			inv.GiveItemPermanent(item, count);
		}
	}

	private static float TempValue(Inventory inv, ItemIndex item)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		if (Group(item, out var group) == null || item != group.BaseItemIndex)
		{
			return inv.GetTempItemDecayValue(item);
		}
		float num = 0f;
		for (int i = -1; i < 4; i++)
		{
			num += inv.GetTempItemDecayValue(group.GetItemIndex((QualityTier)i));
		}
		return num;
	}

	private static void RemoveTemp(Inventory inv, ItemIndex item, float amount)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		pending.Remove(inv);
		ItemQualityGroup group;
		string text = Group(item, out group);
		if (text == null)
		{
			inv.RemoveItemTemp(item, amount);
			return;
		}
		Transfer transfer = new Transfer();
		transfer.Source = text;
		transfer.Temporary = true;
		Transfer transfer2 = transfer;
		for (int i = 0; i < 5; i++)
		{
			if (!(amount > 0f))
			{
				break;
			}
			ItemIndex itemIndex = group.GetItemIndex((QualityTier)(i - 1));
			if (item == group.BaseItemIndex || item == itemIndex)
			{
				float num = Math.Min(amount, inv.GetTempItemDecayValue(itemIndex));
				if (num > 0f)
				{
					inv.RemoveItemTemp(itemIndex, num);
					transfer2.Quantities[i] = num;
					amount -= num;
				}
			}
		}
		pending.Add(inv, transfer2);
	}

	private static void GiveTemp(Inventory inv, ItemIndex item, float amount)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		ItemQualityGroup group;
		string target = Group(item, out group);
		if (pending.TryGetValue(inv, out var value) && value.Temporary && IsPartner(value.Source, target))
		{
			pending.Remove(inv);
			for (int i = 0; i < 5; i++)
			{
				if (!(amount > 0f))
				{
					break;
				}
				float num = Math.Min(amount, value.Quantities[i]);
				if (num > 0f)
				{
					inv.GiveItemTemp(group.GetItemIndex((QualityTier)(i - 1)), num);
					amount -= num;
				}
			}
		}
		else
		{
			pending.Remove(inv);
		}
		if (amount > 0f)
		{
			inv.GiveItemTemp(item, amount);
		}
	}
}

BepInEx/plugins/VanillaPlusPlus/Olligame.VoidDonation.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using BazaarIsMyHaven;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Mono.Cecil;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using MonoMod.RuntimeDetour;
using On.RoR2;
using PerClientSync;
using RoR2;
using TMPro;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace OlligameDonations;

public sealed class DonationLedger
{
	public readonly Dictionary<string, int> RunCounts = new Dictionary<string, int>();

	private readonly HashSet<string> visited = new HashSet<string>();

	public bool CanDonate(string key)
	{
		return !visited.Contains(key);
	}

	public int Price(string key, int initial)
	{
		RunCounts.TryGetValue(key, out var value);
		return (int)Math.Min(2147483647L, initial + 2L * (long)Math.Max(0, value));
	}

	public void Record(string key)
	{
		RunCounts.TryGetValue(key, out var value);
		RunCounts[key] = value + 1;
		visited.Add(key);
	}

	public void NewVisit()
	{
		visited.Clear();
	}

	public void NewRun()
	{
		visited.Clear();
		RunCounts.Clear();
	}

	public static List<int> PlanPayment(IDictionary<int, int> counts, Random random, int price = 2)
	{
		Dictionary<int, int> dictionary = new Dictionary<int, int>(counts);
		List<int> list = new List<int>();
		long num = 0L;
		foreach (int value in counts.Values)
		{
			num += Math.Max(0, value);
		}
		if (price < 1 || num < price)
		{
			return null;
		}
		for (int i = 0; i < price; i++)
		{
			int num2 = 0;
			foreach (int value2 in dictionary.Values)
			{
				num2 = checked(num2 + Math.Max(0, value2));
			}
			if (num2 == 0)
			{
				return null;
			}
			int num3 = random.Next(num2);
			int num4 = -1;
			foreach (KeyValuePair<int, int> item in dictionary)
			{
				if (num3 < item.Value)
				{
					num4 = item.Key;
					break;
				}
				num3 -= Math.Max(0, item.Value);
			}
			list.Add(num4);
			dictionary[num4]--;
		}
		return list;
	}

	public static List<int> PlanScrapFirst(IDictionary<int, int> counts, ISet<int> scrap, Random random, int price = 2)
	{
		Dictionary<int, int> dictionary = new Dictionary<int, int>(counts);
		List<int> list = new List<int>();
		long num = 0L;
		foreach (int value in counts.Values)
		{
			num += Math.Max(0, value);
		}
		if (price < 1 || num < price)
		{
			return null;
		}
		foreach (KeyValuePair<int, int> count in counts)
		{
			if (scrap.Contains(count.Key))
			{
				int num2 = Math.Min(price - list.Count, Math.Max(0, count.Value));
				for (int i = 0; i < num2; i++)
				{
					list.Add(count.Key);
				}
				dictionary[count.Key] -= num2;
				if (list.Count == price)
				{
					return list;
				}
			}
		}
		List<int> list2 = PlanPayment(dictionary, random, price - list.Count);
		if (list2 == null)
		{
			return null;
		}
		list.AddRange(list2);
		return list;
	}
}
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("Olligame.SeparateVoidDonation", "Separate Void Donation", "1.8.0")]
[BepInDependency("Def.BazaarIsMyHaven", "5.3.0")]
public sealed class VoidDonation : BaseUnityPlugin
{
	private readonly DonationLedger ledger = new DonationLedger();

	private readonly DonationLedger yellowLedger = new DonationLedger();

	private YellowDonationPrices yellowPricing;

	private DonationQuality qualityRewards;

	private BazaarPaymentFix paymentFix;

	private readonly Random random = new Random();

	private GameObject altar;

	private GameObject prefab;

	private bool attempted;

	private float nextCheck;

	private ConfigEntry<bool> customPlacement;

	private ConfigEntry<Vector3> yellowPosition;

	private ConfigEntry<Vector3> voidPosition;

	private ILHook placementHook;

	private void Awake()
	{
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Expected O, but got Unknown
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Expected O, but got Unknown
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Expected O, but got Unknown
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Expected O, but got Unknown
		paymentFix = new BazaarPaymentFix();
		VoidScrapSupport.Hook();
		VoidAltarText.Hook();
		yellowPricing = new YellowDonationPrices(yellowLedger);
		qualityRewards = new DonationQuality(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
		customPlacement = ((BaseUnityPlugin)this).Config.Bind<bool>("Placement", "UseSavedPositions", false, "Use positions saved with Page Down in the Bazaar. Applies next visit.");
		yellowPosition = ((BaseUnityPlugin)this).Config.Bind<Vector3>("Placement", "YellowPosition", Vector3.zero, "World position for the yellow donation altar.");
		voidPosition = ((BaseUnityPlugin)this).Config.Bind<Vector3>("Placement", "VoidPosition", Vector3.zero, "World position for the Void donation altar.");
		placementHook = new ILHook((MethodBase)typeof(BazaarDonate).GetMethod("SpawnDonateAltar", BindingFlags.Instance | BindingFlags.NonPublic), new Manipulator(PatchYellowPosition));
		PurchaseInteraction.OnInteractionBegin += new hook_OnInteractionBegin(Interact);
		PurchaseInteraction.GetInteractability += new hook_GetInteractability(Interactability);
		Run.onRunStartGlobal += RunStarted;
		Run.onRunDestroyGlobal += RunEnded;
		SceneManager.sceneLoaded += SceneLoaded;
		ModCompatibilityProperSave.Register("Olligame.VoidDonations", (Func<object>)Save, (Action<object>)Load);
		ModCompatibilityProperSave.Register("Olligame.YellowDonationPrices", (Func<object>)(() => new Dictionary<string, int>(yellowLedger.RunCounts)), (Action<object>)delegate(object data)
		{
			LoadCounts(yellowLedger, data);
		});
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Donation prices: yellow starts at 3, Void at 2; +2 per personal use; one per visit, no run cap.");
	}

	private void PatchYellowPosition(ILContext il)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Expected O, but got Unknown
		ILCursor val = new ILCursor(il);
		if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
		{
			delegate(Instruction instruction)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				object operand = instruction.Operand;
				MethodReference val2 = (MethodReference)((operand is MethodReference) ? operand : null);
				return instruction.OpCode == OpCodes.Newobj && val2 != null && ((MemberReference)((MemberReference)val2).DeclaringType).FullName == "UnityEngine.Vector3" && val2.Parameters.Count == 3;
			}
		}))
		{
			throw new InvalidOperationException("Could not find yellow altar spawn position; this add-on requires BazaarIsMyHaven 5.3.0.");
		}
		val.EmitDelegate<Func<Vector3, Vector3>>((Func<Vector3, Vector3>)((Vector3 original) => customPlacement.Value ? yellowPosition.Value : original));
	}

	private void SavePlacementAtHost()
	{
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: 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_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0161: Unknown result type (might be due to invalid IL or missing references)
		//IL_0187: Unknown result type (might be due to invalid IL or missing references)
		//IL_018c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0192: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_01af: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_0209: Unknown result type (might be due to invalid IL or missing references)
		//IL_0226: Unknown result type (might be due to invalid IL or missing references)
		//IL_0179: Unknown result type (might be due to invalid IL or missing references)
		//IL_017e: Unknown result type (might be due to invalid IL or missing references)
		if (!Input.GetKeyDown((KeyCode)281))
		{
			return;
		}
		if (!NetworkServer.active)
		{
			Chat.AddMessage("Only the host can place the donation altars.");
			return;
		}
		Scene activeScene = SceneManager.GetActiveScene();
		if (((Scene)(ref activeScene)).name != "bazaar")
		{
			Chat.AddMessage("Enter the Bazaar before placing the donation altars.");
			return;
		}
		CharacterBody val = null;
		foreach (LocalUser readOnlyLocalUsers in LocalUserManager.readOnlyLocalUsersList)
		{
			if (Object.op_Implicit((Object)(object)readOnlyLocalUsers.cachedBody))
			{
				val = readOnlyLocalUsers.cachedBody;
				break;
			}
		}
		if (!Object.op_Implicit((Object)(object)val))
		{
			Chat.AddMessage("Could not find your character. Spawn in, then press Page Down again.");
			((BaseUnityPlugin)this).Logger.LogWarning((object)"Page Down received, but no local character was available.");
			return;
		}
		Vector3 val2 = val.footPosition + Vector3.up * 2f;
		Vector3 down = Vector3.down;
		LayerIndex world = LayerIndex.world;
		RaycastHit val3 = default(RaycastHit);
		if (!Physics.Raycast(val2, down, ref val3, 8f, LayerMask.op_Implicit(((LayerIndex)(ref world)).mask), (QueryTriggerInteraction)1))
		{
			Chat.AddMessage("Stand near the floor, then press Page Down again.");
			return;
		}
		Vector3 val4 = Vector3.ProjectOnPlane(((Component)val).transform.right, Vector3.up);
		Vector3 val5 = ((Vector3)(ref val4)).normalized;
		if (((Vector3)(ref val5)).sqrMagnitude < 0.5f)
		{
			val5 = Vector3.right;
		}
		yellowPosition.Value = ((RaycastHit)(ref val3)).point - val5 * 3.5f;
		voidPosition.Value = ((RaycastHit)(ref val3)).point + val5 * 3.5f;
		customPlacement.Value = true;
		((BaseUnityPlugin)this).Config.Save();
		Chat.AddMessage("Both altar positions saved, 7 metres apart. Re-enter the Bazaar to apply (console: next_stage bazaar).");
		((BaseUnityPlugin)this).Logger.LogInfo((object)string.Concat("Saved altar positions: yellow=", yellowPosition.Value, ", void=", voidPosition.Value));
	}

	private void RunStarted(Run run)
	{
		ledger.NewRun();
		yellowLedger.NewRun();
		attempted = false;
	}

	private void RunEnded(Run run)
	{
		ledger.NewRun();
		yellowLedger.NewRun();
		altar = null;
		attempted = false;
	}

	private void SceneLoaded(Scene scene, LoadSceneMode mode)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Invalid comparison between Unknown and I4
		if ((int)mode == 0)
		{
			ledger.NewVisit();
			yellowLedger.NewVisit();
			altar = null;
			attempted = false;
			nextCheck = Time.unscaledTime + 1f;
		}
	}

	private object Save()
	{
		return new Dictionary<string, int>(ledger.RunCounts);
	}

	private void Load(object data)
	{
		LoadCounts(ledger, data);
	}

	private static void LoadCounts(DonationLedger target, object data)
	{
		if (!(data is Dictionary<string, int> dictionary))
		{
			return;
		}
		target.RunCounts.Clear();
		foreach (KeyValuePair<string, int> item in dictionary)
		{
			target.RunCounts[item.Key] = Math.Max(0, item.Value);
		}
	}

	public static string Key(PlayerCharacterMasterController player)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		NetworkUserId id = player.networkUser.id;
		return $"{id.value}/{id.strValue}/{id.subId}";
	}

	private bool Allowed(PlayerCharacterMasterController player)
	{
		return Object.op_Implicit((Object)(object)player) && Object.op_Implicit((Object)(object)player.networkUser) && ledger.CanDonate(Key(player));
	}

	private static bool IsVoid(ItemTier tier)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Invalid comparison between Unknown and I4
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Invalid comparison between Unknown and I4
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Invalid comparison between Unknown and I4
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Invalid comparison between Unknown and I4
		return (int)tier == 6 || (int)tier == 7 || (int)tier == 8 || (int)tier == 9;
	}

	private unsafe static Dictionary<int, int> Eligible(Inventory inventory)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Expected I4, but got Unknown
		Dictionary<int, int> dictionary = new Dictionary<int, int>();
		GenericStaticEnumerable<ItemIndex, AllItemsEnumerator> allItems = ItemCatalog.allItems;
		AllItemsEnumerator enumerator = allItems.GetEnumerator();
		try
		{
			while (((AllItemsEnumerator)(ref enumerator)).MoveNext())
			{
				ItemIndex current = ((AllItemsEnumerator)(ref enumerator)).Current;
				ItemDef itemDef = ItemCatalog.GetItemDef(current);
				if (!((Object)(object)itemDef == (Object)null) && (VoidScrapSupport.IsScrap(current) || (IsVoid(itemDef.tier) && itemDef.canRemove)) && !inventory.IsItemDisabled(current))
				{
					int num = DonationQuality.PermanentCount(inventory, current);
					if (num > 0)
					{
						dictionary[(int)current] = num;
					}
				}
			}
		}
		finally
		{
			((IDisposable)(*(AllItemsEnumerator*)(&enumerator))/*cast due to .constrained prefix*/).Dispose();
		}
		return dictionary;
	}

	private void Update()
	{
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_0128: Unknown result type (might be due to invalid IL or missing references)
		//IL_0170: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_015e: 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)
		//IL_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_017e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0185: Unknown result type (might be due to invalid IL or missing references)
		//IL_0249: Unknown result type (might be due to invalid IL or missing references)
		//IL_024e: Unknown result type (might be due to invalid IL or missing references)
		//IL_025e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0272: Unknown result type (might be due to invalid IL or missing references)
		//IL_0277: Unknown result type (might be due to invalid IL or missing references)
		SavePlacementAtHost();
		if (!NetworkServer.active || !Object.op_Implicit((Object)(object)Run.instance) || attempted || Object.op_Implicit((Object)(object)altar) || Time.unscaledTime < nextCheck)
		{
			return;
		}
		nextCheck = Time.unscaledTime + 1f;
		Scene activeScene = SceneManager.GetActiveScene();
		if (((Scene)(ref activeScene)).name != "bazaar")
		{
			return;
		}
		PurchaseInteraction val = null;
		PurchaseInteraction[] array = Object.FindObjectsOfType<PurchaseInteraction>();
		foreach (PurchaseInteraction val2 in array)
		{
			if (val2.displayNameToken == "NEWT_STATUE_NAME")
			{
				val = val2;
				break;
			}
		}
		if (!Object.op_Implicit((Object)(object)val))
		{
			return;
		}
		DonationPriceView.Attach(((Component)val).gameObject, yellowLedger, isVoid: false);
		DonationPriceView.AttachSigns(((Component)val).gameObject, yellowLedger, isVoid: false);
		attempted = true;
		try
		{
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				prefab = Addressables.LoadAssetAsync<GameObject>((object)"RoR2/DLC1/DeepVoidPortalBattery/DeepVoidPortalBattery.prefab").WaitForCompletion();
			}
			Vector3 val3 = (customPlacement.Value ? voidPosition.Value : (((Component)val).transform.position + ((Component)val).transform.right * 7f));
			altar = Object.Instantiate<GameObject>(prefab, val3, ((Component)val).transform.rotation);
			PurchaseInteraction val2 = altar.GetComponent<PurchaseInteraction>();
			val2.Networkcost = 0;
			val2.NetworkcostType = (CostTypeIndex)0;
			val2.NetworkdisplayNameToken = "<color=#FF7ACD>Void Donation Altar (scrap first)</color>";
			val2.NetworkcontextToken = "<color=#FF7ACD>Donate Void scrap/items (scrap first)</color>";
			val2.Networkavailable = true;
			altar.AddComponent<InstancedPurchase>().original.available = true;
			DonationPriceView.Attach(altar, ledger, isVoid: true);
			DonationRewardDisplay.Apply(altar, (Func<PlayerCharacterMasterController, Dictionary<PickupIndex, int>>)Preview);
			NetworkServer.Spawn(altar);
			VoidSignalBeam.Remove(altar);
			PriceSigns.Apply(altar, altar.transform.TransformPoint(new Vector3(1.5534f, 1.1769f, -0.1835f)), altar.transform.rotation * Quaternion.Euler(0f, 270f, 0f), 2, (CostTypeIndex)4);
			VoidAltarText.MarkPriceSign(altar);
			DonationPriceView.AttachSigns(altar, ledger, isVoid: true);
			foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
			{
				if (Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance.networkUser) && !Allowed(instance))
				{
					DisableFor(instance);
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Spawned separate Void altar beside the yellow altar.");
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)ex);
			if (Object.op_Implicit((Object)(object)altar))
			{
				NetworkServer.Destroy(altar);
			}
			altar = null;
		}
	}

	private Dictionary<PickupIndex, int> Reward()
	{
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)Run.instance))
		{
			return null;
		}
		List<PickupIndex> list = new List<PickupIndex>();
		list.AddRange(Run.instance.availableVoidTier1DropList);
		list.AddRange(Run.instance.availableVoidTier2DropList);
		list.AddRange(Run.instance.availableVoidTier3DropList);
		list.AddRange(Run.instance.availableVoidBossDropList);
		list.RemoveAll(delegate(PickupIndex pickup)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			PickupDef pickupDef = PickupCatalog.GetPickupDef(pickup);
			ItemDef val = ((pickupDef == null) ? null : ItemCatalog.GetItemDef(pickupDef.itemIndex));
			return (Object)(object)val == (Object)null || !IsVoid(val.tier);
		});
		if (list.Count == 0)
		{
			return null;
		}
		Dictionary<PickupIndex, int> dictionary = new Dictionary<PickupIndex, int>();
		dictionary.Add(list[random.Next(list.Count)], 1);
		return dictionary;
	}

	private Dictionary<PickupIndex, int> Preview(PlayerCharacterMasterController player)
	{
		return Allowed(player) ? Reward() : null;
	}

	private void DisableFor(PlayerCharacterMasterController player)
	{
		InstancedPurchase component = altar.GetComponent<InstancedPurchase>();
		component.GetOrCreate(player).available = false;
		InstancedPurchases.UpdatePlayer(altar, player);
		PriceSigns.HideFor(altar, player);
	}

	private Interactability Interactability(orig_GetInteractability orig, PurchaseInteraction self, Interactor activator)
	{
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		if (!NetworkServer.active || !Object.op_Implicit((Object)(object)altar) || (Object)(object)((Component)self).gameObject != (Object)(object)altar)
		{
			return orig.Invoke(self, activator);
		}
		CharacterBody val = (Object.op_Implicit((Object)(object)activator) ? ((Component)activator).GetComponent<CharacterBody>() : null);
		PlayerCharacterMasterController player = ((Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.master)) ? val.master.playerCharacterMasterController : null);
		if (!Allowed(player))
		{
			return (Interactability)0;
		}
		if (!Object.op_Implicit((Object)(object)val.inventory))
		{
			return (Interactability)1;
		}
		int num = ledger.Price(Key(player), 2);
		long num2 = 0L;
		foreach (int value in Eligible(val.inventory).Values)
		{
			num2 += value;
			if (num2 >= num)
			{
				return (Interactability)2;
			}
		}
		return (Interactability)1;
	}

	private void Interact(orig_OnInteractionBegin orig, PurchaseInteraction self, Interactor activator)
	{
		//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)altar) || (Object)(object)((Component)self).gameObject != (Object)(object)altar)
		{
			orig.Invoke(self, activator);
		}
		else
		{
			if (!NetworkServer.active)
			{
				return;
			}
			CharacterBody val = (Object.op_Implicit((Object)(object)activator) ? ((Component)activator).GetComponent<CharacterBody>() : null);
			PlayerCharacterMasterController val2 = ((Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.master)) ? val.master.playerCharacterMasterController : null);
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.inventory) || !Allowed(val2))
			{
				return;
			}
			Dictionary<int, int> dictionary = Eligible(val.inventory);
			HashSet<int> hashSet = new HashSet<int>();
			foreach (int key in dictionary.Keys)
			{
				if (VoidScrapSupport.IsScrap((ItemIndex)key))
				{
					hashSet.Add(key);
				}
			}
			List<int> list = DonationLedger.PlanScrapFirst(dictionary, hashSet, random, ledger.Price(Key(val2), 2));
			if (list == null)
			{
				return;
			}
			Dictionary<PickupIndex, int> dictionary2 = Reward();
			if (dictionary2 == null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"No enabled Void rewards; no items were taken.");
				return;
			}
			qualityRewards.Apply(dictionary2);
			foreach (int item in list)
			{
				val.inventory.RemoveItemPermanent((ItemIndex)item, 1);
			}
			ledger.Record(Key(val2));
			Helper.GivePickups(val, dictionary2, (Vector3?)(altar.transform.position + Vector3.up * 6f), false);
			DisableFor(val2);
			DonationRewardDisplay component = altar.GetComponent<DonationRewardDisplay>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.ShowNextReward(val2);
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Void donation completed; player's run count = " + ledger.RunCounts[Key(val2)]));
		}
	}

	private void OnDestroy()
	{
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Expected O, but got Unknown
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Expected O, but got Unknown
		if (yellowPricing != null)
		{
			yellowPricing.Dispose();
		}
		if (qualityRewards != null)
		{
			qualityRewards.Dispose();
		}
		if (paymentFix != null)
		{
			paymentFix.Dispose();
		}
		VoidAltarText.Unhook();
		VoidScrapSupport.Unhook();
		if (placementHook != null)
		{
			placementHook.Dispose();
		}
		PurchaseInteraction.OnInteractionBegin -= new hook_OnInteractionBegin(Interact);
		PurchaseInteraction.GetInteractability -= new hook_GetInteractability(Interactability);
		Run.onRunStartGlobal -= RunStarted;
		Run.onRunDestroyGlobal -= RunEnded;
		SceneManager.sceneLoaded -= SceneLoaded;
	}
}
public static class VoidScrapSupport
{
	public static bool IsScrap(ItemIndex item)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		ItemDef itemDef = ItemCatalog.GetItemDef(item);
		if ((Object)(object)itemDef == (Object)null)
		{
			return false;
		}
		string[] array = new string[3] { "ScrapWhiteSuppressed", "ScrapGreenSuppressed", "ScrapRedSuppressed" };
		foreach (string text in array)
		{
			if (((Object)itemDef).name == text || ((Object)itemDef).name == text + "Uncommon" || ((Object)itemDef).name == text + "Rare" || ((Object)itemDef).name == text + "Epic" || ((Object)itemDef).name == text + "Legendary")
			{
				return true;
			}
		}
		return false;
	}

	private static bool IsVoid(ItemTier tier)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Invalid comparison between Unknown and I4
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Invalid comparison between Unknown and I4
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Invalid comparison between Unknown and I4
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Invalid comparison between Unknown and I4
		return (int)tier == 6 || (int)tier == 7 || (int)tier == 8 || (int)tier == 9;
	}

	public static void Hook()
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Expected O, but got Unknown
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Expected O, but got Unknown
		PickupPickerController.GetGeneratedOptionsFromInteractor += new hook_GetGeneratedOptionsFromInteractor(Options);
		PickupCatalog.FindScrapIndexForItemTier += new hook_FindScrapIndexForItemTier(ScrapForTier);
	}

	public static void Unhook()
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Expected O, but got Unknown
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Expected O, but got Unknown
		PickupPickerController.GetGeneratedOptionsFromInteractor -= new hook_GetGeneratedOptionsFromInteractor(Options);
		PickupCatalog.FindScrapIndexForItemTier -= new hook_FindScrapIndexForItemTier(ScrapForTier);
	}

	private static PickupIndex ScrapForTier(orig_FindScrapIndexForItemTier orig, ItemTier tier)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Invalid comparison between Unknown and I4
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Invalid comparison between Unknown and I4
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Invalid comparison between Unknown and I4
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		if (IsVoid(tier))
		{
			string text = (((int)tier == 6) ? "ScrapWhiteSuppressed" : (((int)tier == 7) ? "ScrapGreenSuppressed" : "ScrapRedSuppressed"));
			ItemIndex val = ItemCatalog.FindItemIndex(text);
			if ((int)val != -1)
			{
				return PickupCatalog.FindPickupIndex(val);
			}
		}
		return orig.Invoke(tier);
	}

	private unsafe static List<Option> Options(orig_GetGeneratedOptionsFromInteractor orig, PickupPickerController self, Interactor activator)
	{
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Invalid comparison between Unknown and I4
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Invalid comparison between Unknown and I4
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Invalid comparison between Unknown and I4
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: 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)
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_0182: Unknown result type (might be due to invalid IL or missing references)
		//IL_0183: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0194: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01de: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		List<Option> list = orig.Invoke(self, activator);
		if (!NetworkServer.active || !Object.op_Implicit((Object)(object)((Component)self).GetComponent<ScrapperController>()) || !Object.op_Implicit((Object)(object)activator))
		{
			return list;
		}
		CharacterBody body = ((Component)activator).GetComponent<CharacterBody>();
		if (!Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)body.inventory) || body.inventory.inventoryDisabled)
		{
			return list;
		}
		if ((int)ItemCatalog.FindItemIndex("ScrapWhiteSuppressed") == -1 || (int)ItemCatalog.FindItemIndex("ScrapGreenSuppressed") == -1 || (int)ItemCatalog.FindItemIndex("ScrapRedSuppressed") == -1)
		{
			return list;
		}
		list.RemoveAll(delegate(Option option)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			PickupDef pickupDef = PickupCatalog.GetPickupDef(option.pickup.pickupIndex);
			ItemDef val = ((pickupDef == null) ? null : ItemCatalog.GetItemDef(pickupDef.itemIndex));
			return Object.op_Implicit((Object)(object)val) && IsVoid(val.tier) && !((UniquePickup)(ref option.pickup)).isTempItem && !option.pickup.isRental && DonationQuality.PermanentCount(body.inventory, val.itemIndex) < 1;
		});
		GenericStaticEnumerable<ItemIndex, AllItemsEnumerator> allItems = ItemCatalog.allItems;
		AllItemsEnumerator enumerator = allItems.GetEnumerator();
		try
		{
			while (((AllItemsEnumerator)(ref enumerator)).MoveNext())
			{
				ItemIndex current = ((AllItemsEnumerator)(ref enumerator)).Current;
				ItemDef itemDef = ItemCatalog.GetItemDef(current);
				if (Object.op_Implicit((Object)(object)itemDef) && IsVoid(itemDef.tier) && itemDef.canRemove && !itemDef.ContainsTag((ItemTag)10) && !itemDef.ContainsTag((ItemTag)33) && !body.inventory.IsItemDisabled(current) && DonationQuality.PermanentCount(body.inventory, current) >= 1)
				{
					PickupIndex pickup = PickupCatalog.FindPickupIndex(current);
					if (!(pickup == PickupIndex.none) && !list.Exists((Option option) => option.pickup.pickupIndex == pickup && !((UniquePickup)(ref option.pickup)).isTempItem && !option.pickup.isRental))
					{
						list.Add(new Option
						{
							available = true,
							pickup = new UniquePickup(pickup)
						});
					}
				}
			}
		}
		finally
		{
			((IDisposable)(*(AllItemsEnumerator*)(&enumerator))/*cast due to .constrained prefix*/).Dispose();
		}
		return list;
	}
}
public sealed class VoidPriceMarker : MonoBehaviour
{
}
public static class VoidAltarText
{
	private const string Marker = "OLLIGAME_VOID_PRICE_SIGN";

	public static void Hook()
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Expected O, but got Unknown
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Expected O, but got Unknown
		PurchaseInteraction.UpdateHologramContent += new hook_UpdateHologramContent(UpdateContent);
		CostHologramContent.FixedUpdate += new hook_FixedUpdate(UpdateText);
	}

	public static void Unhook()
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Expected O, but got Unknown
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Expected O, but got Unknown
		PurchaseInteraction.UpdateHologramContent -= new hook_UpdateHologramContent(UpdateContent);
		CostHologramContent.FixedUpdate -= new hook_FixedUpdate(UpdateText);
	}

	public static void MarkPriceSign(GameObject altar)
	{
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Expected O, but got Unknown
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Expected O, but got Unknown
		FieldInfo field = typeof(PriceSigns).GetField("signs", BindingFlags.Instance | BindingFlags.NonPublic);
		PriceSigns[] array = Object.FindObjectsOfType<PriceSigns>();
		foreach (PriceSigns obj in array)
		{
			IEnumerable enumerable = (IEnumerable)field.GetValue(obj);
			foreach (object item in enumerable)
			{
				Type type = item.GetType();
				if (!((Object)(GameObject)type.GetField("terminal", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(item) != (Object)(object)altar))
				{
					NetworkIdentity val = (NetworkIdentity)type.GetField("seer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(item);
					((Component)val).GetComponent<PurchaseInteraction>().NetworkdisplayNameToken = "OLLIGAME_VOID_PRICE_SIGN";
				}
			}
		}
	}

	private static void UpdateContent(orig_UpdateHologramContent orig, PurchaseInteraction self, GameObject content, Transform viewer)
	{
		orig.Invoke(self, content, viewer);
		if (self.displayNameToken == "OLLIGAME_VOID_PRICE_SIGN" && Object.op_Implicit((Object)(object)content) && !Object.op_Implicit((Object)(object)content.GetComponent<VoidPriceMarker>()))
		{
			content.AddComponent<VoidPriceMarker>();
		}
	}

	private static void UpdateText(orig_FixedUpdate orig, CostHologramContent self)
	{
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		orig.Invoke(self);
		if (Object.op_Implicit((Object)(object)((Component)self).GetComponent<VoidPriceMarker>()) && Object.op_Implicit((Object)(object)self.targetTextMesh))
		{
			((TMP_Text)self.targetTextMesh).text = "<color=#FF7ACD>" + self.displayValue + " Void scrap/items</color>";
			((Graphic)self.targetTextMesh).color = Color.white;
		}
	}
}
public sealed class YellowDonationPrices : IDisposable
{
	private delegate void OriginalInteraction(BazaarDonate donor, orig_OnInteractionBegin original, PurchaseInteraction purchase, Interactor activator);

	private delegate void ReplacementInteraction(OriginalInteraction original, BazaarDonate donor, orig_OnInteractionBegin chained, PurchaseInteraction purchase, Interactor activator);

	private delegate bool OriginalLimit(BazaarDonate donor, PlayerCharacterMasterController player);

	private delegate bool ReplacementLimit(OriginalLimit original, BazaarDonate donor, PlayerCharacterMasterController player);

	private readonly DonationLedger ledger;

	private readonly Hook interactionHook;

	private readonly Hook limitHook;

	public YellowDonationPrices(DonationLedger counts)
	{
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Expected O, but got Unknown
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Expected O, but got Unknown
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Expected O, but got Unknown
		ledger = counts;
		interactionHook = new Hook((MethodBase)typeof(BazaarDonate).GetMethod("PurchaseInteraction_OnInteractionBegin", BindingFlags.Instance | BindingFlags.NonPublic), (Delegate)new ReplacementInteraction(Interact));
		limitHook = new Hook((MethodBase)typeof(BazaarDonate).GetMethod("CanGetReward", BindingFlags.Instance | BindingFlags.NonPublic), (Delegate)new ReplacementLimit(CanGetReward));
		PurchaseInteraction.CanBeAffordedByInteractor += new hook_CanBeAffordedByInteractor(Affordable);
	}

	private static bool IsYellow(PurchaseInteraction self)
	{
		return NetworkServer.active && Object.op_Implicit((Object)(object)self) && self.displayNameToken == "NEWT_STATUE_NAME";
	}

	private static PlayerCharacterMasterController Player(Interactor activator)
	{
		CharacterBody val = (Object.op_Implicit((Object)(object)activator) ? ((Component)activator).GetComponent<CharacterBody>() : null);
		return (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.master)) ? val.master.playerCharacterMasterController : null;
	}

	private bool CanGetReward(OriginalLimit original, BazaarDonate donor, PlayerCharacterMasterController player)
	{
		return Object.op_Implicit((Object)(object)player) && Main.instance.GetPlayerStruct(player).RewardCount < 1;
	}

	private bool Affordable(orig_CanBeAffordedByInteractor original, PurchaseInteraction self, Interactor activator)
	{
		PlayerCharacterMasterController val = (IsYellow(self) ? Player(activator) : null);
		if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.networkUser))
		{
			return original.Invoke(self, activator);
		}
		int cost = self.cost;
		try
		{
			self.cost = ledger.Price(VoidDonation.Key(val), 3);
			return original.Invoke(self, activator);
		}
		finally
		{
			self.cost = cost;
		}
	}

	private void Interact(OriginalInteraction original, BazaarDonate donor, orig_OnInteractionBegin chained, PurchaseInteraction self, Interactor activator)
	{
		PlayerCharacterMasterController val = (IsYellow(self) ? Player(activator) : null);
		if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.networkUser))
		{
			original(donor, chained, self, activator);
			return;
		}
		PlayerStruct playerStruct = Main.instance.GetPlayerStruct(val);
		int rewardCount = playerStruct.RewardCount;
		int cost = self.cost;
		try
		{
			self.cost = ledger.Price(VoidDonation.Key(val), 3);
			original(donor, chained, self, activator);
			if (playerStruct.RewardCount > rewardCount)
			{
				ledger.Record(VoidDonation.Key(val));
			}
		}
		finally
		{
			self.cost = cost;
		}
	}

	public void Dispose()
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Expected O, but got Unknown
		PurchaseInteraction.CanBeAffordedByInteractor -= new hook_CanBeAffordedByInteractor(Affordable);
		interactionHook.Dispose();
		limitHook.Dispose();
	}
}
public sealed class DonationPriceView : InstancedPurchaseView
{
	public DonationLedger Ledger;

	public bool VoidAltar;

	private int realCost;

	private string realContext;

	private bool usedBase;

	private float nextRefresh;

	public override uint PrivateBits => 26u;

	protected override void Apply(NetworkConnection connection)
	{
		realCost = ((ClientView<PurchaseInteraction>)this).Component.cost;
		realContext = ((ClientView<PurchaseInteraction>)this).Component.contextToken;
		usedBase = (Object)(object)((Component)this).GetComponent<InstancedPurchase>() != (Object)null;
		if (usedBase)
		{
			((InstancedPurchaseView)this).Apply(connection);
		}
		ApplyPersonal(PerClient.GetPlayer(connection));
	}

	protected override void Restore()
	{
		if (usedBase)
		{
			((InstancedPurchaseView)this).Restore();
		}
		((ClientView<PurchaseInteraction>)this).Component.cost = realCost;
		((ClientView<PurchaseInteraction>)this).Component.contextToken = realContext;
	}

	private void ApplyPersonal(PlayerCharacterMasterController player)
	{
		if (Ledger != null && Object.op_Implicit((Object)(object)player) && Object.op_Implicit((Object)(object)player.networkUser))
		{
			int num = Ledger.Price(VoidDonation.Key(player), VoidAltar ? 2 : 3);
			((ClientView<PurchaseInteraction>)this).Component.cost = num;
			((ClientView<PurchaseInteraction>)this).Component.contextToken = (VoidAltar ? ("<color=#FF7ACD>Donate " + num + " Void scrap/items (scrap first)</color>") : ("Donate " + num + " yellow items for 1 yellow item"));
		}
	}

	private void LateUpdate()
	{
		if (!NetworkServer.active || Ledger == null)
		{
			return;
		}
		foreach (LocalUser readOnlyLocalUsers in LocalUserManager.readOnlyLocalUsersList)
		{
			if (Object.op_Implicit((Object)(object)readOnlyLocalUsers.cachedMasterController))
			{
				ApplyPersonal(readOnlyLocalUsers.cachedMasterController);
				break;
			}
		}
		if (Time.unscaledTime >= nextRefresh)
		{
			nextRefresh = Time.unscaledTime + 0.5f;
			((ClientView)this).SetDirtyForAll(((ClientView)this).PrivateBits);
		}
	}

	public static void Attach(GameObject target, DonationLedger ledger, bool isVoid)
	{
		if (!Object.op_Implicit((Object)(object)target.GetComponent<DonationPriceView>()))
		{
			InstancedPurchaseView component = target.GetComponent<InstancedPurchaseView>();
			if (Object.op_Implicit((Object)(object)component))
			{
				((Behaviour)component).enabled = false;
			}
			DonationPriceView donationPriceView = target.AddComponent<DonationPriceView>();
			donationPriceView.Ledger = ledger;
			donationPriceView.VoidAltar = isVoid;
			InstancedPurchase component2 = target.GetComponent<InstancedPurchase>();
			if (Object.op_Implicit((Object)(object)component2))
			{
				typeof(InstancedPurchase).GetField("purchaseView", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(component2, donationPriceView);
			}
			((ClientView)donationPriceView).SetDirtyForAll(((ClientView)donationPriceView).PrivateBits);
		}
	}

	public static void AttachSigns(GameObject altar, DonationLedger ledger, bool isVoid)
	{
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Expected O, but got Unknown
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Expected O, but got Unknown
		FieldInfo field = typeof(PriceSigns).GetField("signs", BindingFlags.Instance | BindingFlags.NonPublic);
		PriceSigns[] array = Object.FindObjectsOfType<PriceSigns>();
		foreach (PriceSigns obj in array)
		{
			foreach (object item in (IEnumerable)field.GetValue(obj))
			{
				Type type = item.GetType();
				if (!((Object)(GameObject)type.GetField("terminal", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(item) != (Object)(object)altar))
				{
					NetworkIdentity val = (NetworkIdentity)type.GetField("seer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(item);
					Attach(((Component)val).gameObject, ledger, isVoid);
				}
			}
		}
	}
}
public static class DonationQualityRoll
{
	public static int Select(double chancePercent, double chanceRoll, double tierRoll)
	{
		if (double.IsNaN(chancePercent) || chanceRoll >= Math.Max(0.0, Math.Min(100.0, chancePercent)) / 100.0)
		{
			return -1;
		}
		return (!(tierRoll < 0.7)) ? ((tierRoll < 0.9) ? 1 : ((tierRoll < 0.98) ? 2 : 3)) : 0;
	}
}
public sealed class DonationQuality : IDisposable
{
	private readonly ConfigEntry<float> chance;

	private readonly ManualLogSource log;

	private readonly Random random = new Random();

	private MethodInfo getQuality;

	private MethodInfo withQuality;

	private Type tierType;

	private ILHook yellowHook;

	private bool warned;

	private static MethodInfo itemQuality;

	private static MethodInfo itemVariant;

	private static Type qualityEnum;

	public static int PermanentCount(Inventory inventory, ItemIndex index)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Invalid comparison between Unknown and I4
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		int num = inventory.GetItemCountPermanent(index);
		if (itemQuality == null || itemVariant == null || Convert.ToInt32(itemQuality.Invoke(null, new object[1] { index })) != -1)
		{
			return num;
		}
		for (int i = 0; i < 4; i++)
		{
			ItemIndex val = (ItemIndex)itemVariant.Invoke(null, new object[2]
			{
				index,
				Enum.ToObject(qualityEnum, i)
			});
			if ((int)val != -1 && val != index)
			{
				num -= inventory.GetItemCountPermanent(val);
			}
		}
		return Math.Max(0, num);
	}

	public DonationQuality(ConfigFile config, ManualLogSource logger)
	{
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Expected O, but got Unknown
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d7: Expected O, but got Unknown
		//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dc: Expected O, but got Unknown
		log = logger;
		chance = config.Bind<float>("Rewards", "QualityChancePercent", 5f, new ConfigDescription("Chance per donated reward item to gain quality. Both altars. Quality levels: 70% Uncommon, 20% Rare, 8% Epic, 2% Legendary. Requires the Quality mod.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[0]));
		Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
		foreach (Assembly assembly in assemblies)
		{
			Type type = assembly.GetType("ItemQualities.QualityCatalog");
			if (!(type == null))
			{
				tierType = assembly.GetType("ItemQualities.QualityTier");
				getQuality = type.GetMethod("GetQualityTier", new Type[1] { typeof(PickupIndex) });
				withQuality = type.GetMethod("GetPickupIndexOfQuality", new Type[2]
				{
					typeof(PickupIndex),
					tierType
				});
				itemQuality = type.GetMethod("GetQualityTier", new Type[1] { typeof(ItemIndex) });
				itemVariant = type.GetMethod("GetItemIndexOfQuality", new Type[2]
				{
					typeof(ItemIndex),
					tierType
				});
				qualityEnum = tierType;
				break;
			}
		}
		if (getQuality == null || withQuality == null)
		{
			log.LogWarning((object)"Quality mod API unavailable; donation rewards remain ordinary.");
			return;
		}
		yellowHook = new ILHook((MethodBase)typeof(BazaarDonate).GetMethod("PurchaseInteraction_OnInteractionBegin", BindingFlags.Instance | BindingFlags.NonPublic), new Manipulator(PatchYellow));
		log.LogInfo((object)("Both donation altars have a " + chance.Value + "% quality chance per reward item."));
	}

	private void PatchYellow(ILContext il)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Expected O, but got Unknown
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		ILCursor val = new ILCursor(il);
		if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
		{
			delegate(Instruction instruction)
			{
				object operand = instruction.Operand;
				MethodReference val3 = (MethodReference)((operand is MethodReference) ? operand : null);
				return val3 != null && ((MemberReference)((MemberReference)val3).DeclaringType).FullName == "BazaarIsMyHaven.Helper" && ((MemberReference)val3).Name == "PayCost";
			}
		}))
		{
			throw new InvalidOperationException("Yellow donation payment call not found.");
		}
		VariableDefinition val2 = il.Body.Variables[3];
		if (((MemberReference)((VariableReference)val2).VariableType).FullName != "System.Collections.Generic.Dictionary`2<RoR2.PickupIndex,System.Int32>")
		{
			throw new InvalidOperationException("Yellow reward local changed; expected BazaarIsMyHaven 5.3.0.");
		}
		val.Emit(OpCodes.Ldloc, val2);
		val.EmitDelegate<Action<Dictionary<PickupIndex, int>>>((Action<Dictionary<PickupIndex, int>>)Apply);
	}

	public void Apply(Dictionary<PickupIndex, int> rewards)
	{
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Invalid comparison between Unknown and I4
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: Unknown result type (might be due to invalid IL or missing references)
		//IL_015e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: 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_014d: 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)
		if (!NetworkServer.active || rewards == null || withQuality == null || chance.Value <= 0f)
		{
			return;
		}
		try
		{
			Dictionary<PickupIndex, int> dictionary = new Dictionary<PickupIndex, int>();
			foreach (KeyValuePair<PickupIndex, int> reward in rewards)
			{
				PickupDef pickupDef = PickupCatalog.GetPickupDef(reward.Key);
				bool flag = pickupDef != null && (int)pickupDef.itemIndex != -1 && Convert.ToInt32(getQuality.Invoke(null, new object[1] { reward.Key })) == -1;
				for (int i = 0; i < reward.Value; i++)
				{
					PickupIndex val = reward.Key;
					int num = (flag ? DonationQualityRoll.Select(chance.Value, random.NextDouble(), random.NextDouble()) : (-1));
					if (num >= 0)
					{
						PickupIndex val2 = (PickupIndex)withQuality.Invoke(null, new object[2]
						{
							val,
							Enum.ToObject(tierType, num)
						});
						if (val2 != PickupIndex.none && PickupCatalog.GetPickupDef(val2) != null)
						{
							val = val2;
						}
					}
					dictionary.TryGetValue(val, out var value);
					dictionary[val] = value + 1;
				}
			}
			rewards.Clear();
			foreach (KeyValuePair<PickupIndex, int> item in dictionary)
			{
				rewards.Add(item.Key, item.Value);
			}
		}
		catch (Exception ex)
		{
			if (!warned)
			{
				warned = true;
				log.LogWarning((object)("Quality roll failed; keeping original donation reward. " + ex));
			}
		}
	}

	public void Dispose()
	{
		if (yellowHook != null)
		{
			yellowHook.Dispose();
		}
	}
}
public sealed class BazaarPaymentFix : IDisposable
{
	private readonly ILHook hook;

	public BazaarPaymentFix()
	{
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Expected O, but got Unknown
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Expected O, but got Unknown
		if (typeof(Helper).GetMethod("PayCostWithCompleteContext", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) != null)
		{
			return;
		}
		hook = new ILHook((MethodBase)typeof(Helper).GetMethod("PayCost", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic), (Manipulator)delegate(ILContext il)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			ILCursor val = new ILCursor(il);
			if (!val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1]
			{
				delegate(Instruction instruction)
				{
					object operand = instruction.Operand;
					MethodReference val2 = (MethodReference)((operand is MethodReference) ? operand : null);
					return val2 != null && ((MemberReference)((MemberReference)val2).DeclaringType).FullName == "RoR2.CostTypeDef" && ((MemberReference)val2).Name == "PayCost" && val2.Parameters.Count == 5;
				}
			}))
			{
				throw new InvalidOperationException("Bazaar payment call changed; expected BazaarIsMyHaven 5.3.0.");
			}
			val.Remove();
			val.EmitDelegate<Func<CostTypeDef, int, Interactor, GameObject, Xoroshiro128Plus, ItemIndex, PayCostResults>>((Func<CostTypeDef, int, Interactor, GameObject, Xoroshiro128Plus, ItemIndex, PayCostResults>)Pay);
		});
	}

	private static PayCostResults Pay(CostTypeDef definition, int cost, Interactor activator, GameObject purchased, Xoroshiro128Plus rng, ItemIndex avoided)
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Expected O, but got Unknown
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Expected O, but got Unknown
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		CharacterBody val = (Object.op_Implicit((Object)(object)activator) ? ((Component)activator).GetComponent<CharacterBody>() : null);
		PayCostResults val2 = new PayCostResults();
		PayCostContext val3 = new PayCostContext();
		val3.costTypeDef = definition;
		val3.cost = cost;
		val3.activator = activator;
		val3.purchasedObject = purchased;
		val3.rng = rng;
		val3.avoidedItemIndex = avoided;
		val3.activatorBody = val;
		val3.activatorMaster = (Object.op_Implicit((Object)(object)val) ? val.master : null);
		val3.activatorInventory = (Object.op_Implicit((Object)(object)val) ? val.inventory : null);
		val3.purchaseInteraction = (Object.op_Implicit((Object)(object)purchased) ? purchased.GetComponent<PurchaseInteraction>() : null);
		val3.results = val2;
		PayCostContext val4 = val3;
		definition.PayCost(val4, val2);
		return val2;
	}

	public void Dispose()
	{
		if (hook != null)
		{
			hook.Dispose();
		}
	}
}