Decompiled source of Ror2Meeeee v0.10.4

Ror2Meeeee.Core.dll

Decompiled 13 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using Microsoft.CodeAnalysis;
using Ror2Meeeee.Core.Eligibility;
using Ror2Meeeee.Core.Pipeline;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Ror2Meeeee.Core")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+47d3711113ead05e4a0dd86c182991233f903141")]
[assembly: AssemblyProduct("Ror2Meeeee.Core")]
[assembly: AssemblyTitle("Ror2Meeeee.Core")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Ror2Meeeee
{
	public static class ModInfo
	{
		public const string Guid = "com.sawcunha.ror2meeeee";

		public const string Name = "Ror2Meeeee";

		public const string Version = "0.10.4";

		public const string ExpectedGameVersion = "1.5.0#1224";
	}
}
namespace Ror2Meeeee.Core.Tax
{
	public static class TaxRelief
	{
		public const int WhitePercent = 20;

		public const int GreenPercent = 30;

		public const int RedPercent = 50;

		public const int WhiteGoldPercent = 10;

		public const int GreenGoldPercent = 20;

		public const int RedGoldPercent = 30;

		public static float Multiplier(bool white, bool green, bool red)
		{
			int num = (white ? 20 : 0) + (green ? 30 : 0) + (red ? 50 : 0);
			return (float)(100 - num) / 100f;
		}

		public static uint Gold(uint amount, bool white, bool green, bool red)
		{
			int num = (white ? 10 : 0) + (green ? 20 : 0) + (red ? 30 : 0);
			if (num == 0 || amount == 0)
			{
				return amount;
			}
			ulong num2 = (ulong)(amount * (100 + num) + 50) / 100uL;
			if (num2 <= uint.MaxValue)
			{
				return (uint)num2;
			}
			return uint.MaxValue;
		}
	}
}
namespace Ror2Meeeee.Core.Stats
{
	public static class Bastion
	{
		public const float ShieldPerStack = 0.4f;

		public const float RegenDelaySeconds = 2f;

		public static float ExtraShield(float maxHealth, int stacks)
		{
			if (stacks > 0 && !(maxHealth <= 0f))
			{
				return maxHealth * 0.4f * (float)stacks;
			}
			return 0f;
		}

		public static bool ShouldForceRegen(float timeSinceLastHit, float shield, float maxShield)
		{
			if (maxShield > 0f && shield < maxShield)
			{
				return timeSinceLastHit >= 2f;
			}
			return false;
		}
	}
	public static class HeavyHeart
	{
		public const float HealthPerStack = 0.5f;

		public const float DamageTakenPerStack = 0.3f;

		public const double MaxMultiplier = 1E+30;

		public static float HealthMultiplier(int stacks)
		{
			return Compound(1.5, stacks);
		}

		public static float DamageTakenMultiplier(int stacks)
		{
			return Compound(1.300000011920929, stacks);
		}

		private static float Compound(double factor, int stacks)
		{
			if (stacks <= 0)
			{
				return 1f;
			}
			double num = Math.Pow(factor, stacks);
			return (float)((num < 1E+30) ? num : 1E+30);
		}
	}
	public static class MultiShot
	{
		public static int ExtraShots(int stacks, int maxExtra)
		{
			if (stacks <= 0 || maxExtra <= 0)
			{
				return 0;
			}
			if (stacks >= maxExtra)
			{
				return maxExtra;
			}
			return stacks;
		}

		public static float FanAngle(int index, float step)
		{
			if (index < 0)
			{
				return 0f;
			}
			int num = index / 2 + 1;
			return ((index % 2 == 0) ? 1f : (-1f)) * (float)num * step;
		}

		public static int Budget(int wanted, int usedThisFrame, int maxPerFrame)
		{
			int num = maxPerFrame - usedThisFrame;
			if (wanted <= 0 || num <= 0)
			{
				return 0;
			}
			if (wanted >= num)
			{
				return num;
			}
			return wanted;
		}
	}
	public static class PortalBattery
	{
		public const float ChargePerStack = 0.1f;

		public static float ChargeRateMultiplier(int teamStacks)
		{
			if (teamStacks > 0)
			{
				return 1f + 0.1f * (float)teamStacks;
			}
			return 1f;
		}
	}
	public static class SelfHeal
	{
		public const float SelfishFlat = 5f;

		public const float SelfishPerStack = 0.0001f;

		public const float VoidFlat = 15f;

		public const float VoidPerStack = 0.005f;

		public const float LevelScaling = 0.2f;

		public static float PerSecond(int stacks, float flat, float perExtraStack, float fullHealth, float level)
		{
			if (stacks <= 0)
			{
				return 0f;
			}
			float num = ((level < 1f) ? 1f : level);
			return flat * (1f + 0.2f * (num - 1f)) + perExtraStack * (float)(stacks - 1) * fullHealth;
		}

		public static float AmountPerTick(int selfish, int voidStacks, float fullHealth, float level, float interval)
		{
			if (interval <= 0f)
			{
				return 0f;
			}
			return (PerSecond(selfish, 5f, 0.0001f, fullHealth, level) + PerSecond(voidStacks, 15f, 0.005f, fullHealth, level)) * interval;
		}
	}
	public static class ShortNumber
	{
		private static readonly CultureInfo Pt = CultureInfo.GetCultureInfo("pt-BR");

		private static readonly (double Div, string Suffix)[] Steps = new(double, string)[4]
		{
			(1000000000000.0, " tri"),
			(1000000000.0, " bi"),
			(1000000.0, " mi"),
			(1000.0, " mil")
		};

		public static string Format(double value)
		{
			double num = ((value < 0.0) ? (0.0 - value) : value);
			(double, string)[] steps = Steps;
			for (int i = 0; i < steps.Length; i++)
			{
				var (num2, text) = steps[i];
				if (num >= num2)
				{
					return (value / num2).ToString("0.#", Pt) + text;
				}
			}
			return value.ToString("0", Pt);
		}
	}
	public static class SpeedToDamage
	{
		public const float FirstStackRatio = 1f;

		public const float ExtraStackRatio = 0.5f;

		public static float Ratio(int stacks)
		{
			if (stacks > 0)
			{
				return 1f + 0.5f * (float)(stacks - 1);
			}
			return 0f;
		}

		public static bool Convert(float moveSpeed, float neutralSpeed, float damage, int stacks, out float newSpeed, out float newDamage)
		{
			newSpeed = moveSpeed;
			newDamage = damage;
			if (stacks <= 0 || !(neutralSpeed > 0f) || !(moveSpeed > neutralSpeed) || float.IsInfinity(moveSpeed) || float.IsNaN(damage))
			{
				return false;
			}
			float num = moveSpeed / neutralSpeed - 1f;
			newSpeed = neutralSpeed;
			newDamage = damage * (1f + num * Ratio(stacks));
			return true;
		}
	}
	public static class StatPool
	{
		public const float MaxCombined = 1E+09f;

		public static float ClampScale(float maxHealth, float maxShield)
		{
			float num = maxHealth + maxShield;
			if (!(num > 1E+09f) || !(num > 0f))
			{
				return 1f;
			}
			return 1E+09f / num;
		}

		public static float Adjust(float current, float previousMax, float newMax)
		{
			float num = newMax - previousMax;
			float num2 = ((num > 0f) ? (current + num) : current);
			if (!(num2 < newMax))
			{
				return newMax;
			}
			return num2;
		}
	}
}
namespace Ror2Meeeee.Core.Spend
{
	public readonly struct SpendRow
	{
		public int Id { get; }

		public string Name { get; }

		public int Purchases { get; }

		public long Gold { get; }

		public SpendRow(int id, string name, int purchases, long gold)
		{
			Id = id;
			Name = name;
			Purchases = purchases;
			Gold = gold;
		}
	}
	public sealed class SpendLedger
	{
		private sealed class Entry
		{
			public string Name;

			public int Purchases;

			public long Gold;
		}

		private readonly Dictionary<int, Entry> _byId = new Dictionary<int, Entry>();

		public int Players => _byId.Count;

		public bool Knows(int id)
		{
			return _byId.ContainsKey(id);
		}

		public void Add(int id, Func<string> name, long gold)
		{
			if (!_byId.TryGetValue(id, out var value))
			{
				value = new Entry
				{
					Name = (name() ?? ("#" + id.ToString(CultureInfo.InvariantCulture)))
				};
				_byId[id] = value;
			}
			value.Purchases++;
			if (gold > 0)
			{
				value.Gold = ((long.MaxValue - value.Gold < gold) ? long.MaxValue : (value.Gold + gold));
			}
		}

		public void Clear()
		{
			_byId.Clear();
		}

		public SpendRow[] Snapshot()
		{
			SpendRow[] array = new SpendRow[_byId.Count];
			int num = 0;
			foreach (KeyValuePair<int, Entry> item in _byId)
			{
				array[num++] = new SpendRow(item.Key, item.Value.Name, item.Value.Purchases, item.Value.Gold);
			}
			Array.Sort(array, (SpendRow a, SpendRow b) => b.Gold.CompareTo(a.Gold));
			return array;
		}

		public static string Format(SpendRow[] rows)
		{
			if (rows.Length == 0)
			{
				return "Nenhuma compra registrada nesta run.";
			}
			StringBuilder stringBuilder = new StringBuilder("Jogador | Compras | Ouro gasto");
			long num = 0L;
			for (int i = 0; i < rows.Length; i++)
			{
				SpendRow spendRow = rows[i];
				stringBuilder.Append('\n').Append(spendRow.Name).Append(" | ")
					.Append(spendRow.Purchases)
					.Append(" | ")
					.Append(spendRow.Gold);
				num += spendRow.Gold;
			}
			stringBuilder.Append("\nTotal | | ").Append(num);
			return stringBuilder.ToString();
		}
	}
}
namespace Ror2Meeeee.Core.RustyNail
{
	public static class RustyNailRules
	{
		public const float ChanceBase = 2f;

		public const float ChancePerStack = 0.1f;

		public const float VoidChancePerStack = 0.5f;

		public const float NailBase = 0.1f;

		public const float NailPerStack = 0.001f;

		public const float VoidNailPerStack = 0.005f;

		public const float BleedDuration = 3f;

		public const float MarkDuration = 3f;

		public const float DetonationCoefficient = 2.5f;

		public const float BurstBase = 1.5f;

		public const float BurstPerStack = 0.5f;

		public const float BurstRadius = 12f;

		public const int MaxActiveMarks = 200;

		public static float ChancePercent(int stacks, float perStack)
		{
			if (stacks <= 0)
			{
				return 0f;
			}
			float num = 2f + perStack * (float)(stacks - 1);
			if (!(num < 100f))
			{
				return 100f;
			}
			return num;
		}

		public static float NailCoefficient(int stacks, float perStack)
		{
			if (stacks > 0)
			{
				return 0.1f + perStack * (float)(stacks - 1);
			}
			return 0f;
		}

		public static float BurstCoefficient(int stacks)
		{
			if (stacks > 0)
			{
				return 1.5f + 0.5f * (float)(stacks - 1);
			}
			return 0f;
		}

		public static bool CanSpread(int generation, int maxChain)
		{
			return generation < maxChain;
		}
	}
}
namespace Ror2Meeeee.Core.Progression
{
	public readonly struct LadderRules
	{
		public float RaiseAt { get; }

		public float Step { get; }

		public float MaxMultiplier { get; }

		public LadderRules(float raiseAt, float step, float maxMultiplier)
		{
			RaiseAt = raiseAt;
			Step = step;
			MaxMultiplier = maxMultiplier;
		}
	}
	public static class ProgressionLadder
	{
		public static int Next(int level, float score, bool won, LadderRules r)
		{
			level = Math.Max(0, level);
			int val = ((!won) ? (level - 1) : ((!float.IsNaN(score) && score >= r.RaiseAt) ? (level + 1) : level));
			return Math.Max(0, Math.Min(val, MaxLevel(r)));
		}

		public static int MaxLevel(LadderRules r)
		{
			if (!ValidStep(r.Step) || !(r.MaxMultiplier > 1f) || float.IsInfinity(r.MaxMultiplier))
			{
				return 0;
			}
			return (int)Math.Min(10000.0, Math.Ceiling(((double)r.MaxMultiplier - 1.0) / (double)r.Step - 1E-06));
		}

		public static float Multiplier(int level, LadderRules r)
		{
			if (level <= 0 || !ValidStep(r.Step) || !(r.MaxMultiplier > 1f))
			{
				return 1f;
			}
			return (float)Math.Min(r.MaxMultiplier, 1.0 + (double)level * (double)r.Step);
		}

		private static bool ValidStep(float step)
		{
			if (!float.IsNaN(step) && !float.IsInfinity(step))
			{
				return step > 0f;
			}
			return false;
		}

		public static string Serialize(int level, int runs)
		{
			return "level=" + Math.Max(0, level).ToString(CultureInfo.InvariantCulture) + "\nruns=" + Math.Max(0, runs).ToString(CultureInfo.InvariantCulture) + "\n";
		}

		public static void Parse(string text, out int level, out int runs)
		{
			level = 0;
			runs = 0;
			if (string.IsNullOrEmpty(text))
			{
				return;
			}
			string[] array = text.Split('\n');
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i].Trim();
				int num = text2.IndexOf('=');
				if (num <= 0 || !int.TryParse(text2.Substring(num + 1).Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || result < 0)
				{
					continue;
				}
				string text3 = text2.Substring(0, num).Trim();
				if (!(text3 == "level"))
				{
					if (text3 == "runs")
					{
						runs = result;
					}
				}
				else
				{
					level = result;
				}
			}
		}

		public static string Summary(RunStats s, RunScoreResult score, int oldLevel, int newLevel, float newMultiplier)
		{
			CultureInfo invariantCulture = CultureInfo.InvariantCulture;
			double num = s.Seconds / 60.0;
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("<color=#e5c07b>Ror2Meeeee</color> ").Append(s.Won ? "vitória" : "derrota").Append(" em ")
				.Append(num.ToString("F1", invariantCulture))
				.Append(" min | nota ")
				.Append((score.Total * 100f).ToString("F0", invariantCulture))
				.Append("/100\n");
			stringBuilder.Append("velocidade ").Append(Pct(score.Speed)).Append(" · sobrevivência ")
				.Append(Pct(score.Survival))
				.Append(" · dano sofrido ")
				.Append(Pct(score.Damage))
				.Append(" · abates ")
				.Append(Pct(score.Kills))
				.Append('\n');
			stringBuilder.Append(s.Kills).Append(" abates, ").Append(s.Deaths)
				.Append(" mortes, ")
				.Append(s.HealthBarsLost.ToString("F1", invariantCulture))
				.Append(" vidas de dano sofrido\n");
			string value = ((newLevel > oldLevel) ? "sobe" : ((newLevel < oldLevel) ? "desce" : "mantém"));
			stringBuilder.Append("Diretor ").Append(value).Append(": nível ")
				.Append(oldLevel)
				.Append(" -> ")
				.Append(newLevel)
				.Append(" (orçamento de spawn x")
				.Append(newMultiplier.ToString("F2", invariantCulture))
				.Append(" na próxima run)");
			return stringBuilder.ToString();
		}

		private static string Pct(float v)
		{
			return (v * 100f).ToString("F0", CultureInfo.InvariantCulture);
		}
	}
	public readonly struct ScorePars
	{
		public float ChargeSeconds { get; }

		public float DeathsPerPlayer { get; }

		public float HealthBarsPerPlayerMinute { get; }

		public float KillsPerMinute { get; }

		public ScorePars(float chargeSeconds, float deathsPerPlayer, float healthBarsPerPlayerMinute, float killsPerMinute)
		{
			ChargeSeconds = chargeSeconds;
			DeathsPerPlayer = deathsPerPlayer;
			HealthBarsPerPlayerMinute = healthBarsPerPlayerMinute;
			KillsPerMinute = killsPerMinute;
		}
	}
	public readonly struct RunScoreResult
	{
		public float Speed { get; }

		public float Survival { get; }

		public float Damage { get; }

		public float Kills { get; }

		public float Total { get; }

		public RunScoreResult(float speed, float survival, float damage, float kills)
		{
			Speed = speed;
			Survival = survival;
			Damage = damage;
			Kills = kills;
			Total = (speed + survival + damage + kills) / 4f;
		}
	}
	public static class RunScore
	{
		public const float Neutral = 0.5f;

		public static RunScoreResult Compute(RunStats s, ScorePars p)
		{
			int num = Math.Max(1, s.Players);
			double num2 = s.Seconds / 60.0;
			float speed = ((s.ChargedStages > 0) ? Lower(s.ChargeSeconds / (double)s.ChargedStages, p.ChargeSeconds) : 0.5f);
			float survival = Lower((double)s.Deaths / (double)num, p.DeathsPerPlayer);
			float damage = ((num2 > 0.0) ? Lower(s.HealthBarsLost / (double)num / num2, p.HealthBarsPerPlayerMinute) : 0.5f);
			float kills = ((num2 > 0.0) ? Higher((double)s.Kills / num2, p.KillsPerMinute) : 0.5f);
			return new RunScoreResult(speed, survival, damage, kills);
		}

		internal static float Lower(double value, float par)
		{
			if (!Valid(par) || double.IsNaN(value))
			{
				return 0.5f;
			}
			return (float)((double)par / ((double)par + Math.Max(0.0, value)));
		}

		internal static float Higher(double value, float par)
		{
			if (!Valid(par) || double.IsNaN(value))
			{
				return 0.5f;
			}
			double num = Math.Max(0.0, value);
			return (float)(num / (num + (double)par));
		}

		private static bool Valid(float par)
		{
			if (!float.IsNaN(par) && !float.IsInfinity(par))
			{
				return par > 0f;
			}
			return false;
		}
	}
	public readonly struct RunStats
	{
		public int Players { get; }

		public double Seconds { get; }

		public int ChargedStages { get; }

		public double ChargeSeconds { get; }

		public int Deaths { get; }

		public int Kills { get; }

		public double HealthBarsLost { get; }

		public bool Won { get; }

		public RunStats(int players, double seconds, int chargedStages, double chargeSeconds, int deaths, int kills, double healthBarsLost, bool won)
		{
			Players = players;
			Seconds = seconds;
			ChargedStages = chargedStages;
			ChargeSeconds = chargeSeconds;
			Deaths = deaths;
			Kills = kills;
			HealthBarsLost = healthBarsLost;
			Won = won;
		}
	}
}
namespace Ror2Meeeee.Core.Pipeline
{
	public readonly struct PickupContext
	{
		public ItemKind Kind { get; }

		public int Count { get; }

		public int CurrentStack { get; }

		public bool PlayerAlive { get; }

		public bool PlayerConnected { get; }

		public bool CapExempt { get; }

		public PickupContext(ItemKind kind, int count, int currentStack, bool playerAlive, bool playerConnected, bool capExempt)
		{
			Kind = kind;
			Count = count;
			CurrentStack = currentStack;
			PlayerAlive = playerAlive;
			PlayerConnected = playerConnected;
			CapExempt = capExempt;
		}
	}
	public readonly struct MultiplierRules
	{
		public const int DefaultMultiplier = 10;

		public int Multiplier { get; }

		public bool IncludeLunar { get; }

		public bool IncludeVoid { get; }

		public int StackCap { get; }

		public MultiplierRules(int multiplier, bool includeLunar, bool includeVoid, int stackCap)
		{
			Multiplier = ((multiplier <= 0) ? 10 : multiplier);
			IncludeLunar = includeLunar;
			IncludeVoid = includeVoid;
			StackCap = ((stackCap >= 0) ? stackCap : 0);
		}
	}
	public static class MultiplierPipeline
	{
		public static bool AtHardCap(int currentStack, MultiplierRules rules)
		{
			if (rules.StackCap > 0)
			{
				return currentStack >= rules.StackCap;
			}
			return false;
		}

		public static int Resolve(PickupContext ctx, MultiplierRules rules)
		{
			if (!ctx.PlayerAlive || !ctx.PlayerConnected)
			{
				return 0;
			}
			if (ctx.Count <= 0 || !EligibilityTable.IsEligible(ctx.Kind, rules))
			{
				return 0;
			}
			long num = (long)ctx.Count * (long)rules.Multiplier;
			if (num > int.MaxValue)
			{
				num = 2147483647L;
			}
			long val = num - ctx.Count;
			if (rules.StackCap > 0 && !ctx.CapExempt)
			{
				long val2 = rules.StackCap - ((long)ctx.CurrentStack + (long)ctx.Count);
				val = Math.Min(val, Math.Max(0L, val2));
			}
			long val3 = int.MaxValue - ((long)ctx.CurrentStack + (long)ctx.Count);
			return (int)Math.Max(0L, Math.Min(val, val3));
		}
	}
	public readonly struct Recipient
	{
		public int CurrentStack { get; }

		public bool Alive { get; }

		public bool Connected { get; }

		public Recipient(int currentStack, bool alive, bool connected)
		{
			CurrentStack = currentStack;
			Alive = alive;
			Connected = connected;
		}
	}
	public static class SharingPipeline
	{
		public static int[] Resolve(PickupContext ctx, MultiplierRules rules, bool enabled, bool fromSharing, IReadOnlyList<Recipient> others)
		{
			int[] array = new int[others.Count];
			if (!enabled || fromSharing || ctx.Count <= 0 || !EligibilityTable.IsShareable(ctx.Kind))
			{
				return array;
			}
			for (int i = 0; i < others.Count; i++)
			{
				Recipient recipient = others[i];
				if (recipient.Alive && recipient.Connected && !MultiplierPipeline.AtHardCap(recipient.CurrentStack, rules))
				{
					int num = MultiplierPipeline.Resolve(new PickupContext(ctx.Kind, ctx.Count, recipient.CurrentStack, recipient.Alive, recipient.Connected, ctx.CapExempt), rules);
					long num2 = (long)ctx.Count + (long)num;
					array[i] = (int)((num2 > int.MaxValue) ? int.MaxValue : num2);
				}
			}
			return array;
		}
	}
}
namespace Ror2Meeeee.Core.Measurement
{
	public static class FrameStats
	{
		public static void Compute(float[] samples, int count, float[] scratch, out float mean, out float p95)
		{
			if (count <= 0)
			{
				mean = 0f;
				p95 = 0f;
				return;
			}
			double num = 0.0;
			for (int i = 0; i < count; i++)
			{
				num += (double)samples[i];
			}
			mean = (float)(num / (double)count);
			Array.Copy(samples, scratch, count);
			Array.Sort(scratch, 0, count);
			int num2 = (int)Math.Ceiling(0.95 * (double)count);
			p95 = scratch[num2 - 1];
		}
	}
}
namespace Ror2Meeeee.Core.Limits
{
	public static class ChanceAggregate
	{
		public static float Factor(int stack, int capped, float chancePerStack)
		{
			if (capped <= 0 || stack <= capped || chancePerStack <= 0f)
			{
				return 1f;
			}
			float num = Math.Min(100f, chancePerStack * (float)stack);
			float num2 = Math.Min(100f, chancePerStack * (float)capped);
			return num / num2;
		}
	}
	public struct BudgetWindow
	{
		public float Start;

		public int Count;

		public float PendingDamage;
	}
	public static class ProjectileBudget
	{
		public static bool Decide(ref BudgetWindow w, float now, int maxPerSecond, float damage, out float damageToFire)
		{
			if (now - w.Start >= 1f || now < w.Start)
			{
				w.Start = now;
				w.Count = 0;
			}
			if (maxPerSecond <= 0 || w.Count < maxPerSecond)
			{
				w.Count++;
				damageToFire = damage + w.PendingDamage;
				w.PendingDamage = 0f;
				return true;
			}
			w.PendingDamage += damage;
			damageToFire = 0f;
			return false;
		}
	}
	public enum StackMode
	{
		Off,
		Clamp,
		Aggregate
	}
	public interface IStackPolicy
	{
		int Limit { get; }

		int Apply(int stack);
	}
	public static class StackPolicy
	{
		private sealed class OffPolicy : IStackPolicy
		{
			public int Limit => int.MaxValue;

			public int Apply(int stack)
			{
				return stack;
			}
		}

		private sealed class ClampPolicy : IStackPolicy
		{
			private readonly int _limit;

			public int Limit => _limit;

			public ClampPolicy(int limit)
			{
				_limit = limit;
			}

			public int Apply(int stack)
			{
				if (stack >= 0)
				{
					if (stack <= _limit)
					{
						return stack;
					}
					return _limit;
				}
				return 0;
			}
		}

		public static readonly IStackPolicy Off = new OffPolicy();

		public static IStackPolicy Clamp(int limit)
		{
			return new ClampPolicy(Math.Max(1, limit));
		}

		public static IStackPolicy Create(StackMode mode, int limit)
		{
			if (mode != StackMode.Off)
			{
				return Clamp(limit);
			}
			return Off;
		}
	}
}
namespace Ror2Meeeee.Core.Helluva
{
	public static class DropRules
	{
		public static int ClampCount(int requested, int owned, int max)
		{
			if (owned <= 0 || max <= 0)
			{
				return 0;
			}
			return Math.Min(Math.Max(requested, 1), Math.Min(owned, max));
		}
	}
	public static class HelluvaRules
	{
		public static float GrimoireCredit(float baseCredit, float difficultyCoefficient)
		{
			if (float.IsNaN(baseCredit) || baseCredit <= 0f || float.IsNaN(difficultyCoefficient))
			{
				return 0f;
			}
			return (float)Math.Min((double)baseCredit * (double)Math.Max(1f, difficultyCoefficient), 10000000.0);
		}

		public static float GrimoireCreditGuarded(float baseCredit, float difficultyCoefficient, float maxPerUse, int monstersAlive, int maxMonsters)
		{
			if (maxMonsters > 0 && monstersAlive >= maxMonsters)
			{
				return 0f;
			}
			float num = GrimoireCredit(baseCredit, difficultyCoefficient);
			if (!(maxPerUse > 0f))
			{
				return num;
			}
			return Math.Min(num, maxPerUse);
		}

		public static uint ContractGoldCapped(uint goldReward, int teamStacks, uint maxGold)
		{
			uint num = ContractGold(goldReward, teamStacks);
			if (maxGold == 0 || num <= maxGold)
			{
				return num;
			}
			return maxGold;
		}

		public static uint ContractGold(uint goldReward, int teamStacks)
		{
			if (goldReward == 0 || teamStacks <= 0)
			{
				return 0u;
			}
			ulong num = (ulong)(goldReward * teamStacks);
			if (num <= uint.MaxValue)
			{
				return (uint)num;
			}
			return uint.MaxValue;
		}

		public static bool ReviveStep(ref float progress, bool allyNear, float dt, float required)
		{
			if (!allyNear || float.IsNaN(dt) || dt < 0f)
			{
				progress = 0f;
				return false;
			}
			progress += dt;
			if (progress < required)
			{
				return false;
			}
			progress = 0f;
			return true;
		}

		public static float ReviverCost(float currentHealth, float fraction)
		{
			if (float.IsNaN(currentHealth) || currentHealth <= 1f || float.IsNaN(fraction) || fraction <= 0f)
			{
				return 0f;
			}
			return Math.Min(currentHealth * Math.Min(1f, fraction), currentHealth - 1f);
		}
	}
}
namespace Ror2Meeeee.Core.Gold
{
	public static class GoldCredit
	{
		public static float Compute(uint amount, int stacks, float ratioPerStack)
		{
			if (amount == 0 || stacks <= 0 || float.IsNaN(ratioPerStack) || float.IsInfinity(ratioPerStack) || ratioPerStack <= 0f)
			{
				return 0f;
			}
			return (float)Math.Min((double)amount * (double)stacks * (double)ratioPerStack, 3.4028234663852886E+38);
		}
	}
	public static class TitheThanks
	{
		private static readonly string[] Lines = new string[4] { "Obrigado pelo dízimo! R$ {1} de vocês já viraram {0} de crédito em monstro.", "Sua generosidade foi notada: R$ {1} viraram +{0} de crédito de spawn.", "R$ {1} recolhidos, {0} de crédito investido em companhia para vocês.", "O diretor agradece a contribuição de R$ {1}. Os monstros também ({0} de crédito)." };

		public static bool Due(double now, double lastPost, double interval, double pendingCredit)
		{
			if (interval > 0.0 && pendingCredit >= 1.0)
			{
				return now - lastPost >= interval;
			}
			return false;
		}

		public static string Format(int index, double credit, ulong gold)
		{
			CultureInfo invariantCulture = CultureInfo.InvariantCulture;
			string format = Lines[(uint)index % (uint)Lines.Length];
			return "<color=#c792ea>Diretor:</color> " + string.Format(invariantCulture, format, Thousands(Math.Floor(credit).ToString("N0", invariantCulture)), Thousands(gold.ToString("N0", invariantCulture)));
		}

		private static string Thousands(string invariantN0)
		{
			return invariantN0.Replace(',', '.');
		}
	}
}
namespace Ror2Meeeee.Core.Elites
{
	public static class EliteRules
	{
		public static (int First, int Second) PickTwoDistinct(int count, int a, int b)
		{
			if (count < 1)
			{
				return (First: -1, Second: -1);
			}
			if (count < 2)
			{
				return (First: 0, Second: -1);
			}
			return (First: a, Second: (b >= a) ? (b + 1) : b);
		}
	}
}
namespace Ror2Meeeee.Core.Eligibility
{
	public enum ItemKind
	{
		White,
		Green,
		Red,
		Boss,
		Lunar,
		Void,
		Temporary,
		Scrap,
		Equipment,
		Other,
		Special
	}
	public static class EligibilityTable
	{
		public static bool IsEligible(ItemKind kind, MultiplierRules rules)
		{
			switch (kind)
			{
			case ItemKind.White:
			case ItemKind.Green:
			case ItemKind.Red:
			case ItemKind.Boss:
				return true;
			case ItemKind.Lunar:
				return rules.IncludeLunar;
			case ItemKind.Void:
				return rules.IncludeVoid;
			default:
				return false;
			}
		}

		public static bool IsShareable(ItemKind kind)
		{
			if (kind != ItemKind.Equipment)
			{
				return kind != ItemKind.Other;
			}
			return false;
		}
	}
}
namespace Ror2Meeeee.Core.Difficulty
{
	public readonly struct DifficultyGains
	{
		public float Health { get; }

		public float Damage { get; }

		public float Quantity { get; }

		public float Pace { get; }

		public DifficultyGains(float health, float damage, float quantity, float pace)
		{
			Health = health;
			Damage = damage;
			Quantity = quantity;
			Pace = pace;
		}
	}
	public readonly struct DifficultyMultipliers
	{
		public static readonly DifficultyMultipliers Identity = new DifficultyMultipliers(1f, 1f, 1f, 1f);

		public float Health { get; }

		public float Damage { get; }

		public float Quantity { get; }

		public float Pace { get; }

		public DifficultyMultipliers(float health, float damage, float quantity, float pace)
		{
			Health = health;
			Damage = damage;
			Quantity = quantity;
			Pace = pace;
		}
	}
	public static class DifficultyCurve
	{
		public const float DefaultFactor = 1f;

		public const float MinMultiplier = 0.1f;

		public const float MaxMultiplier = 1000f;

		public static float SanitizeFactor(float factor)
		{
			if (float.IsNaN(factor) || float.IsInfinity(factor) || factor <= 0f)
			{
				return 1f;
			}
			return factor;
		}

		public static DifficultyMultipliers Evaluate(float factor, DifficultyGains gains)
		{
			float factor2 = SanitizeFactor(factor);
			return new DifficultyMultipliers(Axis(factor2, gains.Health), Axis(factor2, gains.Damage), Axis(factor2, gains.Quantity), Axis(factor2, gains.Pace));
		}

		public static float WithBonus(float multiplier, float bonusPercent)
		{
			if (float.IsNaN(bonusPercent) || float.IsInfinity(bonusPercent))
			{
				bonusPercent = 0f;
			}
			double val = (double)multiplier * (1.0 + (double)bonusPercent / 100.0);
			return (float)Math.Min(1000.0, Math.Max(0.10000000149011612, val));
		}

		private static float Axis(float factor, float gain)
		{
			if (float.IsNaN(gain) || float.IsInfinity(gain))
			{
				return 1f;
			}
			double val = 1.0 + ((double)factor - 1.0) * (double)gain;
			return (float)Math.Min(1000.0, Math.Max(0.10000000149011612, val));
		}
	}
	public static class HordeCurve
	{
		public static float QuantityMultiplier(int stacks, float perStack, float max)
		{
			if (stacks <= 0 || float.IsNaN(perStack) || float.IsNaN(max) || perStack <= 0f || max < 1f)
			{
				return 1f;
			}
			double val = 1.0 + (double)stacks * (double)perStack;
			return (float)Math.Min(max, val);
		}
	}
}
namespace Ror2Meeeee.Core.Bazaar
{
	public enum BazaarTier
	{
		White,
		Green,
		Red,
		Boss,
		Lunar,
		Equipment,
		LunarEquipment
	}
	public static class BazaarRules
	{
		public const int TierCount = 7;

		public const int MaxChests = 6;

		public const int SmallChestBaseCost = 25;

		public const int Unlimited = -1;

		public static int PickWeighted(IReadOnlyList<float> weights, double roll)
		{
			double num = 0.0;
			for (int i = 0; i < weights.Count; i++)
			{
				num += Valid(weights[i]);
			}
			if (num <= 0.0)
			{
				return -1;
			}
			double num2 = roll * num;
			int result = -1;
			for (int j = 0; j < weights.Count; j++)
			{
				double num3 = Valid(weights[j]);
				if (!(num3 <= 0.0))
				{
					if (num2 < num3)
					{
						return j;
					}
					num2 -= num3;
					result = j;
				}
			}
			return result;
		}

		public static int ScaledCost(int baseCost, float difficultyCoefficient, float multiplier)
		{
			double x = ((float.IsNaN(difficultyCoefficient) || difficultyCoefficient <= 0f) ? 1f : difficultyCoefficient);
			double num = ((float.IsNaN(multiplier) || multiplier < 0f) ? 0f : multiplier);
			double num2 = (double)Math.Max(0, baseCost) * Math.Pow(x, 1.25) * num;
			if (!(num2 >= 2147483647.0))
			{
				return (int)num2;
			}
			return int.MaxValue;
		}

		public static int GoldCost(float difficultyCoefficient, float multiplier)
		{
			return ScaledCost(25, difficultyCoefficient, multiplier);
		}

		public static bool UnderLimit(int used, int limit)
		{
			if (limit >= 0)
			{
				return used < limit;
			}
			return true;
		}

		public static int ClampChests(int n)
		{
			if (n >= 1)
			{
				if (n <= 6)
				{
					return n;
				}
				return 6;
			}
			return 1;
		}

		public static uint AddMoney(uint money, long amount)
		{
			long num = money + amount;
			if (num > 0)
			{
				if (num < uint.MaxValue)
				{
					return (uint)num;
				}
				return uint.MaxValue;
			}
			return 0u;
		}

		private static double Valid(float w)
		{
			return (float.IsNaN(w) || w <= 0f) ? 0f : w;
		}
	}
}
namespace Ror2Meeeee.Core.Aegis
{
	public static class AegisRules
	{
		public const float BlockChancePercent = 5f;

		public const float StealPerStack = 0.08f;

		public const float StealCap = 0.5f;

		public const float VoidPerStack = 0.03f;

		public const float VoidCap = 0.2f;

		public const float VoidBaseRadius = 13f;

		public const float VoidRadiusPerStack = 2f;

		public const float VoidRadiusCap = 30f;

		public static float StealFraction(int stacks)
		{
			return Capped(0.08f * (float)stacks, stacks, 0.5f);
		}

		public static float VoidFraction(int stacks)
		{
			return Capped(0.03f * (float)stacks, stacks, 0.2f);
		}

		public static float VoidRadius(int stacks)
		{
			if (stacks <= 0)
			{
				return 0f;
			}
			float num = 13f + 2f * (float)(stacks - 1);
			if (!(num < 30f))
			{
				return 30f;
			}
			return num;
		}

		private static float Capped(float value, int stacks, float cap)
		{
			if (stacks > 0)
			{
				if (!(value < cap))
				{
					return cap;
				}
				return value;
			}
			return 0f;
		}
	}
}

Ror2Meeeee.dll

Decompiled 13 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using EntityStates;
using EntityStates.ClayBoss;
using EntityStates.DefectiveUnit;
using EntityStates.Mimic.Chest;
using EntityStates.Totem;
using EntityStates.VoidBarnacle;
using HG.Reflection;
using IL.RoR2;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using On;
using On.EntityStates.CaptainSupplyDrop;
using On.EntityStates.ClayBoss;
using On.EntityStates.DefectiveUnit;
using On.EntityStates.Mimic.Chest;
using On.EntityStates.Totem;
using On.EntityStates.VoidBarnacle;
using On.RoR2;
using On.RoR2.Items;
using On.RoR2.Orbs;
using On.RoR2.Projectile;
using R2API;
using R2API.Networking;
using R2API.Networking.Interfaces;
using R2API.Utils;
using RiskOfOptions;
using RiskOfOptions.Options;
using RoR2;
using RoR2.AsyncManagement;
using RoR2.CharacterAI;
using RoR2.Items;
using RoR2.Navigation;
using RoR2.Orbs;
using RoR2.Projectile;
using RoR2.Stats;
using RoR2.UI;
using Ror2Meeeee.Core.Aegis;
using Ror2Meeeee.Core.Bazaar;
using Ror2Meeeee.Core.Difficulty;
using Ror2Meeeee.Core.Eligibility;
using Ror2Meeeee.Core.Elites;
using Ror2Meeeee.Core.Gold;
using Ror2Meeeee.Core.Helluva;
using Ror2Meeeee.Core.Limits;
using Ror2Meeeee.Core.Measurement;
using Ror2Meeeee.Core.Pipeline;
using Ror2Meeeee.Core.Progression;
using Ror2Meeeee.Core.RustyNail;
using Ror2Meeeee.Core.Spend;
using Ror2Meeeee.Core.Stats;
using Ror2Meeeee.Core.Tax;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Networking;
using UnityEngine.Profiling;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: OptIn]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Ror2Meeeee")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+47d3711113ead05e4a0dd86c182991233f903141")]
[assembly: AssemblyProduct("Ror2Meeeee")]
[assembly: AssemblyTitle("Ror2Meeeee")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Ror2Meeeee
{
	internal interface IHolderSet
	{
		bool HasHolders { get; }

		bool Holds(GameObject body);
	}
	internal static class BodyHooks
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static hook_RecalculateStats <0>__OnRecalculateStats;

			public static hook_TakeDamageProcess <1>__OnTakeDamage;
		}

		internal static bool RawDamage;

		internal static HeavyHeartFeature Heart;

		internal static BastionFeature Bastion;

		internal static CervoFeature Cervo;

		internal static AegisFeature Aegis;

		private static bool _stats;

		private static bool _damage;

		private static readonly Action<CharacterBody, float> SetMaxHealth = Setter("maxHealth");

		private static readonly Action<CharacterBody, float> SetMaxShield = Setter("maxShield");

		private static readonly Action<CharacterBody, float> SetMaxBarrier = Setter("maxBarrier");

		private static readonly Action<CharacterBody, float> SetMaxHull = Setter("maxHull");

		private static Action<CharacterBody, float> Setter(string property)
		{
			MethodInfo methodInfo = typeof(CharacterBody).GetProperty(property)?.GetSetMethod(nonPublic: true);
			if (!(methodInfo == null))
			{
				return (Action<CharacterBody, float>)Delegate.CreateDelegate(typeof(Action<CharacterBody, float>), methodInfo);
			}
			return null;
		}

		private static bool Active(IHolderSet f)
		{
			return f?.HasHolders ?? false;
		}

		public static void Sync()
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			//IL_0041: 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_004c: Expected O, but got Unknown
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Expected O, but got Unknown
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Expected O, but got Unknown
			bool flag = Active(Heart) || Active(Bastion) || Active(Cervo);
			if (flag != _stats)
			{
				if (flag)
				{
					object obj = <>O.<0>__OnRecalculateStats;
					if (obj == null)
					{
						hook_RecalculateStats val = OnRecalculateStats;
						<>O.<0>__OnRecalculateStats = val;
						obj = (object)val;
					}
					CharacterBody.RecalculateStats += (hook_RecalculateStats)obj;
				}
				else
				{
					object obj2 = <>O.<0>__OnRecalculateStats;
					if (obj2 == null)
					{
						hook_RecalculateStats val2 = OnRecalculateStats;
						<>O.<0>__OnRecalculateStats = val2;
						obj2 = (object)val2;
					}
					CharacterBody.RecalculateStats -= (hook_RecalculateStats)obj2;
				}
				_stats = flag;
				ManualLogSource log = Diag.Log;
				if (log != null)
				{
					log.LogInfo((object)("[BodyHooks] hook de stats " + (flag ? "ligado" : "desligado") + " (Coração/Bastião/Cervo)"));
				}
			}
			bool flag2 = Active(Heart) || Active(Aegis);
			if (flag2 == _damage)
			{
				return;
			}
			if (flag2)
			{
				object obj3 = <>O.<1>__OnTakeDamage;
				if (obj3 == null)
				{
					hook_TakeDamageProcess val3 = OnTakeDamage;
					<>O.<1>__OnTakeDamage = val3;
					obj3 = (object)val3;
				}
				HealthComponent.TakeDamageProcess += (hook_TakeDamageProcess)obj3;
			}
			else
			{
				object obj4 = <>O.<1>__OnTakeDamage;
				if (obj4 == null)
				{
					hook_TakeDamageProcess val4 = OnTakeDamage;
					<>O.<1>__OnTakeDamage = val4;
					obj4 = (object)val4;
				}
				HealthComponent.TakeDamageProcess -= (hook_TakeDamageProcess)obj4;
			}
			_damage = flag2;
			ManualLogSource log2 = Diag.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)("[BodyHooks] hook de dano " + (flag2 ? "ligado" : "desligado") + " (Égides/Coração)"));
			}
		}

		private static void OnRecalculateStats(orig_RecalculateStats orig, CharacterBody self)
		{
			GameObject val = (Object.op_Implicit((Object)(object)self) ? ((Component)self).gameObject : null);
			bool flag = Object.op_Implicit((Object)(object)val) && Heart != null && Heart.Holds(val);
			bool flag2 = Object.op_Implicit((Object)(object)val) && Bastion != null && Bastion.Holds(val);
			bool flag3 = Object.op_Implicit((Object)(object)val) && Cervo != null && Cervo.Holds(val);
			if (!flag && !flag2 && !flag3)
			{
				orig.Invoke(self);
				return;
			}
			HealthComponent healthComponent = self.healthComponent;
			float maxHealth = self.maxHealth;
			float num = (Object.op_Implicit((Object)(object)healthComponent) ? healthComponent.health : 0f);
			float maxShield = self.maxShield;
			float num2 = (Object.op_Implicit((Object)(object)healthComponent) ? healthComponent.shield : 0f);
			orig.Invoke(self);
			if (flag)
			{
				Heart.ApplyStats(self);
			}
			if (flag2)
			{
				Bastion.ApplyStats(self);
			}
			if (flag3)
			{
				Cervo.ApplyStats(self);
			}
			ClampPools(self);
			if (!NetworkServer.active || !Object.op_Implicit((Object)(object)healthComponent) || !healthComponent.alive)
			{
				return;
			}
			try
			{
				if (flag)
				{
					healthComponent.Networkhealth = StatPool.Adjust(num, maxHealth, self.maxHealth);
				}
				if (flag2)
				{
					healthComponent.Networkshield = StatPool.Adjust(num2, maxShield, self.maxShield);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Diag.Log;
				if (log != null)
				{
					log.LogWarning((object)("[BodyHooks] reajuste de vida/escudo falhou: " + ex.Message));
				}
			}
		}

		private static void ClampPools(CharacterBody self)
		{
			try
			{
				float num = StatPool.ClampScale(self.maxHealth, self.maxShield);
				if (!(num >= 1f) && SetMaxHealth != null && SetMaxShield != null && SetMaxBarrier != null && SetMaxHull != null)
				{
					float num2 = self.maxHealth * num;
					float num3 = self.maxShield * num;
					SetMaxHealth(self, num2);
					SetMaxShield(self, num3);
					SetMaxBarrier(self, num2 + num3);
					SetMaxHull(self, num2 + num3);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Diag.Log;
				if (log != null)
				{
					log.LogWarning((object)("[BodyHooks] teto de vida/escudo falhou: " + ex.Message));
				}
			}
		}

		private static void OnTakeDamage(orig_TakeDamageProcess orig, HealthComponent self, DamageInfo damageInfo)
		{
			if (RawDamage)
			{
				orig.Invoke(self, damageInfo);
				return;
			}
			CharacterBody body = null;
			bool num = Aegis != null && Aegis.BeforeDamage(self, damageInfo, out body);
			Heart?.AmplifyDamage(self, damageInfo);
			orig.Invoke(self, damageInfo);
			if (num && damageInfo.rejected)
			{
				Aegis.AfterBlocked(body, damageInfo);
			}
		}
	}
	public sealed class Cfg
	{
		public const int MinMaxFailures = 50;

		private readonly ConfigFile _file;

		private readonly ManualLogSource _log;

		private readonly ConfigEntry<bool> _verboseLogging;

		private readonly ConfigEntry<int> _maxFailures;

		private readonly List<ConfigEntryBase> _entries = new List<ConfigEntryBase>();

		private const string EnabledSuffix = " Liga/desliga na hora; o efeito vale a partir do próximo evento ou estágio.";

		public IReadOnlyList<ConfigEntryBase> Entries => _entries;

		public ConfigEntry<bool> ProbeEnabledEntry { get; }

		public bool ProbeEmptyHook { get; }

		public int ProbeAutoWindowSeconds { get; }

		public bool VerboseLogging { get; private set; }

		public int MaxFailures { get; private set; }

		public Cfg(ConfigFile file, ManualLogSource log)
		{
			_file = file;
			_log = log;
			_verboseLogging = Bind("General", "VerboseLogging", defaultValue: false, "Logs extras de depuração no LogOutput.log. Deixe desligado no dia a dia: log verboso custa FPS.");
			_maxFailures = Bind("General", "MaxFailures", 50, $"Quantos erros uma feature pode ter antes de se desligar sozinha para proteger a partida. Mínimo {50}.");
			ProbeEnabledEntry = Bind("General", "ProbeEnabled", defaultValue: false, "Ferramenta de medição de desempenho: grava tempo de frame, RAM, projéteis e dano em BepInEx/ror2meeeee-probe.csv. Só para testes; desligada não custa nada. Não muda o jogo.");
			ProbeEmptyHook = Bind("General", "ProbeEmptyHook", defaultValue: false, "Teste do Probe: adiciona um hook vazio para medir quanto custa um hook sozinho. Exige reiniciar o jogo.").Value;
			ProbeAutoWindowSeconds = Math.Max(0, Bind("General", "ProbeAutoWindowSeconds", 30, "Probe: mede sozinho durante a run em janelas de X segundos (cada janela vira uma linha no CSV e no log). 0 = só com os comandos ror2meeeee_probe_*. Exige reiniciar o jogo.").Value);
			_verboseLogging.SettingChanged += delegate
			{
				Refresh();
			};
			_maxFailures.SettingChanged += delegate
			{
				Refresh();
			};
			Refresh();
		}

		public ConfigEntry<bool> BindEnabled(string section, string summary = null, bool defaultValue = false)
		{
			return Bind(section, "Enabled", defaultValue, (summary ?? "Liga esta feature.") + " Liga/desliga na hora; o efeito vale a partir do próximo evento ou estágio.");
		}

		public ConfigEntry<T> Bind<T>(string section, string key, T defaultValue, string description)
		{
			ConfigEntry<T> val = _file.Bind<T>(section, key, defaultValue, description);
			if (!_entries.Contains((ConfigEntryBase)(object)val))
			{
				_entries.Add((ConfigEntryBase)(object)val);
			}
			return val;
		}

		private void Refresh()
		{
			VerboseLogging = _verboseLogging.Value;
			int num = _maxFailures.Value;
			if (num < 50)
			{
				_log.LogWarning((object)$"General.MaxFailures={num} inválido (mínimo {50}); usando {50}.");
				num = 50;
				_maxFailures.Value = num;
			}
			MaxFailures = num;
		}
	}
	internal static class Diag
	{
		internal sealed class RateWatch
		{
			private readonly string _name;

			private readonly int _threshold;

			private float _start;

			private int _n;

			private bool _logged;

			public RateWatch(string name, int threshold)
			{
				_name = name;
				_threshold = threshold;
				lock (Watches)
				{
					Watches.Add(this);
				}
			}

			public void ResetStage()
			{
				_logged = false;
			}

			public bool Hit(int scale = 1)
			{
				float time = Time.time;
				if (time - _start >= 1f)
				{
					_start = time;
					_n = 0;
				}
				if (++_n < _threshold * Math.Max(1, scale) || _logged)
				{
					return false;
				}
				_logged = true;
				return true;
			}

			public void Report(string detail = null)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogWarning((object)string.Format("[Diag] enxurrada de {0}: {1} em <1 s{2}; monstros ~{3}. Origem:\n{4}", _name, _n, (detail != null) ? (" (" + detail + ")") : "", Monsters, new StackTrace(1, fNeedFileInfo: false)));
				}
			}
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static Action<Stage> <0>__OnStageBegin;

			public static Action<Stage> <1>__OnStageComplete;

			public static Action<Run> <2>__OnRunDestroy;

			public static Action<DamageReport> <3>__OnDeath;

			public static Action <4>__OnUpdate;

			public static LogCallback <5>__OnUnityLog;

			public static ThreadStart <6>__WatchLoop;
		}

		public static long GoldEvents;

		public static double CreditGiven;

		public static long CreditDropped;

		public static int Exceptions;

		public static int Revives;

		public static int GrimoireUses;

		public static long GhostBladesSkipped;

		public static double GrimoireTrimmed;

		public static int Tombstones;

		public static int Monsters;

		public static int WindowMaxMonsters;

		public static double MonsterSum;

		public static long MonsterSamples;

		private static readonly string[] KnownNoise = new string[30]
		{
			"PushPickupNotification", "FrolicAway", "DroneCopycat", "has no NetworkIdentity", "Non-convex MeshCollider", "InvalidKeyException", "Could not find target object with netId", "Lobby.GetMemberIDs", "already a player at that playerControllerId", "A connection has already been set as ready",
			"ViewableTag.OnDisable", "SteamworksLobbyDataGenerator.RebuildLobbyData", "ReleasePools called on non-empty pool", "AssignClientAuthority can only be used", "CombatSquad has no living members", "Unable to set gate state for", "PickupDisplay bounds are zero", "invoked wrong io operation", "out of bound or host has been already removed", "SurvivorMannequinSlotController.ApplyLoadoutToMannequinInstance",
			"ExtractorUnit.ExtractLunge.OnEnter", "SolusAmalgamator.DetatchState.OnEnter", "InventorySafekeepController.OnCharacterMasterLost", "SetStateOnHurt.GetModifiedDuration", "ParticleSystemColorFromEffectData.ResetParticleSystems", "from prefab named 'GenericHugeFootstepDust'", "BaseAchievement: localUser is null", "MasterSuicideOnTimer.OnDestroy", "BrotherUltUtils.EvaluatePattern", "CaptainSupplyDropFinaleAchievement"
		};

		private static readonly int[] KnownCounts = new int[KnownNoise.Length];

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

		private static readonly object UnityLogLock = new object();

		private static int _unknownCount;

		private static int _unknownAtStage;

		private const float StallSeconds = 3f;

		private static ManualLogSource _log;

		private static long _beat;

		private static volatile bool _watch;

		private static float _sampleAcc;

		private static volatile float _lastFrameMs;

		private const int HeartbeatSeconds = 5;

		private static readonly object HeartbeatLock = new object();

		private static bool _stageActive;

		private static string _stageName;

		private static float _stageStart;

		private static float _stageWorstMs;

		private static int _stageKills;

		private static int _stageMaxMonsters;

		private static long _gold0;

		private static double _credit0;

		private static long _dropped0;

		private static int _exc0;

		private static int _rev0;

		private static readonly List<RateWatch> Watches = new List<RateWatch>();

		private static string HeartbeatPath => Path.Combine(Paths.BepInExRootPath, "ror2meeeee-heartbeat.txt");

		public static ManualLogSource Log => _log;

		public static void Install(ManualLogSource log)
		{
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Expected O, but got Unknown
			_log = log;
			Interlocked.Exchange(ref _beat, Stopwatch.GetTimestamp());
			Stage.onServerStageBegin += OnStageBegin;
			Stage.onServerStageComplete += OnStageComplete;
			Run.onRunDestroyGlobal += OnRunDestroy;
			GlobalEventManager.onCharacterDeathServer += OnDeath;
			RoR2Application.onUpdate += OnUpdate;
			object obj = <>O.<5>__OnUnityLog;
			if (obj == null)
			{
				LogCallback val = OnUnityLog;
				<>O.<5>__OnUnityLog = val;
				obj = (object)val;
			}
			Application.logMessageReceivedThreaded += (LogCallback)obj;
			ReportPreviousSession();
			Thread thread = new Thread(WatchLoop);
			thread.IsBackground = true;
			thread.Name = "Ror2Meeeee.Watchdog";
			thread.Start();
		}

		private static void ReportPreviousSession()
		{
			try
			{
				string heartbeatPath = HeartbeatPath;
				if (File.Exists(heartbeatPath))
				{
					_log.LogWarning((object)("[Vigia] a sessão anterior não fechou normalmente (travou ou foi encerrada à força). Último sinal: " + File.ReadAllText(heartbeatPath).Trim()));
					File.Delete(heartbeatPath);
				}
			}
			catch (Exception ex)
			{
				_log.LogWarning((object)("[Vigia] falha ao ler o último sinal: " + ex.Message));
			}
		}

		public static void MarkCleanExit()
		{
			lock (HeartbeatLock)
			{
				try
				{
					File.Delete(HeartbeatPath);
				}
				catch (Exception)
				{
				}
			}
		}

		private static void WriteHeartbeat(double gap)
		{
			lock (HeartbeatLock)
			{
				if (!Plugin.Quitting)
				{
					string contents = string.Format("{0:yyyy-MM-dd HH:mm:ss} | estágio {1} | ", DateTime.Now, _stageActive ? _stageName : "fora de estágio") + $"último frame há {gap:F1} s ({_lastFrameMs:F0} ms) | monstros {Monsters} | abates no estágio {_stageKills} | " + $"eventos de ouro {GoldEvents} | lâminas puladas {GhostBladesSkipped} | exceções do mod {Exceptions} | " + $"RAM gerenciada {GC.GetTotalMemory(forceFullCollection: false) / 1048576} MB";
					File.WriteAllText(HeartbeatPath, contents);
				}
			}
		}

		private static void OnStageBegin(Stage stage)
		{
			try
			{
				if (_stageActive)
				{
					LogStageSummary("(interrompido)");
				}
				_stageActive = true;
				_stageName = ((Object.op_Implicit((Object)(object)stage) && Object.op_Implicit((Object)(object)stage.sceneDef)) ? stage.sceneDef.cachedName : "?");
				_stageStart = Time.time;
				_stageWorstMs = 0f;
				_stageKills = 0;
				_stageMaxMonsters = 0;
				_gold0 = GoldEvents;
				_credit0 = CreditGiven;
				_dropped0 = CreditDropped;
				_exc0 = Exceptions;
				_rev0 = Revives;
				_unknownAtStage = _unknownCount;
				foreach (RateWatch watch in Watches)
				{
					watch.ResetStage();
				}
				DroppedGrants.Clear();
				Interlocked.Exchange(ref _beat, Stopwatch.GetTimestamp());
				_watch = true;
			}
			catch (Exception ex)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogWarning((object)("[Diag] falha no início do estágio: " + ex.Message));
				}
			}
		}

		private static void OnStageComplete(Stage stage)
		{
			try
			{
				LogStageSummary("concluído");
			}
			catch (Exception ex)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogWarning((object)("[Diag] falha no resumo do estágio: " + ex.Message));
				}
			}
			_watch = false;
		}

		private static void OnRunDestroy(Run run)
		{
			try
			{
				if (_stageActive)
				{
					LogStageSummary("run encerrada");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogWarning((object)("[Diag] falha no resumo do estágio: " + ex.Message));
				}
			}
			_watch = false;
		}

		private static void LogStageSummary(string how)
		{
			if (_stageActive)
			{
				_stageActive = false;
				int num;
				lock (UnityLogLock)
				{
					num = _unknownCount - _unknownAtStage;
				}
				_log.LogInfo((object)($"[Estágio] {_stageName} {how}: {Time.time - _stageStart:F0} s | pior frame {_stageWorstMs:F0} ms | " + $"abates {_stageKills} | monstros pico {_stageMaxMonsters} | ouro {GoldEvents - _gold0} eventos, crédito +{CreditGiven - _credit0:F0} " + $"(cortados {CreditDropped - _dropped0}) | revives {Revives - _rev0} | exceções do mod {Exceptions - _exc0} | erros novos do jogo {num}"));
			}
		}

		private static void OnDeath(DamageReport report)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Invalid comparison between Unknown and I4
			if (_stageActive && report != null && (int)report.victimTeamIndex == 2)
			{
				_stageKills++;
			}
		}

		private static void OnUpdate()
		{
			Interlocked.Exchange(ref _beat, Stopwatch.GetTimestamp());
			float unscaledDeltaTime = Time.unscaledDeltaTime;
			float num = (_lastFrameMs = unscaledDeltaTime * 1000f);
			if (num > _stageWorstMs)
			{
				_stageWorstMs = num;
			}
			_sampleAcc += unscaledDeltaTime;
			if (!(_sampleAcc < 0.5f))
			{
				_sampleAcc = 0f;
				int num2 = (Monsters = (Object.op_Implicit((Object)(object)Run.instance) ? TeamComponent.GetTeamMembers((TeamIndex)2).Count : 0));
				MonsterSum += num2;
				MonsterSamples++;
				if (num2 > WindowMaxMonsters)
				{
					WindowMaxMonsters = num2;
				}
				if (num2 > _stageMaxMonsters)
				{
					_stageMaxMonsters = num2;
				}
			}
		}

		public static string MonsterBreakdown(int top)
		{
			ReadOnlyCollection<TeamComponent> teamMembers = TeamComponent.GetTeamMembers((TeamIndex)2);
			if (teamMembers == null || teamMembers.Count == 0)
			{
				return "nenhum";
			}
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			for (int i = 0; i < teamMembers.Count; i++)
			{
				TeamComponent val = teamMembers[i];
				string text = ((Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.body)) ? ((Object)val.body).name : "?");
				if (text.EndsWith("(Clone)"))
				{
					text = text.Substring(0, text.Length - 7);
				}
				dictionary.TryGetValue(text, out var value);
				dictionary[text] = value + 1;
			}
			List<KeyValuePair<string, int>> list = new List<KeyValuePair<string, int>>(dictionary);
			list.Sort((KeyValuePair<string, int> a, KeyValuePair<string, int> b) => b.Value.CompareTo(a.Value));
			StringBuilder stringBuilder = new StringBuilder();
			for (int num = 0; num < list.Count && num < top; num++)
			{
				stringBuilder.Append((num == 0) ? "" : ", ").Append(list[num].Key).Append('=')
					.Append(list[num].Value);
			}
			if (list.Count > top)
			{
				stringBuilder.Append($" (+{list.Count - top} tipos)");
			}
			return stringBuilder.ToString();
		}

		private static void WatchLoop()
		{
			float num = 3f;
			bool flag = false;
			int num2 = 0;
			while (!Plugin.Quitting)
			{
				Thread.Sleep(1000);
				try
				{
					double num3 = (double)(Stopwatch.GetTimestamp() - Interlocked.Read(in _beat)) / (double)Stopwatch.Frequency;
					if (++num2 % 5 == 0)
					{
						WriteHeartbeat(num3);
					}
					if (!_watch)
					{
						flag = false;
						num = 3f;
					}
					else if (num3 >= (double)num)
					{
						flag = true;
						num = (float)num3 + 10f;
						_log.LogWarning((object)$"[Vigia] jogo sem atualizar há {num3:F0} s (monstros ~{Monsters}, eventos de ouro {GoldEvents}, lápides {Tombstones}).");
					}
					else if (num3 < 3.0 && flag)
					{
						flag = false;
						num = 3f;
						_log.LogInfo((object)"[Vigia] jogo voltou a responder.");
					}
				}
				catch (Exception)
				{
				}
			}
		}

		private static void OnUnityLog(string condition, string stackTrace, LogType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Invalid comparison between Unknown and I4
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Invalid comparison between Unknown and I4
			if (((int)type != 0 && (int)type != 4 && (int)type != 1) || string.IsNullOrEmpty(condition) || condition.Contains("Ror2Meeeee"))
			{
				return;
			}
			lock (UnityLogLock)
			{
				for (int i = 0; i < KnownNoise.Length; i++)
				{
					if (condition.Contains(KnownNoise[i]) || (stackTrace != null && stackTrace.Contains(KnownNoise[i])))
					{
						KnownCounts[i]++;
						return;
					}
				}
				_unknownCount++;
				int num = condition.IndexOf('\n');
				string text = ((num > 0) ? condition.Substring(0, num) : condition);
				if (text.Length > 140)
				{
					text = text.Substring(0, 140);
				}
				StringBuilder stringBuilder = new StringBuilder(text.Length);
				string text2 = text;
				foreach (char c in text2)
				{
					stringBuilder.Append(char.IsDigit(c) ? '#' : c);
				}
				string text3 = (string.IsNullOrEmpty(stackTrace) ? "" : stackTrace.Split('\n')[0].Trim());
				if (SeenUnknown.Count < 60 && SeenUnknown.Add(stringBuilder?.ToString() + text3))
				{
					ManualLogSource log = _log;
					if (log != null)
					{
						log.LogWarning((object)("[Diag] erro novo do jogo/outro mod (1ª vez): " + text + ((text3.Length > 0) ? (" @ " + text3) : "")));
					}
				}
			}
		}

		public static string Report()
		{
			StringBuilder stringBuilder = new StringBuilder("Diagnóstico:\n");
			stringBuilder.Append($"  ouro: {GoldEvents} eventos, crédito +{CreditGiven:F0}, cortado em {CreditDropped} eventos\n");
			stringBuilder.Append($"  monstros agora ~{Monsters}, pico do estágio {_stageMaxMonsters}, pior frame do estágio {_stageWorstMs:F0} ms\n");
			stringBuilder.Append($"  exceções do mod {Exceptions}, revives {Revives}, lápides {Tombstones}, usos do Grimório {GrimoireUses} (crédito cortado {GrimoireTrimmed:F0}), lâminas fantasmas puladas {GhostBladesSkipped}\n");
			stringBuilder.Append($"  MoneyHub: {MoneyHub.Calls} chamadas, custo do mod ~{MoneyHub.AverageMicros:F1} µs/chamada (amostrado)\n");
			lock (UnityLogLock)
			{
				stringBuilder.Append($"  erros do jogo: {_unknownCount} novos");
				for (int i = 0; i < KnownNoise.Length; i++)
				{
					if (KnownCounts[i] > 0)
					{
						stringBuilder.Append($", {KnownNoise[i]}={KnownCounts[i]}");
					}
				}
			}
			return stringBuilder.ToString();
		}
	}
	internal static class Directors
	{
		private static readonly FieldInfo MoneyWavesField = typeof(CombatDirector).GetField("moneyWaves", BindingFlags.Instance | BindingFlags.NonPublic);

		public static bool Available => MoneyWavesField != null;

		public static Array GetMoneyWaves(CombatDirector d)
		{
			return MoneyWavesField?.GetValue(d) as Array;
		}

		public static bool IsMainMonster(CombatDirector d)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			if ((int)d.teamIndex == 2)
			{
				Array moneyWaves = GetMoneyWaves(d);
				if (moneyWaves != null)
				{
					return moneyWaves.Length > 0;
				}
			}
			return false;
		}
	}
	internal sealed class DropMenu : MonoBehaviour
	{
		private struct Row
		{
			public string Name;

			public string Internal;

			public int Count;

			public Color Color;

			public Texture Tex;

			public Rect Uv;
		}

		private const float Cell = 104f;

		private const float Gap = 12f;

		private static ConfigEntry<string> _key;

		private static DropMenu _instance;

		private static string _preselect;

		private readonly List<Row> _rows = new List<Row>();

		private bool _open;

		private string _selectedName;

		private int _qty = 1;

		private string _qtyText = "1";

		private float _refreshAt;

		private string _status = "";

		private Vector2 _scroll;

		private KeyCode _keyCode = (KeyCode)288;

		private int _cols = 1;

		private float _gridH = 400f;

		private bool _savedCursor;

		private bool _iconLogged;

		private CursorLockMode _lockBefore;

		private bool _visibleBefore;

		private GUIStyle _label;

		private GUIStyle _big;

		private GUIStyle _small;

		private GUIStyle _count;

		private GUIStyle _name;

		private GUIStyle _button;

		private GUIStyle _field;

		public static bool IsOpen
		{
			get
			{
				if (Object.op_Implicit((Object)(object)_instance))
				{
					return _instance._open;
				}
				return false;
			}
		}

		public static void Install(GameObject host, ConfigEntry<string> key)
		{
			if (!Object.op_Implicit((Object)(object)_instance))
			{
				_key = key;
				_instance = host.AddComponent<DropMenu>();
				((Behaviour)_instance).enabled = false;
				_instance.ParseKey();
				RoR2Application.onUpdate += PollKey;
				key.SettingChanged += delegate
				{
					_instance.ParseKey();
				};
			}
		}

		public static string OpenWith(string name)
		{
			if (!Object.op_Implicit((Object)(object)_instance))
			{
				return "Menu indisponível.";
			}
			if (!Object.op_Implicit((Object)(object)Run.instance))
			{
				return "Entre em uma run primeiro.";
			}
			if (!FeatureOn())
			{
				return "Drop desligado (Drop.Enabled=false).";
			}
			if (StatsPanel.IsOpen)
			{
				return "Feche a tela de status primeiro.";
			}
			_preselect = (string.IsNullOrWhiteSpace(name) ? null : name.Trim());
			_instance.SetOpen(open: true);
			return "Tela de soltar itens aberta.";
		}

		private void ParseKey()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (!Enum.TryParse<KeyCode>(_key.Value, ignoreCase: true, out _keyCode))
			{
				_keyCode = (KeyCode)288;
			}
		}

		private static DropFeature DropFeatureInstance()
		{
			Plugin instance = Plugin.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			foreach (Feature feature in instance.Features)
			{
				if (feature is DropFeature result)
				{
					return result;
				}
			}
			return null;
		}

		private static bool FeatureOn()
		{
			return DropFeatureInstance()?.Enabled ?? false;
		}

		private static int MaxQty(Row row)
		{
			DropFeature dropFeature = DropFeatureInstance();
			return DropRules.ClampCount(int.MaxValue, row.Count, dropFeature?.MaxPerCommand ?? 0);
		}

		private static void PollKey()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (Object.op_Implicit((Object)(object)_instance) && Input.GetKeyDown(_instance._keyCode))
				{
					if (_instance._open)
					{
						_instance.SetOpen(open: false);
					}
					else
					{
						OpenWith(null);
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Diag.Log;
				if (log != null)
				{
					log.LogWarning((object)("[DropMenu] falha na tecla: " + ex.Message));
				}
			}
		}

		private void SetOpen(bool open)
		{
			//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_006a: Unknown result type (might be due to invalid IL or missing references)
			if (open != _open)
			{
				_open = open;
				((Behaviour)this).enabled = open;
				if (open)
				{
					_status = "";
					_refreshAt = 0f;
					_qty = 1;
					_qtyText = "1";
					_lockBefore = Cursor.lockState;
					_visibleBefore = Cursor.visible;
					_savedCursor = true;
				}
				else if (_savedCursor)
				{
					Cursor.lockState = _lockBefore;
					Cursor.visible = _visibleBefore;
					_savedCursor = false;
				}
			}
		}

		private int SelectedIndex()
		{
			for (int i = 0; i < _rows.Count; i++)
			{
				if (_rows[i].Internal == _selectedName)
				{
					return i;
				}
			}
			return -1;
		}

		private void Select(int index)
		{
			if (index >= 0 && index < _rows.Count)
			{
				bool num = _rows[index].Internal != _selectedName;
				_selectedName = _rows[index].Internal;
				if (num)
				{
					SetQty(1);
				}
				EnsureVisible(index);
			}
		}

		private void EnsureVisible(int index)
		{
			float num = (float)(index / _cols) * 116f;
			if (num < _scroll.y)
			{
				_scroll.y = num;
			}
			else if (num + 104f > _scroll.y + _gridH)
			{
				_scroll.y = num + 104f - _gridH;
			}
		}

		private void Update()
		{
			try
			{
				if (!_open)
				{
					return;
				}
				if (!Object.op_Implicit((Object)(object)Run.instance))
				{
					SetOpen(open: false);
					return;
				}
				if (Time.unscaledTime >= _refreshAt)
				{
					Refresh();
					_refreshAt = Time.unscaledTime + 0.5f;
				}
				int num = SelectedIndex();
				if (Input.GetKeyDown((KeyCode)275))
				{
					Select((num >= 0) ? Mathf.Min(num + 1, _rows.Count - 1) : 0);
				}
				if (Input.GetKeyDown((KeyCode)276))
				{
					Select((num >= 0) ? Mathf.Max(num - 1, 0) : 0);
				}
				if (Input.GetKeyDown((KeyCode)274))
				{
					Select((num >= 0) ? Mathf.Min(num + _cols, _rows.Count - 1) : 0);
				}
				if (Input.GetKeyDown((KeyCode)273))
				{
					Select((num >= 0) ? Mathf.Max(num - _cols, 0) : 0);
				}
				if (Input.GetKeyDown((KeyCode)61) || Input.GetKeyDown((KeyCode)270) || Input.GetKeyDown((KeyCode)280))
				{
					ChangeQty(1);
				}
				if (Input.GetKeyDown((KeyCode)45) || Input.GetKeyDown((KeyCode)269) || Input.GetKeyDown((KeyCode)281))
				{
					ChangeQty(-1);
				}
				if (Input.GetKeyDown((KeyCode)13) || Input.GetKeyDown((KeyCode)271))
				{
					DropSelected();
				}
			}
			catch (Exception ex)
			{
				SetOpen(open: false);
				ManualLogSource log = Diag.Log;
				if (log != null)
				{
					log.LogWarning((object)("[DropMenu] falha: " + ex.Message));
				}
			}
		}

		private void LateUpdate()
		{
			if (_open)
			{
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
		}

		private void ChangeQty(int delta)
		{
			SetQty(_qty + delta);
		}

		private void SetQty(int value)
		{
			int num = SelectedIndex();
			_qty = ((num < 0) ? 1 : Mathf.Clamp(value, 1, Mathf.Max(1, MaxQty(_rows[num]))));
			_qtyText = _qty.ToString();
		}

		private void OnQtyTyped(string text)
		{
			StringBuilder stringBuilder = new StringBuilder();
			int i;
			for (i = 0; i < text.Length; i++)
			{
				char c = text[i];
				if (c >= '0' && c <= '9')
				{
					stringBuilder.Append(c);
				}
			}
			_qtyText = stringBuilder.ToString();
			if (_qtyText.Length > 0 && int.TryParse(_qtyText, out var result) && result != _qty)
			{
				SetQty(result);
			}
			else if (_qtyText.Length > 0 && !int.TryParse(_qtyText, out i))
			{
				SetQty(int.MaxValue);
			}
		}

		private void Refresh()
		{
			//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_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: 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)
			//IL_0126: 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_00d0: 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)
			_rows.Clear();
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			Inventory val = ((firstLocalUser != null && Object.op_Implicit((Object)(object)firstLocalUser.cachedMaster)) ? firstLocalUser.cachedMaster.inventory : null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			Dictionary<ItemIndex, Texture> dictionary = null;
			foreach (ItemIndex item in val.itemAcquisitionOrder)
			{
				ItemDef itemDef = ItemCatalog.GetItemDef(item);
				int itemCountPermanent = val.GetItemCountPermanent(item);
				if (DropFeature.Droppable(itemDef) && itemCountPermanent > 0)
				{
					Color color = Color.white;
					ItemTierDef itemTierDef = ItemTierCatalog.GetItemTierDef(itemDef.tier);
					if (Object.op_Implicit((Object)(object)itemTierDef))
					{
						color = Color32.op_Implicit(ColorCatalog.GetColor(itemTierDef.colorIndex));
					}
					ResolveIcon(itemDef, item, out var tex, out var uv);
					if (!Object.op_Implicit((Object)(object)tex))
					{
						(dictionary ?? (dictionary = HudIcons())).TryGetValue(item, out tex);
					}
					_rows.Add(new Row
					{
						Name = Language.GetString(itemDef.nameToken),
						Internal = ((Object)itemDef).name,
						Count = itemCountPermanent,
						Color = color,
						Tex = tex,
						Uv = uv
					});
				}
			}
			if (!_iconLogged && _rows.Count > 0)
			{
				_iconLogged = true;
				int count = _rows.FindAll((Row r) => !Object.op_Implicit((Object)(object)r.Tex)).Count;
				ManualLogSource log = Diag.Log;
				if (log != null)
				{
					log.LogInfo((object)string.Format("[DropMenu] ícones: {0} de {1} itens com imagem{2}", _rows.Count - count, _rows.Count, (count > 0) ? " (o resto mostra o nome)" : ""));
				}
				if (count > 0)
				{
					LogIconFields(ItemCatalog.GetItemDef(ItemCatalog.FindItemIndex(_rows.Find((Row x) => !Object.op_Implicit((Object)(object)x.Tex)).Internal)));
				}
			}
			if (_preselect != null)
			{
				int num = _rows.FindIndex((Row r) => string.Equals(r.Internal, _preselect, StringComparison.OrdinalIgnoreCase) || string.Equals(r.Name, _preselect, StringComparison.OrdinalIgnoreCase));
				if (num < 0)
				{
					num = _rows.FindIndex((Row r) => r.Internal.IndexOf(_preselect, StringComparison.OrdinalIgnoreCase) >= 0 || r.Name.IndexOf(_preselect, StringComparison.OrdinalIgnoreCase) >= 0);
				}
				if (num >= 0)
				{
					Select(num);
				}
				else
				{
					_status = "Nenhum item seu combina com '" + _preselect + "'.";
				}
				_preselect = null;
			}
			int num2 = SelectedIndex();
			if (num2 < 0 && _rows.Count > 0)
			{
				_selectedName = _rows[0].Internal;
				num2 = 0;
			}
			if (num2 >= 0 && Mathf.Clamp(_qty, 1, Mathf.Max(1, MaxQty(_rows[num2]))) != _qty)
			{
				SetQty(_qty);
			}
		}

		private void DropSelected()
		{
			int num = SelectedIndex();
			if (num < 0)
			{
				return;
			}
			Row row = _rows[num];
			int num2 = Mathf.Min(_qty, MaxQty(row));
			if (num2 <= 0)
			{
				_status = "Nada para soltar (Drop.MaxPerCommand = 0?).";
				return;
			}
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			if (firstLocalUser == null || !Object.op_Implicit((Object)(object)firstLocalUser.currentNetworkUser))
			{
				_status = "Sem usuário local.";
				return;
			}
			Console.instance.SubmitCmd(firstLocalUser.currentNetworkUser, $"ror2meeeee_drop {row.Internal} {num2}", false);
			_status = $"Soltando {num2}x {row.Name}...";
			row.Count -= num2;
			if (row.Count > 0)
			{
				_rows[num] = row;
				SetQty(_qty);
			}
			else
			{
				_rows.RemoveAt(num);
			}
			_refreshAt = Time.unscaledTime + 1f;
		}

		private void MakeStyles()
		{
			//IL_0014: 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_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_0038: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			//IL_0083: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Expected O, but got Unknown
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected O, but got Unknown
			//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)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Expected O, but got Unknown
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: 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_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Expected O, but got Unknown
			if (_label == null)
			{
				_label = new GUIStyle(GUI.skin.label)
				{
					fontSize = 22,
					wordWrap = true
				};
				_big = new GUIStyle(GUI.skin.label)
				{
					fontSize = 32,
					fontStyle = (FontStyle)1,
					wordWrap = true
				};
				_small = new GUIStyle(GUI.skin.label)
				{
					fontSize = 18,
					wordWrap = true
				};
				_count = new GUIStyle(_small)
				{
					alignment = (TextAnchor)8,
					fontStyle = (FontStyle)1
				};
				_name = new GUIStyle(_big)
				{
					fontSize = 28
				};
				_button = new GUIStyle(GUI.skin.button)
				{
					fontSize = 30,
					fontStyle = (FontStyle)1
				};
				_field = new GUIStyle(GUI.skin.textField)
				{
					fontSize = 40,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)4
				};
			}
		}

		private static void Border(Rect r, Color c, float t)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			Color color = GUI.color;
			GUI.color = c;
			GUI.DrawTexture(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y, ((Rect)(ref r)).width, t), (Texture)(object)Texture2D.whiteTexture);
			GUI.DrawTexture(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).yMax - t, ((Rect)(ref r)).width, t), (Texture)(object)Texture2D.whiteTexture);
			GUI.DrawTexture(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y, t, ((Rect)(ref r)).height), (Texture)(object)Texture2D.whiteTexture);
			GUI.DrawTexture(new Rect(((Rect)(ref r)).xMax - t, ((Rect)(ref r)).y, t, ((Rect)(ref r)).height), (Texture)(object)Texture2D.whiteTexture);
			GUI.color = color;
		}

		private static void ResolveIcon(ItemDef def, ItemIndex idx, out Texture tex, out Rect uv)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0091: 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_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			tex = null;
			uv = new Rect(0f, 0f, 1f, 1f);
			try
			{
				tex = def.pickupIconTexture;
			}
			catch (Exception)
			{
			}
			if (Object.op_Implicit((Object)(object)tex))
			{
				return;
			}
			Sprite val = null;
			try
			{
				PickupDef pickupDef = PickupCatalog.GetPickupDef(PickupCatalog.FindPickupIndex(idx));
				if (pickupDef != null)
				{
					tex = pickupDef.iconTexture;
					if (Object.op_Implicit((Object)(object)tex))
					{
						return;
					}
					val = pickupDef.iconSprite;
				}
			}
			catch (Exception)
			{
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				val = def.pickupIconSprite;
			}
			if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.texture))
			{
				Rect textureRect = val.textureRect;
				Texture2D val2 = (Texture2D)(object)(tex = (Texture)(object)val.texture);
				uv = new Rect(((Rect)(ref textureRect)).x / (float)((Texture)val2).width, ((Rect)(ref textureRect)).y / (float)((Texture)val2).height, ((Rect)(ref textureRect)).width / (float)((Texture)val2).width, ((Rect)(ref textureRect)).height / (float)((Texture)val2).height);
			}
		}

		private static Dictionary<ItemIndex, Texture> HudIcons()
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Invalid comparison between Unknown and I4
			//IL_0046: 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)
			Dictionary<ItemIndex, Texture> dictionary = new Dictionary<ItemIndex, Texture>();
			try
			{
				ItemIcon[] array = Object.FindObjectsOfType<ItemIcon>();
				foreach (ItemIcon val in array)
				{
					if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.image) && Object.op_Implicit((Object)(object)val.image.texture) && (int)val.itemIndex != -1 && !dictionary.ContainsKey(val.itemIndex))
					{
						dictionary[val.itemIndex] = val.image.texture;
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Diag.Log;
				if (log != null)
				{
					log.LogWarning((object)("[DropMenu] não consegui ler os ícones do HUD: " + ex.Message));
				}
			}
			return dictionary;
		}

		private static void LogIconFields(ItemDef def)
		{
			try
			{
				StringBuilder stringBuilder = new StringBuilder("[DropMenu] campos de ícone de ItemDef (" + ((Object)def).name + "):");
				FieldInfo[] fields = typeof(ItemDef).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (fieldInfo.Name.IndexOf("icon", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						stringBuilder.Append(' ').Append(fieldInfo.Name).Append(':')
							.Append(fieldInfo.FieldType.Name)
							.Append((fieldInfo.GetValue(def) == null) ? "=nulo" : "=ok")
							.Append(';');
					}
				}
				PropertyInfo[] properties = typeof(ItemDef).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (PropertyInfo propertyInfo in properties)
				{
					if (propertyInfo.Name.IndexOf("icon", StringComparison.OrdinalIgnoreCase) >= 0 && propertyInfo.GetIndexParameters().Length == 0)
					{
						object obj = null;
						try
						{
							obj = propertyInfo.GetValue(def, null);
						}
						catch (Exception)
						{
						}
						stringBuilder.Append(' ').Append(propertyInfo.Name).Append(':')
							.Append(propertyInfo.PropertyType.Name)
							.Append((obj == null) ? "=nulo" : "=ok")
							.Append(';');
					}
				}
				ManualLogSource log = Diag.Log;
				if (log != null)
				{
					log.LogInfo((object)stringBuilder.ToString());
				}
			}
			catch (Exception ex2)
			{
				ManualLogSource log2 = Diag.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("[DropMenu] diagnóstico de ícones falhou: " + ex2.Message));
				}
			}
		}

		private static void DrawIcon(Rect r, Texture tex, Rect uv, Color fallback)
		{
			//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_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)tex))
			{
				GUI.DrawTextureWithTexCoords(r, tex, uv);
				return;
			}
			Color color = GUI.color;
			GUI.color = new Color(fallback.r * 0.35f, fallback.g * 0.35f, fallback.b * 0.35f, 1f);
			GUI.DrawTexture(r, (Texture)(object)Texture2D.whiteTexture);
			GUI.color = color;
		}

		private void OnGUI()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: 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_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_01ee: 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_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0345: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			//IL_0701: Unknown result type (might be due to invalid IL or missing references)
			//IL_0483: Unknown result type (might be due to invalid IL or missing references)
			//IL_0491: Unknown result type (might be due to invalid IL or missing references)
			//IL_0498: Unknown result type (might be due to invalid IL or missing references)
			//IL_04af: Unknown result type (might be due to invalid IL or missing references)
			//IL_04db: Unknown result type (might be due to invalid IL or missing references)
			//IL_0514: Unknown result type (might be due to invalid IL or missing references)
			//IL_0559: Unknown result type (might be due to invalid IL or missing references)
			//IL_0590: Unknown result type (might be due to invalid IL or missing references)
			//IL_037a: Unknown result type (might be due to invalid IL or missing references)
			//IL_035a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0364: Unknown result type (might be due to invalid IL or missing references)
			//IL_073d: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_061c: Unknown result type (might be due to invalid IL or missing references)
			//IL_078b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0654: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_068c: Unknown result type (might be due to invalid IL or missing references)
			//IL_06bc: Unknown result type (might be due to invalid IL or missing references)
			if (!_open)
			{
				return;
			}
			MakeStyles();
			float num = Mathf.Max(0.8f, (float)Screen.height / 1080f) * 1.15f;
			Matrix4x4 matrix = GUI.matrix;
			GUI.matrix = Matrix4x4.Scale(new Vector3(num, num, 1f));
			float num2 = (float)Screen.width / num;
			float num3 = (float)Screen.height / num;
			float num4 = Mathf.Min(1180f, num2 - 60f);
			float num5 = Mathf.Min(720f, num3 - 60f);
			Rect val = default(Rect);
			((Rect)(ref val))..ctor((num2 - num4) / 2f, (num3 - num5) / 2f, num4, num5);
			Color color = GUI.color;
			GUI.color = new Color(0f, 0f, 0f, 0.92f);
			GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture);
			GUI.color = color;
			Border(val, new Color(0.9f, 0.8f, 0.4f), 3f);
			GUI.Label(new Rect(((Rect)(ref val)).x + 24f, ((Rect)(ref val)).y + 12f, num4 - 48f, 44f), "SOLTAR ITENS", _big);
			float num6 = num4 * 0.58f;
			Rect val2 = default(Rect);
			((Rect)(ref val2))..ctor(((Rect)(ref val)).x + 24f, ((Rect)(ref val)).y + 70f, num6, num5 - 150f);
			_gridH = ((Rect)(ref val2)).height;
			_cols = Mathf.Max(1, (int)((((Rect)(ref val2)).width - 24f) / 116f));
			int num7 = Mathf.Max(1, Mathf.CeilToInt((float)_rows.Count / (float)_cols));
			Rect val3 = default(Rect);
			((Rect)(ref val3))..ctor(0f, 0f, (float)_cols * 116f, (float)num7 * 116f);
			int num8 = SelectedIndex();
			if (_rows.Count == 0)
			{
				GUI.Label(val2, "Você não tem itens que possam ser soltos.", _label);
			}
			_scroll = GUI.BeginScrollView(val2, _scroll, val3);
			Rect val4 = default(Rect);
			for (int i = 0; i < _rows.Count; i++)
			{
				((Rect)(ref val4))..ctor((float)(i % _cols) * 116f, (float)(i / _cols) * 116f, 104f, 104f);
				Color color2 = GUI.color;
				GUI.color = new Color(0.15f, 0.15f, 0.15f, 1f);
				GUI.DrawTexture(val4, (Texture)(object)Texture2D.whiteTexture);
				GUI.color = color2;
				DrawIcon(new Rect(((Rect)(ref val4)).x + 6f, ((Rect)(ref val4)).y + 6f, 92f, 92f), _rows[i].Tex, _rows[i].Uv, _rows[i].Color);
				if (!Object.op_Implicit((Object)(object)_rows[i].Tex))
				{
					GUI.Label(new Rect(((Rect)(ref val4)).x + 4f, ((Rect)(ref val4)).y + 4f, 96f, 70f), _rows[i].Name, _small);
				}
				Border(val4, (Color)((i == num8) ? new Color(1f, 0.9f, 0.3f) : (_rows[i].Color * 0.7f)), (i == num8) ? 5f : 2f);
				GUI.Label(new Rect(((Rect)(ref val4)).x, ((Rect)(ref val4)).yMax - 30f, ((Rect)(ref val4)).width - 6f, 28f), "x" + _rows[i].Count, _count);
				if (GUI.Button(val4, GUIContent.none, GUIStyle.none))
				{
					Select(i);
				}
			}
			GUI.EndScrollView();
			float num9 = ((Rect)(ref val)).x + 24f + num6 + 24f;
			float num10 = ((Rect)(ref val)).xMax - num9 - 24f;
			if (num8 >= 0)
			{
				Row row = _rows[num8];
				DrawIcon(new Rect(num9, ((Rect)(ref val)).y + 74f, 150f, 150f), row.Tex, row.Uv, row.Color);
				_name.normal.textColor = row.Color;
				GUI.Label(new Rect(num9 + 164f, ((Rect)(ref val)).y + 74f, num10 - 164f, 100f), row.Name, _name);
				GUI.Label(new Rect(num9 + 164f, ((Rect)(ref val)).y + 170f, num10 - 164f, 50f), $"Você tem {row.Count}", _label);
				int num11 = MaxQty(row);
				GUI.Label(new Rect(num9, ((Rect)(ref val)).y + 240f, num10, 40f), $"Quantidade a soltar (máx. {num11} por vez)", _label);
				string text = GUI.TextField(new Rect(num9, ((Rect)(ref val)).y + 284f, num10, 72f), _qtyText, 6, _field);
				if (text != _qtyText)
				{
					OnQtyTyped(text);
				}
				float num12 = (num10 - 24f) / 4f;
				float num13 = ((Rect)(ref val)).y + 366f;
				if (GUI.Button(new Rect(num9, num13, num12, 64f), "−1", _button))
				{
					ChangeQty(-1);
				}
				if (GUI.Button(new Rect(num9 + (num12 + 8f), num13, num12, 64f), "+1", _button))
				{
					ChangeQty(1);
				}
				if (GUI.Button(new Rect(num9 + 2f * (num12 + 8f), num13, num12, 64f), "+5", _button))
				{
					ChangeQty(5);
				}
				if (GUI.Button(new Rect(num9 + 3f * (num12 + 8f), num13, num12, 64f), "+10", _button))
				{
					ChangeQty(10);
				}
				if (GUI.Button(new Rect(num9, num13 + 80f, num10, 90f), $"SOLTAR {_qty}x", _button))
				{
					DropSelected();
				}
			}
			else
			{
				GUI.Label(new Rect(num9, ((Rect)(ref val)).y + 80f, num10, 120f), "Clique em um item para escolher.", _label);
			}
			GUI.Label(new Rect(((Rect)(ref val)).x + 24f, ((Rect)(ref val)).yMax - 66f, num4 - 48f, 56f), ((_status.Length > 0) ? (_status + "\n") : "") + "Clique no item · setas movem · digite ou +/- quantidade · Enter solta · " + _key.Value + " fecha", _small);
			GUI.matrix = matrix;
		}
	}
	internal static class DroppedGrants
	{
		private static readonly Dictionary<ItemIndex, int> Pending = new Dictionary<ItemIndex, int>();

		private static int _frame = -1;

		private static ItemIndex _index = (ItemIndex)(-1);

		private static bool _result;

		public static void Note(ItemIndex index, int count)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (count > 0)
			{
				Pending.TryGetValue(index, out var value);
				Pending[index] = value + count;
			}
		}

		public static bool IsDropped(ItemIndex index)
		{
			//IL_0022: 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_000e: 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_0058: 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)
			int frameCount = Time.frameCount;
			if (frameCount == _frame && index == _index)
			{
				return _result;
			}
			_frame = frameCount;
			_index = index;
			_result = false;
			if (Pending.TryGetValue(index, out var value) && value > 0)
			{
				if (value == 1)
				{
					Pending.Remove(index);
				}
				else
				{
					Pending[index] = value - 1;
				}
				_result = true;
			}
			return _result;
		}

		public static void Clear()
		{
			Pending.Clear();
			_frame = -1;
		}
	}
	public abstract class Feature
	{
		private readonly ConfigEntry<bool> _enabledEntry;

		private int _failureCount;

		private bool _shutdownByFailures;

		private readonly List<string> _hookResults = new List<string>();

		public string Name { get; }

		public bool Enabled { get; private set; }

		public bool ConfigEnabled
		{
			get
			{
				if (_enabledEntry != null)
				{
					return _enabledEntry.Value;
				}
				return true;
			}
		}

		internal ConfigEntry<bool> EnabledEntry => _enabledEntry;

		public int FailureCount => _failureCount;

		public bool ShutdownByFailures => _shutdownByFailures;

		public IReadOnlyList<string> HookResults => _hookResults;

		protected Cfg Cfg { get; }

		protected ManualLogSource Log { get; }

		protected Feature(string name, Cfg cfg, ManualLogSource log, string summary, bool enabledByDefault = false)
			: this(name, cfg, log, cfg.BindEnabled(name, summary, enabledByDefault))
		{
		}

		protected Feature(string name, Cfg cfg, ManualLogSource log, ConfigEntry<bool> enabledEntry)
		{
			Name = name;
			Cfg = cfg;
			Log = log;
			_enabledEntry = enabledEntry;
		}

		public void Enable()
		{
			if (Enabled || _shutdownByFailures)
			{
				return;
			}
			_hookResults.Clear();
			try
			{
				OnEnable();
				Enabled = true;
				Log.LogInfo((object)(Name + ": hooks registrados"));
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"{Name}: falha ao registrar hooks, feature desligada: {arg}");
				RemoveHooksQuietly();
			}
		}

		public void Disable()
		{
			if (Enabled)
			{
				Enabled = false;
				RemoveHooksQuietly();
			}
		}

		public virtual void ResetRunState()
		{
		}

		internal void ResetRunStateSafe()
		{
			try
			{
				ResetRunState();
			}
			catch (Exception ex)
			{
				if (Enabled)
				{
					Fail(ex);
				}
				else
				{
					Log.LogError((object)$"{Name}: falha em ResetRunState (feature desligada, não contada): {ex}");
				}
			}
		}

		protected void Fail(Exception e)
		{
			if (!_shutdownByFailures)
			{
				_failureCount++;
				Diag.Exceptions++;
				Log.LogError((object)$"{Name}: falha {_failureCount}/{Cfg.MaxFailures}: {e}");
				if (_failureCount >= Cfg.MaxFailures && !_shutdownByFailures)
				{
					_shutdownByFailures = true;
					Disable();
					Log.LogWarning((object)$"{Name}: desligada após {_failureCount} falhas.");
				}
			}
		}

		protected void Track(string hookName, Action register)
		{
			try
			{
				register();
				_hookResults.Add(hookName + ": ok");
			}
			catch (Exception ex)
			{
				_hookResults.Add(hookName + ": FALHA (" + ex.GetType().Name + ": " + ex.Message + ")");
				throw;
			}
		}

		protected abstract void OnEnable();

		protected abstract void OnDisable();

		private void RemoveHooksQuietly()
		{
			try
			{
				OnDisable();
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"{Name}: falha ao remover hooks: {arg}");
			}
		}
	}
	internal static class ItemClassifier
	{
		public static bool IsUnique(ItemIndex index)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0004: 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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if ((int)index != -1)
			{
				if (!TaxReliefItems.IsReliefItem(index) && index != CanoItem.Index)
				{
					return index == HordeItem.Index;
				}
				return true;
			}
			return false;
		}

		public static ItemKind Classify(ItemDef def, bool temporaryPickup)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected I4, but got Unknown
			if (temporaryPickup)
			{
				return (ItemKind)6;
			}
			if (IsUnique(def.itemIndex))
			{
				return (ItemKind)9;
			}
			if (def.ContainsTag((ItemTag)10))
			{
				return (ItemKind)7;
			}
			ItemTier tier = def.tier;
			switch ((int)tier)
			{
			case 0:
				return (ItemKind)0;
			case 1:
				return (ItemKind)1;
			case 2:
				return (ItemKind)2;
			case 4:
				return (ItemKind)3;
			case 3:
				return (ItemKind)4;
			case 6:
			case 7:
			case 8:
			case 9:
				return (ItemKind)5;
			default:
				return (ItemKind)10;
			}
		}
	}
	internal static class ModItem
	{
		public static ItemDef Register(string name, string token, ItemTier tier, ItemTag[] tags, string iconResource, Color32 iconFallback, string displayName, string pickup, string description, string lore, ManualLogSource log, string modelKey = null)
		{
			//IL_0083: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Expected O, but got Unknown
			try
			{
				ItemDef val = ScriptableObject.CreateInstance<ItemDef>();
				((Object)val).name = name;
				val.nameToken = token + "_NAME";
				val.pickupToken = token + "_PICKUP";
				val.descriptionToken = token + "_DESC";
				val.loreToken = token + "_LORE";
				val.canRemove = true;
				val.hidden = false;
				val.tags = tags;
				typeof(ItemDef).GetField("deprecatedTier", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(val, tier);
				val.pickupIconSprite = TitheArtifact.LoadIcon(iconResource, iconFallback);
				val.pickupModelPrefab = Model(modelKey, name, log);
				LanguageAPI.Add(token + "_NAME", displayName);
				LanguageAPI.Add(token + "_PICKUP", pickup);
				LanguageAPI.Add(token + "_DESC", description);
				LanguageAPI.Add(token + "_LORE", lore);
				if (!ItemAPI.Add(new CustomItem(val, Array.Empty<ItemDisplayRule>())))
				{
					log.LogError((object)(name + ": ItemAPI.Add recusou o item."));
					return null;
				}
				log.LogInfo((object)(name + ": item registrado."));
				return val;
			}
			catch (Exception arg)
			{
				log.LogError((object)$"{name}: falha ao registrar o item (o plugin segue sem ele): {arg}");
				return null;
			}
		}

		public static void Corrupt(ItemDef normal, ItemDef voidItem, ManualLogSource log)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: 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_008d: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)normal) || !Object.op_Implicit((Object)(object)voidItem))
			{
				return;
			}
			try
			{
				ItemRelationshipType val = Addressables.LoadAssetAsync<ItemRelationshipType>((object)"RoR2/DLC1/Common/ContagiousItem.asset").WaitForCompletion();
				if (!Object.op_Implicit((Object)(object)val))
				{
					log.LogWarning((object)(((Object)voidItem).name + ": tipo ContagiousItem indisponível; não corrompe."));
					return;
				}
				ItemRelationshipProvider val2 = ScriptableObject.CreateInstance<ItemRelationshipProvider>();
				((Object)val2).name = ((Object)voidItem).name + "Contagion";
				val2.relationshipType = val;
				val2.relationships = (Pair[])(object)new Pair[1]
				{
					new Pair
					{
						itemDef1 = normal,
						itemDef2 = voidItem
					}
				};
				if (!ContentAddition.AddItemRelationshipProvider(val2))
				{
					log.LogWarning((object)(((Object)voidItem).name + ": ContentAddition recusou a corrupção."));
				}
			}
			catch (Exception ex)
			{
				log.LogWarning((object)(((Object)voidItem).name + ": falha ao registrar a corrupção (itens seguem sem ela): " + ex.Message));
			}
		}

		public static GameObject Model(string key, string owner, ManualLogSource log)
		{
			//IL_0004: 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)
			if (key != null)
			{
				try
				{
					GameObject val = Addressables.LoadAssetAsync<GameObject>((object)key).WaitForCompletion();
					if (Object.op_Implicit((Object)(object)val))
					{
						return val;
					}
					log.LogWarning((object)(owner + ": modelo " + key + " indisponível; usando o placeholder."));
				}
				catch (Exception ex)
				{
					log.LogWarning((object)(owner + ": modelo " + key + " indisponível (" + ex.GetType().Name + "); usando o placeholder."));
				}
			}
			try
			{
				return LegacyResourcesAPI.Load<GameObject>("Prefabs/PickupModels/PickupMystery");
			}
			catch (Exception ex2)
			{
				log.LogWarning((object)(owner + ": modelo placeholder indisponível (" + ex2.GetType().Name + "); o item ficará invisível no chão."));
				return null;
			}
		}
	}
	internal static class ModOptions
	{
		private static readonly string[] RestartKeys = new string[2] { "ProbeEmptyHook", "ProbeAutoWindowSeconds" };

		[MethodImpl(MethodImplOptions.NoInlining)]
		public static void Register(Cfg cfg, ManualLogSource log)
		{
			//IL_001b: 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)
			try
			{
				ModSettingsManager.SetModDescription("Multiplicador e compartilhamento de itens, dificuldade ajustável com progressão entre runs, artefatos do Dízimo e Taxade (com os itens Capitalismo), corte de partículas e ferramentas de medição. Cada seção tem um Enabled que explica o que ela faz. Só o host precisa configurar; alterações valem na hora ou a partir do próximo estágio.", "com.sawcunha.ror2meeeee", "Ror2Meeeee");
				Sprite val = TitheArtifact.LoadIcon("mod_icon.png", default(Color32));
				if (Object.op_Implicit((Object)(object)val))
				{
					ModSettingsManager.SetModIcon(val, "com.sawcunha.ror2meeeee", "Ror2Meeeee");
				}
				int num = 0;
				foreach (ConfigEntryBase entry in cfg.Entries)
				{
					BaseOption val2 = Create(entry);
					if (val2 != null)
					{
						ModSettingsManager.AddOption(val2, "com.sawcunha.ror2meeeee", "Ror2Meeeee");
						num++;
					}
				}
				log.LogInfo((object)$"Opções na tela de mods: {num} entradas.");
			}
			catch (Exception ex)
			{
				log.LogWarning((object)("Tela de mods indisponível (o plugin segue; use o .cfg): " + ex.GetType().Name + ": " + ex.Message));
			}
		}

		private static BaseOption Create(ConfigEntryBase entry)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			bool flag = Array.IndexOf(RestartKeys, entry.Definition.Key) >= 0;
			if (!(entry is ConfigEntry<bool> val))
			{
				if (!(entry is ConfigEntry<int> val2))
				{
					if (!(entry is ConfigEntry<float> val3))
					{
						if (entry is ConfigEntry<string> val4)
						{
							return (BaseOption)new StringInputFieldOption(val4, flag);
						}
						if (!entry.SettingType.IsEnum)
						{
							return null;
						}
						return (BaseOption)new ChoiceOption(entry, flag);
					}
					return (BaseOption)new FloatFieldOption(val3, flag);
				}
				return (BaseOption)new IntFieldOption(val2, flag);
			}
			return (BaseOption)new CheckBoxOption(val, flag);
		}
	}
	internal static class MoneyHub
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static hook_GiveMoney_uint_bool <0>__OnGiveMoney;
		}

		private static Func<CharacterMaster, uint, uint> _before;

		private static Action<CharacterMaster, uint> _after;

		private static bool _hooked;

		public static long Calls;

		private static long _sampleTicks;

		private static long _samples;

		public static double AverageMicros
		{
			get
			{
				if (_samples != 0L)
				{
					return (double)_sampleTicks * 1000000.0 / (double)Stopwatch.Frequency / (double)_samples;
				}
				return 0.0;
			}
		}

		public static void SetBefore(Func<CharacterMaster, uint, uint> f)
		{
			_before = f;
			Sync();
		}

		public static void SetAfter(Action<CharacterMaster, uint> f)
		{
			_after = f;
			Sync();
		}

		private static void Sync()
		{
			//IL_0051: 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_005c: Expected O, but got Unknown
			//IL_002f: 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_003a: Expected O, but got Unknown
			bool flag = _before != null || _after != null;
			if (flag == _hooked)
			{
				return;
			}
			if (flag)
			{
				object obj = <>O.<0>__OnGiveMoney;
				if (obj == null)
				{
					hook_GiveMoney_uint_bool val = OnGiveMoney;
					<>O.<0>__OnGiveMoney = val;
					obj = (object)val;
				}
				CharacterMaster.GiveMoney_uint_bool += (hook_GiveMoney_uint_bool)obj;
			}
			else
			{
				object obj2 = <>O.<0>__OnGiveMoney;
				if (obj2 == null)
				{
					hook_GiveMoney_uint_bool val2 = OnGiveMoney;
					<>O.<0>__OnGiveMoney = val2;
					obj2 = (object)val2;
				}
				CharacterMaster.GiveMoney_uint_bool -= (hook_GiveMoney_uint_bool)obj2;
			}
			_hooked = flag;
		}

		private static void OnGiveMoney(orig_GiveMoney_uint_bool orig, CharacterMaster self, uint amount, bool bypassStatManager)
		{
			uint arg = amount;
			bool num = (++Calls & 0xF) == 0;
			long num2 = (num ? Stopwatch.GetTimestamp() : 0);
			Func<CharacterMaster, uint, uint> before = _before;
			if (before != null)
			{
				amount = before(self, amount);
			}
			long num3 = (num ? Stopwatch.GetTimestamp() : 0);
			orig.Invoke(self, amount, bypassStatManager);
			long num4 = (num ? Stopwatch.GetTimestamp() : 0);
			_after?.Invoke(self, arg);
			if (num)
			{
				_sampleTicks += num3 - num2 + (Stopwatch.GetTimestamp() - num4);
				_samples++;
			}
		}
	}
	internal sealed class Overlay : MonoBehaviour
	{
		private sealed class Marker
		{
			public object Key;

			public Vector3 Position;

			public Transform Follow;

			public string Label;

			public Color Color;

			public int Size;
		}

		private static Overlay _instance;

		private static readonly List<Marker> Markers = new List<Marker>();

		private static string _banner;

		private static float _bannerUntil;

		private static GUIStyle _style;

		public static void Install(GameObject host)
		{
			if (!Object.op_Implicit((Object)(object)_instance))
			{
				_instance = host.AddComponent<Overlay>();
			}
		}

		public static void Banner(string text, float seconds = 8f)
		{
			_banner = text;
			_bannerUntil = Time.unscaledTime + seconds;
		}

		public static void Mark(object key, Vector3 position, string label, Color color, int size = 18)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			Add(key, position, null, label, color, size);
		}

		public static void Mark(object key, Transform follow, string label, Color color, int size = 18)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			Add(key, Vector3.zero, follow, label, color, size);
		}

		public static void Unmark(object key)
		{
			Markers.RemoveAll((Marker m) => m.Key == key);
		}

		public static void Clear()
		{
			Markers.Clear();
		}

		private static void Add(object key, Vector3 position, Transform follow, string label, Color color, int size)
		{
			//IL_0018: 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_002d: 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)
			Unmark(key);
			Markers.Add(new Marker
			{
				Key = key,
				Position = position,
				Follow = follow,
				Label = label,
				Color = color,
				Size = size
			});
		}

		private static Camera SceneCamera()
		{
			ReadOnlyCollection<CameraRigController> readOnlyInstancesList = CameraRigController.readOnlyInstancesList;
			for (int i = 0; i < readOnlyInstancesList.Count; i++)
			{
				if (Object.op_Implicit((Object)(object)readOnlyInstancesList[i]) && Object.op_Implicit((Object)(object)readOnlyInstancesList[i].sceneCam) && ((Behaviour)readOnlyInstancesList[i].sceneCam).enabled)
				{
					return readOnlyInstancesList[i].sceneCam;
				}
			}
			return Camera.main;
		}

		private void OnGUI()
		{
			//IL_0038: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			//IL_007e: 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_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: 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)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: 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_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: 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_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			bool flag = _banner != null && Time.unscaledTime < _bannerUntil;
			if (!flag && Markers.Count == 0)
			{
				return;
			}
			if (_style == null)
			{
				_style = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)4,
					fontSize = 18,
					fontStyle = (FontStyle)1,
					wordWrap = false
				};
			}
			if (flag)
			{
				DrawText(new Rect(0f, (float)Screen.height * 0.12f, (float)Screen.width, 40f), _banner, new Color(1f, 0.9f, 0.4f), 18);
			}
			if (Markers.Count == 0)
			{
				return;
			}
			Camera val = SceneCamera();
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			for (int num = Markers.Count - 1; num >= 0; num--)
			{
				Marker marker = Markers[num];
				if ((Object)(object)marker.Follow != (Object)null && !Object.op_Implicit((Object)(object)marker.Follow))
				{
					Markers.RemoveAt(num);
				}
				else
				{
					Vector3 val2 = (Object.op_Implicit((Object)(object)marker.Follow) ? (marker.Follow.position + Vector3.up * 2f) : (marker.Position + Vector3.up * 2f));
					Vector3 val3 = val.WorldToScreenPoint(val2);
					bool num2 = val3.z < 0f;
					if (num2)
					{
						val3.x = (float)Screen.width - val3.x;
						val3.y = (float)Screen.height - val3.y;
					}
					bool num3 = !num2 && val3.x > 60f && val3.x < (float)Screen.width - 60f && val3.y > 60f && val3.y < (float)Screen.height - 60f;
					float num4 = Mathf.Clamp(val3.x, 60f, (float)Screen.width - 60f);
					float num5 = Mathf.Clamp(val3.y, 60f, (float)Screen.height - 60f);
					string text = string.Concat(str2: $" ({Vector3.Distance(((Component)val).transform.position, val2):F0} m)", str0: num3 ? "▼ " : "◆ ", str1: marker.Label);
					float num6 = (float)marker.Size * 2f;
					DrawText(new Rect(num4 - 300f, (float)Screen.height - num5 - num6 / 2f, 600f, num6), text, marker.Color, marker.Size);
				}
			}
		}

		private static void DrawText(Rect r, string text, Color color, int size)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			_style.fontSize = size;
			Color color2 = GUI.color;
			GUI.color = Color.black;
			GUI.Label(new Rect(((Rect)(ref r)).x + 1.5f, ((Rect)(ref r)).y + 1.5f, ((Rect)(ref r)).width, ((Rect)(ref r)).height), text, _style);
			GUI.color = color;
			GUI.Label(r, text, _style);
			GUI.color = color2;
		}
	}
	internal static class ProcModel
	{
		private static GameObject _holder;

		public static void AddLathe(Vector2[] profile, float[] v, int sides, Matrix4x4 m, List<Vector3> verts, List<Vector2> uvs, List<int> tris)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: 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_0121: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < profile.Length - 1; i++)
			{
				Vector2 val = profile[i];
				Vector2 val2 = profile[i + 1];
				int count = verts.Count;
				for (int j = 0; j <= sides; j++)
				{
					float num = (float)j * 2f * MathF.PI / (float)sides;
					float num2 = Mathf.Cos(num);
					float num3 = Mathf.Sin(num);
					verts.Add(((Matrix4x4)(ref m)).MultiplyPoint3x4(new Vector3(val.x * num2, val.y, val.x * num3)));
					verts.Add(((Matrix4x4)(ref m)).MultiplyPoint3x4(new Vector3(val2.x * num2, val2.y, val2.x * num3)));
					uvs.Add(new Vector2((float)j / (float)sides, v[i]));
					uvs.Add(new Vector2((float)j / (float)sides, v[i + 1]));
				}
				for (int k = 0; k < sides; k++)
				{
					int num4 = count + k * 2;
					int item = num4 + 1;
					int item2 = num4 + 2;
					int item3 = num4 + 3;
					if (val.x > 0f)
					{
						tris.Add(num4);
						tris.Add(item);
						tris.Add(item2);
					}
					if (val2.x > 0f)
					{
						tris.Add(item);
						tris.Add(item3);
						tris.Add(item2);
					}
				}
			}
		}

		public static GameObject Build(string name, List<Vector3> verts, List<Vector2> uvs, List<int> tris, Texture2D tex, float smoothness, Color emission, ManualLogSource log)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Expected O, but got Unknown
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Expected O, but got Unknown
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Expected O, but got Unknown
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Expected O, but got Unknown
			try
			{
				Shader val = Addressables.LoadAssetAsync<Shader>((object)"RoR2/Base/Shaders/HGStandard.shader").WaitForCompletion();
				if (!Object.op_Implicit((Object)(object)val))
				{
					log.LogWarning((object)(name + ": shader HGStandard indisponível; mantendo o modelo do jogo."));
					return null;
				}
				Bounds val2 = default(Bounds);
				((Bounds)(ref val2))..ctor(verts[0], Vector3.zero);
				foreach (Vector3 vert in verts)
				{
					((Bounds)(ref val2)).Encapsulate(vert);
				}
				for (int i = 0; i < verts.Count; i++)
				{
					int index = i;
					verts[index] -= ((Bounds)(ref val2)).center;
				}
				Mesh val3 = new Mesh
				{
					name = name + "Mesh"
				};
				val3.SetVertices(verts);
				val3.SetUVs(0, uvs);
				val3.SetTriangles(tris, 0);
				val3.RecalculateNormals();
				val3.RecalculateBounds();
				Material val4 = new Material(val)
				{
					name = name + "Mat"
				};
				val4.SetColor("_Color", Color.white);
				val4.SetTexture("_MainTex", (Texture)(object)tex);
				val4.SetFloat("_Smoothness", smoothness);
				if (((Color)(ref emission)).maxColorComponent > 0f)
				{
					val4.SetColor("_EmColor", emission);
					val4.SetFloat("_EmPower", 1f);
				}
				if (!Object.op_Implicit((Object)(object)_holder))
				{
					_holder = new GameObject("Ror2MeeeeeModels");
					_holder.SetActive(false);
					Object.DontDestroyOnLoad((Object)(object)_holder);
				}
				GameObject val5 = new GameObject(name);
				val5.transform.SetParent(_holder.transform, false);
				val5.AddComponent<MeshFilter>().sharedMesh = val3;
				((Renderer)val5.AddComponent<MeshRenderer>()).sharedMaterial = val4;
				return val5;
			}
			catch (Exception ex)
			{
				log.LogWarning((object)(name + ": falha ao gerar o modelo (" + ex.GetType().Name + "); mantendo o modelo do jogo."));
				return null;
			}
		}

		public static Texture2D Bands(string name, params (Color32 a, Color32 b)[] bands)
		{
			//IL_0006: 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_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(32, 32, (TextureFormat)4, false)
			{
				name = name,
				wrapMode = (TextureWrapMode)1,
				filterMode = (FilterMode)(bands.Length <= 1)
			};
			Random random = new Random(1);
			Color32[] array = (Color32[])(object)new Color32[1024];
			for (int i = 0; i < 32; i++)
			{
				(Color32, Color32) tuple = bands[Math.Min(bands.Length - 1, i * bands.Length / 32)];
				for (int j = 0; j < 32; j++)
				{
					array[i * 32 + j] = Color32.Lerp(tuple.Item1, tuple.Item2, (float)random.NextDouble());
				}
			}
			val.SetPixels32(array);
			val.Apply(false, true);
			return val;
		}
	}
	internal static class PurchaseHub
	{
		private static Action<PayCostContext, PayCostResults> _bazaar;

		private static Action<PayCostContext, PayCostResults> _spend;

		private static Action<PayCostContext, PayCostResults> _tax;

		private static bool _hooked;

		public static void SetBazaar(Action<PayCostContext, PayCostResults> f)
		{
			_bazaar = f;
			Sync();
		}

		public static void SetSpend(Action<PayCostContext, PayCostResults> f)
		{
			_spend = f;
			Sync();
		}

		public static void SetTax(Action<PayCostContext, PayCostResults> f)
		{
			_tax = f;
			Sync();
		}

		private static void Sync()
		{
			bool flag = _bazaar != null || _spend != null || _tax != null;
			if (flag != _hooked)
			{
				if (flag)
				{
					PurchaseInteraction.onPurchaseGlobalServer += OnPurchase;
				}
				else
				{
					PurchaseInteraction.onPurchaseGlobalServer -= OnPurchase;
				}
				_hooked = flag;
			}
		}

		private static void OnPurchase(PayCostContext ctx, PayCostResults results)
		{
			_bazaar?.Invoke(ctx, results);
			_spend?.Invoke(ctx, results);
			_tax?.Invoke(ctx, results);
		}
	}
	internal sealed class StatsPanel : MonoBehaviour
	{
		private const float RefreshSeconds = 0.25f;

		private static ConfigEntry<string> _key;

		private static StatsPanel _instance;

		private KeyCode _keyCode = (KeyCode)289;

		private bool _open;

		private float _refreshAt;

		private string _now = "";

		private string _run = "";

		private string _title = "";

		private GUIStyle _label;

		private GUIStyle _big;

		private GUIStyle _head;

		private readonly StringBuilder _sb = new StringBuilder(512);

		public static bool IsOpen
		{
			get
			{
				if (Object.op_Implicit((Object)(object)_instance))
				{
					return _instance._open;
				}
				return false;
			}
		}

		public static void Install(GameObject host, ConfigEntry<string> key)
		{
			if (!Object.op_Implicit((Object)(object)_instance))
			{
				_key = key;
				_instance = host.AddComponent<StatsPanel>();
				((Behaviour)_instance).enabled = false;
				_instance.ParseKey();
				key.SettingChanged += delegate
				{
					_instance.ParseKey();
				};
				RoR2Application.onUpdate += PollKey;
				StatsSyncMessage.Install();
			}
		}

		private void ParseKey()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (!Enum.TryParse<KeyCode>(_key.Value, ignoreCase: true, out _keyCode))
			{
				_keyCode = (KeyCode)289;
			}
		}

		private static void PollKey()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (Object.op_Implicit((Object)(object)_instance) && Input.GetKeyDown(_instance._keyCode) && (_instance._open || !DropMenu.IsOpen))
				{
					_instance.SetOpen(!_instance._open && Object.op_Implicit((Object)(object)Run.instance));
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Diag.Log;
				if (log != null)
				{
					log.LogWarning((object)("[Stats] falha na tecla: " + ex.Message));
				}
			}
		}

		private void SetOpen(bool open)
		{
			_open = open;
			((Behaviour)this).enabled = open;
			_refreshAt = 0f;
		}

		private void Update()
		{
			if (!_open)
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)Run.instance))
			{
				SetOpen(open: false);
			}
			else
			{
				if (Time.unscaledTime < _refreshAt)
				{
					return;
				}
				_refreshAt = Time.unscaledTime + 0.25f;
				try
				{
					Refresh();
				}
				catch (Exception ex)
				{
					SetOpen(open: false);
					ManualLogSource log = Diag.Log;
					if (log != null)
					{
						log.LogWarning((object)("[Stats] falha: " + ex.Message));
					}
				}
			}
		}

		private static string N(double v)
		{
			return ShortNumber.Format(v);
		}

		private static bool TryTotals(CharacterMaster master, bool own, out RunTotals totals)
		{
			//IL_003a: 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)
			totals = default(RunTotals);
			if (!Object.op_Implicit((Object)(object)master))
			{
				return false;
			}
			if (NetworkServer.active || own)
			{
				StatSheet val = PlayerStatsComponent.FindMasterStatSheet(master);
				if (val == null)
				{
					return false;
				}
				totals = RunTotals.From(val);
				return true;
			}
			Dictionary<uint, RunTotals> remote = StatsSyncMessage.Remote;
			NetworkInstanceId netId = ((NetworkBehaviour)master).netId;
			return remote.TryGetValue(((NetworkInstanceId)(ref netId)).Value, out totals);
		}

		private void Refresh()
		{
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			CharacterMaster val = ((firstLocalUser != null) ? firstLocalUser.cachedMaster : null);
			CharacterBody val2 = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
			_title = (Object.op_Implicit((Object)(object)val) ? ("STATUS — " + Util.GetBestMasterName(val)) : "STATUS");
			_sb.Clear();
			if (Object.op_Implicit((Object)(object)val2))
			{
				HealthComponent healthComponent = val2.healthComponent;
				_sb.Append("Vida ").Append(N(Object.op_Implicit((Object)(object)healthComponent) ? healthComponent.health : 0f)).Append('/')
					.Append(N(val2.maxHealth));
				if (val2.maxShield > 0f)
				{
					_sb.Append("   Escudo ").Append(N(Object.op_Implicit((Object)(object)healthComponent) ? healthComponent.shield : 0f)).Append('/')
						.Append(N(val2.maxShield));
				}
				if (Object.op_Implicit((Object)(object)healthComponent) && healthComponent.barrier > 0f)
				{
					_sb.Append("   Barreira ").Append(N(healthComponent.barrier));
				}
				_sb.Append("   Regeneração ").Append(N(val2.regen)).Append("/s\n");
				_sb.Append("Dano ").Append(N(val2.damage)).Append("   Vel. de ataque ")
					.Append(val2.attackSpeed.ToString("0.##"))
					.Append('x')
					.Append("   Crítico ")
					.Append(val2.crit.ToString("0.#"))
					.Append('%')
					.Append("   Armadura ")
					.Append(val2.armor.ToString("0"))
					.Append("   Velocidade ")
					.Append(val2.moveSpeed.ToString("0.#"))
					.Append("   Nível ")
					.Append(val2.level.ToString("0"));
			}
			else
			{
				_sb.Append("(sem personagem: morto ou espectando)");
			}
			_now = _sb.ToString();
			_sb.Clear();
			foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
			{
				CharacterMaster val3 = (Object.op_Implicit((Object)(object)instance) ? instance.master : null);
				if (Object.op_Implicit((Object)(object)val3))
				{
					CharacterBody body = val3.GetBody();
					HealthComponent val4 = (Object.op_Implicit((Object)(object)body) ? body.healthComponent : null);
					_sb.Append(((Object)(object)val3 == (Object)(object)val) ? "> " : "  ").Append(Util.GetBestMasterName(val3)).Append('\n');
					_sb.Append("    vida ").Append(Object.op_Implicit((Object)(object)body) ? (N(Object.op_Implicit((Object)(object)val4) ? val4.health : 0f) + "/" + N(body.maxHealth)) : "morto").Append("   dano ")
						.Append(Object.op_Implicit((Object)(object)body) ? N(body.damage) : "—")
						.Append('\n');
					if (TryTotals(val3, (Object)(object)val3 == (Object)(object)val, out var totals))
					{
						_sb.Append("    causado ").Append(N(totals.Dealt)).Append(" (ajudantes ")
							.Append(N(totals.Minion))
							.Append(")   maior golpe ")
							.Append(N(totals.Highest))
							.Append("\n    cura ")
							.Append(N(totals.Healed))
							.Append("   recebido ")
							.Append(N(totals.Taken))
							.Append("   abates ")
							.Append(N(totals.Kills))
							.Append("   mortes ")
							.Append(N(totals.Deaths))
							.Append("   itens ")
							.Append(N(totals.Items))
							.Append('\n');
					}
					else
					{
						_sb.Append("    totais da run: aguardando o host\n");
					}
				}
			}
			_run = _sb.ToString();
		}

		private void OnGUI()
		{
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: 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_017f: 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_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_0060: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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_0084: Expected O, but got Unknown
			if (_open)
			{
				if (_label == null)
				{
					_label = new GUIStyle(GUI.skin.label)
					{
						fontSize = 19,
						wordWrap = true,
						richText = false
					};
					_head = new GUIStyle(GUI.skin.label)
					{
						fontSize = 21,
						fontStyle = (FontStyle)1
					};
					_big = new GUIStyle(GUI.skin.label)
					{
						fontSize = 28,
						fontStyle = (FontStyle)1
					};
				}
				float num = Mathf.Max(0.8f, (float)Screen.height / 1