Decompiled source of BrutalREPO v1.1.0

BrutalREPO.dll

Decompiled 5 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BrutalREPO.Core;
using BrutalREPO.Networking;
using BrutalREPO.Patches;
using BrutalREPO.UI;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[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 BrutalREPO
{
	[BepInPlugin("justrat.repo.chaosdirector", "BrutalREPO", "0.26.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "justrat.repo.chaosdirector";

		public const string PluginName = "BrutalREPO";

		public const string PluginVersion = "0.26.0";

		internal static ChaosLog Log;

		public static ConfigEntry<bool> LoggingEnabled;

		public static ConfigEntry<bool> VehicleRewardEnabled;

		public static ConfigEntry<string> VehicleItemName;

		public static ConfigEntry<string> VehicleBundleFile;

		internal static WeightScale EventCountScale;

		public static ConfigEntry<int> AbsoluteMaxActiveEvents;

		public static ConfigEntry<float> ExtraEventChance;

		public static ConfigEntry<float> DifficultyPerLevel;

		public static ConfigEntry<float> DifficultyPerHaulThousand;

		public static ConfigEntry<float> DifficultyPerExtraPlayer;

		public static ConfigEntry<float> DifficultyOverride;

		public static ConfigEntry<float> DifficultyDropChanceEarly;

		public static ConfigEntry<float> DifficultyDropChanceMid;

		public static ConfigEntry<float> DifficultyDropChanceLate;

		public static ConfigEntry<float> DifficultyDropEarlyMax;

		public static ConfigEntry<float> DifficultyDropMidMax;

		public static ConfigEntry<int> DifficultyDropMin;

		public static ConfigEntry<int> DifficultyDropMax;

		public static ConfigEntry<int> ConfigVersion;

		public static ConfigEntry<float> WeightShopOnly;

		internal static readonly Dictionary<EventTier, WeightScale> TierScales = new Dictionary<EventTier, WeightScale>();

		public static ConfigEntry<float> BadPricePercent;

		public static ConfigEntry<float> BadDurabilityPercent;

		public static ConfigEntry<float> BadFragilityPercent;

		public static ConfigEntry<float> ReallyBadPricePercent;

		public static ConfigEntry<float> ReallyBadDurabilityPercent;

		public static ConfigEntry<float> ReallyBadFragilityPercent;

		public static ConfigEntry<float> TooMuchBadPricePercent;

		public static ConfigEntry<float> TooMuchBadDurabilityPercent;

		public static ConfigEntry<float> TooMuchBadFragilityPercent;

		public static ConfigEntry<float> TrickIntervalSeconds;

		public static ConfigEntry<KeyCode> PanelKey;

		public static ConfigEntry<bool> DebugModeEnabled;

		public static ConfigEntry<string> DebugForceEventId;

		private readonly Harmony _harmony = new Harmony("justrat.repo.chaosdirector");

		private void ApplyConfigMigrations()
		{
			ConfigVersion = ((BaseUnityPlugin)this).Config.Bind<int>("Meta", "ConfigVersion", 0, "Служебное: версия миграции настроек. Не меняй вручную.");
			if (ConfigVersion.Value < 19)
			{
				DifficultyPerLevel.Value = 4f;
				DifficultyPerHaulThousand.Value = 0.03f;
				DifficultyPerExtraPlayer.Value = 2f;
				ReallyBadPricePercent.Value = 0.25f;
				WeightScale weightScale = TierScales[EventTier.TooMuchBad];
				weightScale.Base.Value = 0.86f;
				weightScale.Increment.Value = 0.0177f;
				weightScale.MinCap.Value = 0.86f;
				weightScale.MaxCap.Value = 2.63f;
				ConfigVersion.Value = 19;
				Log.LogInfo("[BrutalREPO] Конфиг мигрирован до v19 (новые значения Difficulty / TooMuchBad / ReallyBad).");
			}
		}

		internal static float WeightFor(EventTier tier, float difficulty)
		{
			if (!TierScales.TryGetValue(tier, out var value))
			{
				return 0f;
			}
			return value.Evaluate(difficulty);
		}

		private void Awake()
		{
			Log = new ChaosLog(((BaseUnityPlugin)this).Logger);
			LoggingEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Logging", "Enabled", false, "Писать в лог BepInEx служебные строки мода (выпавшие события, difficulty, диагностика). По умолчанию ВЫКЛЮЧЕНО. Ошибки пишутся всегда. Включи, если нужно прислать лог для разбора бага.");
			DifficultyPerLevel = ((BaseUnityPlugin)this).Config.Bind<float>("Difficulty", "PerLevel", 4f, "Сколько пунктов difficulty (0-100) даёт каждый пройденный уровень рана.");
			DifficultyPerHaulThousand = ((BaseUnityPlugin)this).Config.Bind<float>("Difficulty", "PerHaulThousand", 0.03f, "Пунктов difficulty за каждую 1000$ суммарного хаула рана. 0 = не учитывать.");
			DifficultyPerExtraPlayer = ((BaseUnityPlugin)this).Config.Bind<float>("Difficulty", "PerExtraPlayer", 2f, "Пунктов difficulty за каждого игрока сверх первого. 0 = не учитывать.");
			DifficultyDropChanceEarly = ((BaseUnityPlugin)this).Config.Bind<float>("Difficulty.Drop", "ChanceEarly", 2f, "Шанс в % (на каждый ролл уровня), что difficulty этого ролла упадёт, пока difficulty <= EarlyMax.");
			DifficultyDropChanceMid = ((BaseUnityPlugin)this).Config.Bind<float>("Difficulty.Drop", "ChanceMid", 4f, "Шанс в % падения difficulty, пока difficulty <= MidMax (и выше EarlyMax).");
			DifficultyDropChanceLate = ((BaseUnityPlugin)this).Config.Bind<float>("Difficulty.Drop", "ChanceLate", 5f, "Шанс в % падения difficulty выше MidMax.");
			DifficultyDropEarlyMax = ((BaseUnityPlugin)this).Config.Bind<float>("Difficulty.Drop", "EarlyMax", 30f, "Граница ранней игры (difficulty).");
			DifficultyDropMidMax = ((BaseUnityPlugin)this).Config.Bind<float>("Difficulty.Drop", "MidMax", 65f, "Граница средней игры (difficulty).");
			DifficultyDropMin = ((BaseUnityPlugin)this).Config.Bind<int>("Difficulty.Drop", "DropMin", 15, "Минимальное падение difficulty (пунктов).");
			DifficultyDropMax = ((BaseUnityPlugin)this).Config.Bind<int>("Difficulty.Drop", "DropMax", 25, "Максимальное падение difficulty (пунктов).");
			DifficultyOverride = ((BaseUnityPlugin)this).Config.Bind<float>("Difficulty", "Override", -1f, "Для тестов: значение >= 0 фиксирует difficulty (0-100) независимо от прогресса. -1 = считать по прогрессу.");
			EventCountScale = WeightScale.Bind(((BaseUnityPlugin)this).Config, "Events.Count", "Количество событий за уровень", 2.5f, 0.015f, 2.5f, 4f);
			AbsoluteMaxActiveEvents = ((BaseUnityPlugin)this).Config.Bind<int>("Events", "AbsoluteMaxActiveEvents", 5, "Абсолютный потолок — выше него количество событий никогда не поднимется.");
			ExtraEventChance = ((BaseUnityPlugin)this).Config.Bind<float>("Events", "ExtraEventChance", 0.2f, "Шанс (0-1) добавить ещё одно \"бонусное\" событие сверх посчитанного по шкале, вплоть до AbsoluteMaxActiveEvents.");
			WeightShopOnly = ((BaseUnityPlugin)this).Config.Bind<float>("Weights", "ShopOnly", 20f, "Тир ShopOnly роллится ТОЛЬКО на уровне-магазине. Значение — шанс В ПРОЦЕНТАХ (0-100), что при заходе в магазин выпадет одно событие этого тира (иначе магазин без событий).");
			TierScales[EventTier.VeryGood] = WeightScale.Bind(((BaseUnityPlugin)this).Config, "TierWeights.VeryGood", "Вес VeryGood", 6f, 0.04f, 6f, 10f);
			TierScales[EventTier.Good] = WeightScale.Bind(((BaseUnityPlugin)this).Config, "TierWeights.Good", "Вес Good", 15f, -0.05f, 10f, 15f);
			TierScales[EventTier.Pleasant] = WeightScale.Bind(((BaseUnityPlugin)this).Config, "TierWeights.Pleasant", "Вес Pleasant (Peasant)", 16f, -0.08f, 8f, 16f);
			TierScales[EventTier.Neutral] = WeightScale.Bind(((BaseUnityPlugin)this).Config, "TierWeights.Neutral", "Вес Neutral", 9f, -0.04f, 5f, 9f);
			TierScales[EventTier.Unfortunate] = WeightScale.Bind(((BaseUnityPlugin)this).Config, "TierWeights.Unfortunate", "Вес Unfortunate (пока тир пуст — не участвует)", 34f, -0.09f, 25f, 34f);
			TierScales[EventTier.Bad] = WeightScale.Bind(((BaseUnityPlugin)this).Config, "TierWeights.Bad", "Вес Bad", 34f, -0.04f, 30f, 34f);
			TierScales[EventTier.ReallyBad] = WeightScale.Bind(((BaseUnityPlugin)this).Config, "TierWeights.ReallyBad", "Вес ReallyBad", 5f, 0.17f, 5f, 22f);
			TierScales[EventTier.TooMuchBad] = WeightScale.Bind(((BaseUnityPlugin)this).Config, "TierWeights.TooMuchBad", "Вес TooMuchBad", 0.86f, 0.0177f, 0.86f, 2.63f);
			BadPricePercent = ((BaseUnityPlugin)this).Config.Bind<float>("TierScaling.Bad", "PricePercent", 0.1f, "Цена valuables, % за каждую активную единицу Bad.");
			BadDurabilityPercent = ((BaseUnityPlugin)this).Config.Bind<float>("TierScaling.Bad", "DurabilityDisplayPercent", 0.2f, "Отображаемая прочность, % за каждую активную единицу Bad.");
			BadFragilityPercent = ((BaseUnityPlugin)this).Config.Bind<float>("TierScaling.Bad", "FragilityPercent", -0.15f, "Реальная хрупкость (fragilityMultiplier), % за каждую активную единицу Bad.");
			ReallyBadPricePercent = ((BaseUnityPlugin)this).Config.Bind<float>("TierScaling.ReallyBad", "PricePercent", 0.25f, "Цена valuables, % за каждую активную единицу ReallyBad.");
			ReallyBadDurabilityPercent = ((BaseUnityPlugin)this).Config.Bind<float>("TierScaling.ReallyBad", "DurabilityDisplayPercent", 0.35f, "Отображаемая прочность, % за каждую активную единицу ReallyBad.");
			ReallyBadFragilityPercent = ((BaseUnityPlugin)this).Config.Bind<float>("TierScaling.ReallyBad", "FragilityPercent", -1.5f, "Реальная хрупкость, % за каждую активную единицу ReallyBad.");
			TooMuchBadPricePercent = ((BaseUnityPlugin)this).Config.Bind<float>("TierScaling.TooMuchBad", "PricePercent", 2.05f, "Цена valuables, % за каждую активную единицу TooMuchBad.");
			TooMuchBadDurabilityPercent = ((BaseUnityPlugin)this).Config.Bind<float>("TierScaling.TooMuchBad", "DurabilityDisplayPercent", 1.05f, "Отображаемая прочность, % за каждую активную единицу TooMuchBad.");
			TooMuchBadFragilityPercent = ((BaseUnityPlugin)this).Config.Bind<float>("TierScaling.TooMuchBad", "FragilityPercent", -2f, "Реальная хрупкость, % за каждую активную единицу TooMuchBad.");
			TrickIntervalSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("TrickOrTreat", "IntervalSeconds", 180f, "Как часто (секунды) во время события Trick or Treat! срабатывает случайный мини-эффект.");
			VehicleRewardEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Rewards", "VehicleEnabled", false, "Выдавать транспорт-награду, если уровень пройден при активном событии тира TooMuchBad. По умолчанию ВЫКЛЮЧЕНО (модель транспорта ещё не готова; без неё выдаётся ванильный Hauler как заглушка).");
			VehicleItemName = ((BaseUnityPlugin)this).Config.Bind<string>("Rewards", "VehicleItemName", "Brutal Hauler", "Имя предмета-награды (поле itemName у Item-ассета или имя самого ассета). Если такого предмета нет — выдаётся ванильный Hauler как заглушка.");
			VehicleBundleFile = ((BaseUnityPlugin)this).Config.Bind<string>("Rewards", "VehicleBundleFile", "brutalrepo_vehicle", "Файл AssetBundle с кастомным транспортом (лежит рядом с BrutalREPO.dll). Нет файла — используется заглушка.");
			ApplyConfigMigrations();
			PanelKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("UI", "PanelKey", (KeyCode)107, "Клавиша, при удержании которой показывается панель активных событий.");
			DebugModeEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DebugModeEnabled", false, "Если true — на СЛЕДУЮЩЕМ заходе в уровень принудительно сработает только событие из DebugForceEventId (вместо обычного ролла), после чего этот флаг сам сбросится обратно в false. Полный список Id — в README.md.");
			DebugForceEventId = ((BaseUnityPlugin)this).Config.Bind<string>("Debug", "DebugForceEventId", "", "Id события для принудительного вызова (например: here_live_bussisman). Работает только вместе с DebugModeEnabled=true. Полный список Id — в README.md.");
			try
			{
				ChaosPanelUI.EnsureCreated();
			}
			catch (Exception arg)
			{
				Log.LogError($"Не удалось создать UI: {arg}");
			}
			try
			{
				_harmony.PatchAll();
			}
			catch (Exception arg2)
			{
				Log.LogError($"PatchAll() упал с ошибкой — часть патчей могла не применится: {arg2}");
			}
			try
			{
				BrutalVehicle.TryRegister(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location));
			}
			catch (Exception arg3)
			{
				Log.LogError($"Регистрация транспорта-награды не удалась: {arg3}");
			}
			Log.LogInfo("BrutalREPO v0.26.0 loaded.");
		}
	}
}
namespace BrutalREPO.UI
{
	internal class ChaosPanelUI : MonoBehaviour
	{
		private enum Mode
		{
			Hidden,
			Auto,
			Held
		}

		private static ChaosPanelUI _instance;

		private static readonly Color Burgundy = new Color(0.2f, 0.035f, 0.07f, 0.9f);

		private static readonly Color BurgundyBorder = new Color(0.46f, 0.09f, 0.15f, 0.95f);

		private static readonly Color Divider = new Color(0.55f, 0.12f, 0.2f, 0.75f);

		private static readonly Color TextMain = new Color(0.97f, 0.88f, 0.89f, 1f);

		private static readonly Color TextMuted = new Color(0.8f, 0.6f, 0.64f, 1f);

		private static readonly Color TrackColor = new Color(0f, 0f, 0f, 0.28f);

		private static readonly Color HandleColor = new Color(0.78f, 0.22f, 0.3f, 0.95f);

		private const float PanelWidth = 390f;

		private const float PanelHeight = 460f;

		private const float HeaderHeight = 44f;

		private const float FooterHeight = 24f;

		private const float AutoHoldSeconds = 2.4f;

		private const float AutoScrollSpeed = 38f;

		private const float AutoEndHoldSeconds = 2.6f;

		private const float WheelStepPixels = 70f;

		private Mode _mode;

		private float _autoTimer;

		private int _builtRoll = -1;

		private int _shownRoll = -1;

		private CanvasGroup _group;

		private GameObject _panelGO;

		private RectTransform _viewport;

		private RectTransform _content;

		private RectTransform _parent;

		private ScrollRect _scroll;

		private GameObject _scrollbarGO;

		private Text _difficultyText;

		private GameObject _timerRow;

		private Text _timerText;

		private Font _font;

		private Sprite _roundedSprite;

		private static readonly EventTier[] ShareOrder = new EventTier[8]
		{
			EventTier.VeryGood,
			EventTier.Good,
			EventTier.Pleasant,
			EventTier.Neutral,
			EventTier.Unfortunate,
			EventTier.Bad,
			EventTier.ReallyBad,
			EventTier.TooMuchBad
		};

		public static bool IsHeld
		{
			get
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				if (Plugin.PanelKey != null)
				{
					return Input.GetKey(Plugin.PanelKey.Value);
				}
				return false;
			}
		}

		public static void EnsureCreated()
		{
			//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_001e: Expected O, but got Unknown
			if (!((Object)(object)_instance != (Object)null))
			{
				GameObject val = new GameObject("ChaosDirector_Panel");
				Object.DontDestroyOnLoad((Object)val);
				_instance = val.AddComponent<ChaosPanelUI>();
			}
		}

		private static Color TierColor(EventTier tier)
		{
			//IL_00d7: 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_0053: 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: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: 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_00dd: Unknown result type (might be due to invalid IL or missing references)
			return (Color)(tier switch
			{
				EventTier.VeryGood => new Color(0.25f, 0.95f, 0.35f), 
				EventTier.Good => new Color(0.1f, 0.62f, 0.22f), 
				EventTier.Pleasant => new Color(0.66f, 0.83f, 0.29f), 
				EventTier.Neutral => Color.white, 
				EventTier.Unfortunate => new Color(1f, 0.6f, 0.18f), 
				EventTier.Bad => new Color(1f, 0.23f, 0.23f), 
				EventTier.ReallyBad => new Color(0.7f, 0.07f, 0.12f), 
				EventTier.TooMuchBad => new Color(0.07f, 0.06f, 0.06f), 
				EventTier.ShopOnly => new Color(0.3f, 0.78f, 0.95f), 
				_ => Color.white, 
			});
		}

		private static bool NeedsHalo(EventTier tier)
		{
			if (tier != EventTier.ReallyBad)
			{
				return tier == EventTier.TooMuchBad;
			}
			return true;
		}

		private static Font GetFont()
		{
			Font val = Resources.GetBuiltinResource<Font>("Arial.ttf");
			if ((Object)(object)val == (Object)null)
			{
				val = Font.CreateDynamicFontFromOSFont("Arial", 14);
			}
			return val;
		}

		private static Sprite MakeRoundedSprite(int size, int radius)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(size, size, (TextureFormat)4, false);
			((Texture)val).filterMode = (FilterMode)1;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			Color32[] array = (Color32[])(object)new Color32[size * size];
			for (int i = 0; i < size; i++)
			{
				for (int j = 0; j < size; j++)
				{
					float num = (float)j + 0.5f;
					float num2 = (float)i + 0.5f;
					float num3 = Mathf.Clamp(num, (float)radius, (float)(size - radius));
					float num4 = Mathf.Clamp(num2, (float)radius, (float)(size - radius));
					float num5 = Mathf.Sqrt((num - num3) * (num - num3) + (num2 - num4) * (num2 - num4));
					float num6 = Mathf.Clamp01((float)radius - num5 + 0.5f);
					array[i * size + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)Mathf.RoundToInt(num6 * 255f));
				}
			}
			val.SetPixels32(array);
			val.Apply();
			return Sprite.Create(val, new Rect(0f, 0f, (float)size, (float)size), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4((float)radius, (float)radius, (float)radius, (float)radius));
		}

		private RectTransform NewRect(string name, Transform parent)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent, false);
			RectTransform obj = val.AddComponent<RectTransform>();
			obj.anchorMin = Vector2.zero;
			obj.anchorMax = Vector2.one;
			obj.offsetMin = Vector2.zero;
			obj.offsetMax = Vector2.zero;
			return obj;
		}

		private Image NewImage(string name, Transform parent, Color color, bool rounded)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			Image val = ((Component)NewRect(name, parent)).gameObject.AddComponent<Image>();
			((Graphic)val).color = color;
			((Graphic)val).raycastTarget = false;
			if (rounded)
			{
				val.sprite = _roundedSprite;
				val.type = (Type)1;
			}
			return val;
		}

		private Text NewText(string name, Transform parent, int size, FontStyle style, Color color, TextAnchor anchor)
		{
			//IL_0026: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			Text obj = ((Component)NewRect(name, parent)).gameObject.AddComponent<Text>();
			obj.font = _font;
			obj.fontSize = size;
			obj.fontStyle = style;
			((Graphic)obj).color = color;
			obj.alignment = anchor;
			obj.supportRichText = true;
			obj.horizontalOverflow = (HorizontalWrapMode)0;
			obj.verticalOverflow = (VerticalWrapMode)1;
			((Graphic)obj).raycastTarget = false;
			return obj;
		}

		private void Awake()
		{
			//IL_0046: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: 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_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_0327: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: 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_037f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0399: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_040b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0460: Unknown result type (might be due to invalid IL or missing references)
			//IL_047a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0494: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04df: Expected O, but got Unknown
			//IL_0535: Unknown result type (might be due to invalid IL or missing references)
			//IL_0564: Unknown result type (might be due to invalid IL or missing references)
			//IL_057a: 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_05a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_05bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_06fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0714: Unknown result type (might be due to invalid IL or missing references)
			//IL_0736: Unknown result type (might be due to invalid IL or missing references)
			//IL_073b: Unknown result type (might be due to invalid IL or missing references)
			Canvas obj = ((Component)this).gameObject.AddComponent<Canvas>();
			obj.renderMode = (RenderMode)0;
			obj.sortingOrder = 32767;
			obj.sortingLayerID = 0;
			obj.overrideSorting = true;
			CanvasScaler obj2 = ((Component)this).gameObject.AddComponent<CanvasScaler>();
			obj2.uiScaleMode = (ScaleMode)1;
			obj2.referenceResolution = new Vector2(1920f, 1080f);
			_font = GetFont();
			_roundedSprite = MakeRoundedSprite(48, 12);
			Image val = NewImage("IconBorder", ((Component)this).transform, BurgundyBorder, rounded: true);
			RectTransform rectTransform = ((Graphic)val).rectTransform;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(1f, 1f);
			rectTransform.pivot = val2;
			Vector2 anchorMin = (rectTransform.anchorMax = val2);
			rectTransform.anchorMin = anchorMin;
			rectTransform.anchoredPosition = new Vector2(-16f, -16f);
			rectTransform.sizeDelta = new Vector2(44f, 44f);
			Image val4 = NewImage("IconBody", ((Component)val).transform, Burgundy, rounded: true);
			((Graphic)val4).rectTransform.offsetMin = new Vector2(2f, 2f);
			((Graphic)val4).rectTransform.offsetMax = new Vector2(-2f, -2f);
			Text obj3 = NewText("IconText", ((Component)val4).transform, 22, (FontStyle)1, TextMain, (TextAnchor)4);
			obj3.horizontalOverflow = (HorizontalWrapMode)1;
			obj3.text = ((Plugin.PanelKey != null) ? ((object)Plugin.PanelKey.Value/*cast due to .constrained prefix*/).ToString() : "K");
			Image val5 = NewImage("PanelBorder", ((Component)this).transform, BurgundyBorder, rounded: true);
			_panelGO = ((Component)val5).gameObject;
			RectTransform rectTransform2 = ((Graphic)val5).rectTransform;
			((Vector2)(ref val2))..ctor(1f, 1f);
			rectTransform2.pivot = val2;
			anchorMin = (rectTransform2.anchorMax = val2);
			rectTransform2.anchorMin = anchorMin;
			rectTransform2.anchoredPosition = new Vector2(-16f, -68f);
			rectTransform2.sizeDelta = new Vector2(390f, 460f);
			_group = _panelGO.AddComponent<CanvasGroup>();
			_group.alpha = 0f;
			_group.blocksRaycasts = false;
			_group.interactable = false;
			Image val7 = NewImage("PanelBody", _panelGO.transform, Burgundy, rounded: true);
			((Graphic)val7).rectTransform.offsetMin = new Vector2(2f, 2f);
			((Graphic)val7).rectTransform.offsetMax = new Vector2(-2f, -2f);
			RectTransform val8 = NewRect("Header", ((Component)val7).transform);
			val8.anchorMin = new Vector2(0f, 1f);
			val8.anchorMax = new Vector2(1f, 1f);
			val8.pivot = new Vector2(0.5f, 1f);
			val8.offsetMin = new Vector2(0f, -44f);
			val8.offsetMax = Vector2.zero;
			_difficultyText = NewText("Difficulty", (Transform)(object)val8, 17, (FontStyle)0, TextMain, (TextAnchor)3);
			((Graphic)_difficultyText).rectTransform.offsetMin = new Vector2(16f, 2f);
			((Graphic)_difficultyText).rectTransform.offsetMax = new Vector2(-16f, 0f);
			_difficultyText.horizontalOverflow = (HorizontalWrapMode)1;
			Image obj4 = NewImage("Divider", (Transform)(object)val8, Divider, rounded: false);
			((Graphic)obj4).rectTransform.anchorMin = new Vector2(0f, 0f);
			((Graphic)obj4).rectTransform.anchorMax = new Vector2(1f, 0f);
			((Graphic)obj4).rectTransform.offsetMin = new Vector2(12f, 0f);
			((Graphic)obj4).rectTransform.offsetMax = new Vector2(-12f, 2f);
			RectTransform val9 = NewRect("Scroll", ((Component)val7).transform);
			val9.offsetMin = new Vector2(0f, 24f);
			val9.offsetMax = new Vector2(-18f, -48f);
			_viewport = NewRect("Viewport", (Transform)(object)val9);
			((Component)_viewport).gameObject.AddComponent<RectMask2D>();
			_content = NewRect("Content", (Transform)(object)_viewport);
			_content.anchorMin = new Vector2(0f, 1f);
			_content.anchorMax = new Vector2(1f, 1f);
			_content.pivot = new Vector2(0.5f, 1f);
			_content.offsetMin = Vector2.zero;
			_content.offsetMax = Vector2.zero;
			VerticalLayoutGroup obj5 = ((Component)_content).gameObject.AddComponent<VerticalLayoutGroup>();
			((LayoutGroup)obj5).padding = new RectOffset(10, 4, 6, 10);
			((HorizontalOrVerticalLayoutGroup)obj5).spacing = 10f;
			((LayoutGroup)obj5).childAlignment = (TextAnchor)0;
			((HorizontalOrVerticalLayoutGroup)obj5).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj5).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj5).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj5).childForceExpandHeight = false;
			ContentSizeFitter obj6 = ((Component)_content).gameObject.AddComponent<ContentSizeFitter>();
			obj6.verticalFit = (FitMode)2;
			obj6.horizontalFit = (FitMode)0;
			Image val10 = NewImage("Scrollbar", ((Component)val7).transform, TrackColor, rounded: true);
			_scrollbarGO = ((Component)val10).gameObject;
			RectTransform rectTransform3 = ((Graphic)val10).rectTransform;
			rectTransform3.anchorMin = new Vector2(1f, 0f);
			rectTransform3.anchorMax = new Vector2(1f, 1f);
			rectTransform3.pivot = new Vector2(1f, 0.5f);
			rectTransform3.offsetMin = new Vector2(-14f, 28f);
			rectTransform3.offsetMax = new Vector2(-6f, -52f);
			Image val11 = NewImage("Handle", (Transform)(object)rectTransform3, HandleColor, rounded: true);
			Scrollbar val12 = _scrollbarGO.AddComponent<Scrollbar>();
			val12.direction = (Direction)2;
			val12.handleRect = ((Graphic)val11).rectTransform;
			((Selectable)val12).targetGraphic = (Graphic)(object)val11;
			((Selectable)val12).transition = (Transition)0;
			_scroll = ((Component)val9).gameObject.AddComponent<ScrollRect>();
			_scroll.horizontal = false;
			_scroll.vertical = true;
			_scroll.movementType = (MovementType)2;
			_scroll.inertia = false;
			_scroll.scrollSensitivity = 0f;
			_scroll.viewport = _viewport;
			_scroll.content = _content;
			_scroll.verticalScrollbar = val12;
			_scroll.verticalScrollbarVisibility = (ScrollbarVisibility)0;
			Text obj7 = NewText("Footer", ((Component)val7).transform, 11, (FontStyle)0, TextMuted, (TextAnchor)4);
			((Graphic)obj7).rectTransform.anchorMin = new Vector2(0f, 0f);
			((Graphic)obj7).rectTransform.anchorMax = new Vector2(1f, 0f);
			((Graphic)obj7).rectTransform.offsetMin = new Vector2(10f, 2f);
			((Graphic)obj7).rectTransform.offsetMax = new Vector2(-10f, 24f);
			obj7.text = "Hold [" + ((Plugin.PanelKey != null) ? ((object)Plugin.PanelKey.Value/*cast due to .constrained prefix*/).ToString() : "K") + "]  +  mouse wheel to scroll";
			_panelGO.SetActive(false);
		}

		private static string Mult(float m)
		{
			return "x" + m.ToString("0.00", CultureInfo.InvariantCulture);
		}

		private static float Product(Func<ChaosEvent, float> selector)
		{
			float num = 1f;
			foreach (ChaosEvent item in EventState.Active)
			{
				num *= selector(item);
			}
			return num;
		}

		private void ClearContent()
		{
			for (int num = ((Transform)_content).childCount - 1; num >= 0; num--)
			{
				GameObject gameObject = ((Component)((Transform)_content).GetChild(num)).gameObject;
				gameObject.SetActive(false);
				Object.Destroy((Object)(object)gameObject);
			}
		}

		private void BeginSection(string title)
		{
			//IL_0020: 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: Expected O, but got Unknown
			//IL_0085: 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)
			Image val = NewImage("Section", (Transform)(object)_content, new Color(0f, 0f, 0f, 0.22f), rounded: true);
			VerticalLayoutGroup obj = ((Component)val).gameObject.AddComponent<VerticalLayoutGroup>();
			((LayoutGroup)obj).padding = new RectOffset(10, 10, 8, 10);
			((HorizontalOrVerticalLayoutGroup)obj).spacing = 3f;
			((LayoutGroup)obj).childAlignment = (TextAnchor)0;
			((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false;
			NewText("SectionTitle", ((Component)val).transform, 12, (FontStyle)1, TextMuted, (TextAnchor)3).text = title;
			((Component)NewImage("SectionDivider", ((Component)val).transform, Divider, rounded: false)).gameObject.AddComponent<LayoutElement>().preferredHeight = 2f;
			_parent = ((Graphic)val).rectTransform;
		}

		private void EndSection()
		{
			_parent = _content;
		}

		private void AddEventRow(ChaosEvent ev)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_0059: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = NewRect("EventRow", (Transform)(object)_parent);
			VerticalLayoutGroup obj = ((Component)val).gameObject.AddComponent<VerticalLayoutGroup>();
			((LayoutGroup)obj).padding = new RectOffset(12, 0, 3, 3);
			((HorizontalOrVerticalLayoutGroup)obj).spacing = 1f;
			((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false;
			Color color = TierColor(ev.Tier);
			Image obj2 = NewImage("TierBar", (Transform)(object)val, color, rounded: false);
			((Component)obj2).gameObject.AddComponent<LayoutElement>().ignoreLayout = true;
			((Graphic)obj2).rectTransform.anchorMin = new Vector2(0f, 0f);
			((Graphic)obj2).rectTransform.anchorMax = new Vector2(0f, 1f);
			((Graphic)obj2).rectTransform.pivot = new Vector2(0f, 0.5f);
			((Graphic)obj2).rectTransform.offsetMin = new Vector2(0f, 3f);
			((Graphic)obj2).rectTransform.offsetMax = new Vector2(4f, -3f);
			Text val2 = NewText("Name", (Transform)(object)val, 18, (FontStyle)1, color, (TextAnchor)0);
			val2.text = ev.PickDisplayName(EventState.NameSeed);
			if (NeedsHalo(ev.Tier))
			{
				Outline obj3 = ((Component)val2).gameObject.AddComponent<Outline>();
				((Shadow)obj3).effectColor = new Color(1f, 0.86f, 0.88f, 0.95f);
				((Shadow)obj3).effectDistance = new Vector2(1.2f, -1.2f);
			}
		}

		private static string TierDisplayName(EventTier tier)
		{
			return tier switch
			{
				EventTier.VeryGood => "Really Good", 
				EventTier.Good => "Good", 
				EventTier.Pleasant => "Pleasant", 
				EventTier.Neutral => "Neutral", 
				EventTier.Unfortunate => "Unfortunate", 
				EventTier.Bad => "Bad", 
				EventTier.ReallyBad => "Really Bad", 
				EventTier.TooMuchBad => "Too Much Bad", 
				EventTier.ShopOnly => "Shop", 
				_ => tier.ToString(), 
			};
		}

		private void AddShareRow(EventTier tier, float percent)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_0064: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = NewRect("ShareRow", (Transform)(object)_parent);
			HorizontalLayoutGroup obj = ((Component)val).gameObject.AddComponent<HorizontalLayoutGroup>();
			((LayoutGroup)obj).padding = new RectOffset(4, 0, 1, 1);
			((HorizontalOrVerticalLayoutGroup)obj).spacing = 6f;
			((LayoutGroup)obj).childAlignment = (TextAnchor)3;
			((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false;
			Text val2 = NewText("Tier", (Transform)(object)val, 15, (FontStyle)1, TierColor(tier), (TextAnchor)3);
			val2.text = TierDisplayName(tier);
			((Component)val2).gameObject.AddComponent<LayoutElement>().flexibleWidth = 1f;
			if (NeedsHalo(tier))
			{
				Outline obj2 = ((Component)val2).gameObject.AddComponent<Outline>();
				((Shadow)obj2).effectColor = new Color(1f, 0.86f, 0.88f, 0.95f);
				((Shadow)obj2).effectDistance = new Vector2(1.2f, -1.2f);
			}
			Text obj3 = NewText("Percent", (Transform)(object)val, 15, (FontStyle)0, TextMain, (TextAnchor)5);
			obj3.text = percent.ToString("0.0", CultureInfo.InvariantCulture) + "%";
			((Component)obj3).gameObject.AddComponent<LayoutElement>().preferredWidth = 64f;
		}

		private static bool HasVisibleShares()
		{
			Dictionary<EventTier, float> tierShares = EventState.TierShares;
			if (tierShares == null)
			{
				return false;
			}
			EventTier[] shareOrder = ShareOrder;
			foreach (EventTier eventTier in shareOrder)
			{
				if (eventTier != EventTier.TooMuchBad && tierShares.ContainsKey(eventTier))
				{
					return true;
				}
			}
			return false;
		}

		private void AddShares()
		{
			Dictionary<EventTier, float> tierShares = EventState.TierShares;
			if (tierShares == null)
			{
				return;
			}
			EventTier[] shareOrder = ShareOrder;
			foreach (EventTier eventTier in shareOrder)
			{
				if (eventTier != EventTier.TooMuchBad && tierShares.TryGetValue(eventTier, out var value))
				{
					AddShareRow(eventTier, value);
				}
			}
		}

		private void AddTotals()
		{
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			StringBuilder sb = new StringBuilder();
			sb.Append(Line("Durablity Valuables", EventState.ValuableDurabilityDisplay));
			sb.Append(Line("Count Valuables", EventState.ValuableCountMultiplier));
			sb.Append(Line("Price Valuables", EventState.ValuablePriceMultiplier));
			Extra("Mob HP", Product((ChaosEvent e) => e.EnemyHealthMultiplier));
			Extra("Mob speed", Product((ChaosEvent e) => e.EnemySpeedMultiplier));
			Extra("Mob damage", Product((ChaosEvent e) => e.EnemyDamageMultiplier));
			Extra("Mob count", Product((ChaosEvent e) => e.EnemyCountMultiplier));
			Extra("Quota", Product((ChaosEvent e) => e.HaulGoalMultiplier));
			Extra("Move speed", Product((ChaosEvent e) => e.PlayerSpeedMultiplier));
			Extra("Energy regen", Product((ChaosEvent e) => e.EnergyRegenMultiplier));
			Extra("Damage dealt", Product((ChaosEvent e) => e.PlayerDamageDealtMultiplier));
			NewText("Totals", (Transform)(object)_parent, 14, (FontStyle)0, TextMain, (TextAnchor)0).text = sb.ToString().TrimEnd('\n');
			void Extra(string label, float value)
			{
				if (Math.Abs(value - 1f) > 0.0001f)
				{
					sb.Append(Line(label, value));
				}
			}
			static string Line(string label, float value)
			{
				return label + "  <b><color=#FFFFFF>" + Mult(value) + "</color></b>\n";
			}
		}

		private void Rebuild()
		{
			//IL_0046: 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)
			_builtRoll = EventState.RollId;
			ClearContent();
			_parent = _content;
			BeginSection("CURRENT EVENTS");
			Text val = NewText("TimeLeft", (Transform)(object)_parent, 16, (FontStyle)1, new Color(1f, 0.45f, 0.45f), (TextAnchor)3);
			_timerRow = ((Component)val).gameObject;
			_timerText = val;
			_timerRow.SetActive(false);
			if (EventState.Active.Count == 0)
			{
				NewText("None", (Transform)(object)_parent, 15, (FontStyle)0, TextMuted, (TextAnchor)0).text = "No active events";
			}
			else
			{
				foreach (ChaosEvent item in EventState.Active)
				{
					AddEventRow(item);
				}
			}
			EndSection();
			BeginSection("MULTIPLIERS");
			AddTotals();
			EndSection();
			if (HasVisibleShares())
			{
				BeginSection("TIER CHANCES (PER EVENT)");
				AddShares();
				EndSection();
			}
			if (EventState.Difficulty >= 0)
			{
				string text = "Difficulty <b>" + EventState.Difficulty + "</b>/100";
				if (EventState.DifficultyDrop > 0)
				{
					text = text + " <color=#8FE3A0>(-" + EventState.DifficultyDrop + ")</color>";
				}
				_difficultyText.text = text;
			}
			else
			{
				_difficultyText.text = (SemiFunc.RunIsShop() ? "Shop" : "");
			}
			LayoutRebuilder.ForceRebuildLayoutImmediate(_content);
			_scroll.verticalNormalizedPosition = 1f;
			UpdateScrollbarVisibility();
		}

		private float Overflow()
		{
			//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_001e: 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)
			Rect rect = _content.rect;
			float height = ((Rect)(ref rect)).height;
			rect = _viewport.rect;
			return Mathf.Max(0f, height - ((Rect)(ref rect)).height);
		}

		private void UpdateScrollbarVisibility()
		{
			_scrollbarGO.SetActive(Overflow() > 1f);
		}

		private void UpdateTimerRow()
		{
			if (!((Object)(object)_timerRow == (Object)null))
			{
				float num = TimedEffects.RemainingSeconds();
				bool flag = num >= 0f;
				if (_timerRow.activeSelf != flag)
				{
					_timerRow.SetActive(flag);
					LayoutRebuilder.ForceRebuildLayoutImmediate(_content);
					UpdateScrollbarVisibility();
				}
				if (flag)
				{
					int num2 = Mathf.CeilToInt(num);
					_timerText.text = "Time left  " + (num2 / 60).ToString("00") + ":" + (num2 % 60).ToString("00");
				}
			}
		}

		private void StartAuto()
		{
			_mode = Mode.Auto;
			_autoTimer = 0f;
			_scroll.verticalNormalizedPosition = 1f;
		}

		private void ConsiderAutoOpen()
		{
			if (_shownRoll == EventState.RollId || (!SemiFunc.RunIsShop() && (!((Object)(object)LevelGenerator.Instance != (Object)null) || !LevelGenerator.Instance.Generated)))
			{
				return;
			}
			_shownRoll = EventState.RollId;
			if (EventState.Active.Count != 0 && _mode != Mode.Held)
			{
				if (_builtRoll != EventState.RollId)
				{
					Rebuild();
				}
				StartAuto();
			}
		}

		private void TickAuto()
		{
			_autoTimer += Time.unscaledDeltaTime;
			float num = Overflow();
			float num2 = ((num > 1f) ? (num / 38f) : 0f);
			float verticalNormalizedPosition = ((num2 <= 0f) ? 1f : (1f - Mathf.Clamp01((_autoTimer - 2.4f) / num2)));
			_scroll.verticalNormalizedPosition = verticalNormalizedPosition;
			if (_autoTimer >= 2.4f + num2 + 2.6f)
			{
				_mode = Mode.Hidden;
			}
		}

		private void HandleWheel()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			float y = Input.mouseScrollDelta.y;
			if (!(Mathf.Abs(y) < 0.01f))
			{
				float num = Mathf.Max(1f, Overflow());
				_scroll.verticalNormalizedPosition = Mathf.Clamp01(_scroll.verticalNormalizedPosition + y * 70f / num);
			}
		}

		private void Update()
		{
			bool isHeld = IsHeld;
			ConsiderAutoOpen();
			if (isHeld)
			{
				if (_mode != Mode.Held)
				{
					bool flag = _group.alpha > 0.05f;
					_mode = Mode.Held;
					if (_builtRoll != EventState.RollId)
					{
						Rebuild();
					}
					else if (!flag)
					{
						_scroll.verticalNormalizedPosition = 1f;
					}
				}
				HandleWheel();
			}
			else if (_mode == Mode.Held)
			{
				_mode = Mode.Hidden;
			}
			if (_mode == Mode.Auto)
			{
				TickAuto();
			}
			float num = ((_mode == Mode.Hidden) ? 0f : 1f);
			float num2 = ((num > _group.alpha) ? 5f : 2.5f);
			_group.alpha = Mathf.MoveTowards(_group.alpha, num, Time.unscaledDeltaTime * num2);
			bool flag2 = _group.alpha > 0.01f || num > 0f;
			if (_panelGO.activeSelf != flag2)
			{
				_panelGO.SetActive(flag2);
			}
			if (flag2)
			{
				if (_builtRoll != EventState.RollId)
				{
					Rebuild();
				}
				UpdateTimerRow();
			}
		}
	}
	internal static class EventDescriber
	{
		private static readonly CultureInfo Inv = CultureInfo.InvariantCulture;

		private static string X(float m)
		{
			return "x" + m.ToString("0.##", Inv);
		}

		private static string Pct(float p)
		{
			return p.ToString("0.##", Inv) + "%";
		}

		private static bool Differs(float v)
		{
			return Math.Abs(v - 1f) > 0.0001f;
		}

		private static string CleanMobName(string raw)
		{
			if (string.IsNullOrEmpty(raw))
			{
				return raw;
			}
			int num = raw.IndexOf(" - ", StringComparison.Ordinal);
			if (num < 0)
			{
				return raw;
			}
			return raw.Substring(num + 3);
		}

		public static List<string> Describe(ChaosEvent ev)
		{
			List<string> list = new List<string>();
			if (Differs(ev.ValuableValueMultiplier))
			{
				list.Add("Valuable price " + X(ev.ValuableValueMultiplier));
			}
			if (Differs(ev.ValuableFragilityMultiplier))
			{
				list.Add("Valuable fragility " + X(ev.ValuableFragilityMultiplier));
			}
			if (Differs(ev.EnemyHealthMultiplier))
			{
				list.Add("Mob HP " + X(ev.EnemyHealthMultiplier));
			}
			if (Differs(ev.EnemySpeedMultiplier))
			{
				list.Add("Mob speed " + X(ev.EnemySpeedMultiplier));
			}
			if (Differs(ev.EnemyDamageMultiplier))
			{
				list.Add("Mob damage " + X(ev.EnemyDamageMultiplier));
			}
			if (Differs(ev.EnemyCountMultiplier))
			{
				list.Add("Mob count " + X(ev.EnemyCountMultiplier));
			}
			if (ev.EnemyCountDeltaMin != 0 || ev.EnemyCountDeltaMax != 0)
			{
				if (ev.EnemyCountDeltaMin == ev.EnemyCountDeltaMax)
				{
					list.Add(((ev.EnemyCountDeltaMin > 0) ? "+" : "") + ev.EnemyCountDeltaMin + " mobs");
				}
				else
				{
					list.Add("Mobs " + ev.EnemyCountDeltaMin + " to " + ev.EnemyCountDeltaMax);
				}
			}
			if (ev.ForceAllEnemyTypes)
			{
				list.Add("Every mob type spawns");
			}
			if (!string.IsNullOrEmpty(ev.ForceSpecificEnemyExactName))
			{
				list.Add("Guaranteed: " + CleanMobName(ev.ForceSpecificEnemyExactName));
			}
			if (ev.BanEnemyNamesContaining != null && ev.BanEnemyNamesContaining.Count > 0)
			{
				list.Add("No " + string.Join(", ", ev.BanEnemyNamesContaining) + " this level");
			}
			if (ev.NoEnemyOrbs)
			{
				list.Add("Mobs drop no orbs");
			}
			if (ev.EnemyOrbChance > 0f)
			{
				list.Add(Pct(ev.EnemyOrbChance * 100f) + " chance: mob orb " + X(ev.EnemyOrbValueMultiplier));
			}
			if (Differs(ev.TranqStatMultiplier))
			{
				list.Add("Tranq stats " + X(ev.TranqStatMultiplier));
			}
			if (Differs(ev.PlayerSpeedMultiplier))
			{
				list.Add("Move speed " + X(ev.PlayerSpeedMultiplier));
			}
			if (Differs(ev.CarryingValuableSpeedMultiplier))
			{
				list.Add("Speed while carrying " + X(ev.CarryingValuableSpeedMultiplier));
			}
			if (Differs(ev.EnergyRegenMultiplier))
			{
				list.Add("Energy regen " + X(ev.EnergyRegenMultiplier));
			}
			if (Differs(ev.PlayerDamageDealtMultiplier))
			{
				list.Add("Damage dealt " + X(ev.PlayerDamageDealtMultiplier));
			}
			if (ev.DodgeChancePercent > 0f)
			{
				list.Add(Pct(ev.DodgeChancePercent) + " dodge vs mobs");
			}
			if (ev.InstantHealPercent > 0f)
			{
				list.Add("Heal " + Pct(ev.InstantHealPercent));
			}
			if (ev.HealthRegenPercentPerTick > 0f)
			{
				list.Add("Regen " + Pct(ev.HealthRegenPercentPerTick) + " HP / " + ev.HealthRegenIntervalSeconds.ToString("0.#", Inv) + "s");
			}
			if (ev.GrantExtraLife)
			{
				list.Add("One extra life (50% HP)");
			}
			if (ev.InvertMouseX)
			{
				list.Add("Mouse X inverted");
			}
			List<string> list2 = new List<string>();
			if (ev.EnergyUpgradeLevels != 0)
			{
				list2.Add(((ev.EnergyUpgradeLevels > 0) ? "+" : "") + ev.EnergyUpgradeLevels + " Energy");
			}
			if (ev.HealthUpgradeLevels != 0)
			{
				list2.Add(((ev.HealthUpgradeLevels > 0) ? "+" : "") + ev.HealthUpgradeLevels + " Health");
			}
			if (ev.StrengthUpgradeLevels != 0)
			{
				list2.Add(((ev.StrengthUpgradeLevels > 0) ? "+" : "") + ev.StrengthUpgradeLevels + " Strength");
			}
			if (list2.Count > 0)
			{
				list.Add(string.Join(", ", list2));
			}
			if (ev.RandomUpgradeLevels > 0)
			{
				int num = Math.Max(ev.RandomUpgradeLevels, ev.RandomUpgradeLevelsMax);
				list.Add((num > ev.RandomUpgradeLevels) ? (ev.RandomUpgradeLevels + " to " + num + " random upgrades") : (ev.RandomUpgradeLevels + " random upgrade"));
			}
			if (ev.StealUpgradeFromOneRandomPlayer < 0)
			{
				list.Add("One player loses an upgrade");
			}
			if (Differs(ev.HaulGoalMultiplier))
			{
				list.Add("Quota " + X(ev.HaulGoalMultiplier));
			}
			if (Differs(ev.ExtractionMoneyMultiplier))
			{
				list.Add("Extraction money " + X(ev.ExtractionMoneyMultiplier));
			}
			if (ev.ExtractionBonusDollars > 0f)
			{
				list.Add("+$" + ev.ExtractionBonusDollars.ToString("0", Inv) + " per extraction");
			}
			if (ev.NoExtractionMoney)
			{
				list.Add("Extraction pays nothing");
			}
			if (ev.CurrencyBonusMax > 0f)
			{
				list.Add("+$" + ev.CurrencyBonusMin.ToString("0", Inv) + "-" + ev.CurrencyBonusMax.ToString("0", Inv));
			}
			if (Differs(ev.ShopPriceMultiplier))
			{
				list.Add("Shop prices " + X(ev.ShopPriceMultiplier));
			}
			if (ev.SuppliesItemCount > 0)
			{
				list.Add(ev.SuppliesItemCount + " free items each");
			}
			if (ev.SpawnSemiscooter)
			{
				list.Add("Free scooter each");
			}
			if (ev.FillChargingStation)
			{
				list.Add("Charging station full");
			}
			if (ev.DrainItemBatteries)
			{
				list.Add("Item batteries drained");
			}
			if (ev.TriggerFullBlackout)
			{
				list.Add("Total blackout");
			}
			if (ev.TriggerFog)
			{
				list.Add("Fog");
			}
			if (ev.DarknessBoost)
			{
				list.Add("Darker ambient");
			}
			if (ev.TintEnemiesDark)
			{
				list.Add("Mobs tinted dark");
			}
			if (ev.TintLightsRed)
			{
				list.Add("Red lights");
			}
			if (ev.PartyLights)
			{
				list.Add("Party lights");
			}
			if (Differs(ev.LightIntensityMultiplier))
			{
				list.Add("Lights " + X(ev.LightIntensityMultiplier));
			}
			if (ev.GrenadePercentChancePerSecond > 0f)
			{
				list.Add(Pct(ev.GrenadePercentChancePerSecond) + " grenade chance / s");
			}
			if (ev.TimeLimitSeconds > 0f)
			{
				int num2 = (int)ev.TimeLimitSeconds;
				list.Add("Time limit " + (num2 / 60).ToString("00") + ":" + (num2 % 60).ToString("00"));
			}
			if (ev.TrickOrTreat)
			{
				list.Add("Random effect every " + (Plugin.TrickIntervalSeconds.Value / 60f).ToString("0.#", Inv) + " min");
			}
			return list;
		}
	}
}
namespace BrutalREPO.Patches
{
	[HarmonyPatch(typeof(LightManager))]
	internal static class BlackoutPatch
	{
		private static int _lastTriggeredRollId = -1;

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void Update_Postfix(LightManager __instance)
		{
			if (_lastTriggeredRollId == EventState.RollId)
			{
				return;
			}
			bool flag = false;
			foreach (ChaosEvent item in EventState.Active)
			{
				if (item.TriggerFullBlackout)
				{
					flag = true;
					break;
				}
			}
			if (!flag || (Object)(object)LevelGenerator.Instance == (Object)null || !LevelGenerator.Instance.Generated)
			{
				return;
			}
			_lastTriggeredRollId = EventState.RollId;
			try
			{
				((MonoBehaviour)__instance).StopAllCoroutines();
				Traverse obj = Traverse.Create((object)__instance);
				obj.Method("Setup", Array.Empty<object>()).GetValue();
				int num = obj.Field("propLights").GetValue<List<PropLight>>()?.Count ?? (-1);
				Plugin.Log.LogInfo($"[BrutalREPO] We die in the dark: запускаю TurnOffLights/TurnOffEmissions, propLights.Count={num} (после повторного Setup()).");
				IEnumerator enumerator2 = (IEnumerator)obj.Method("TurnOffLights", Array.Empty<object>()).GetValue();
				((MonoBehaviour)__instance).StartCoroutine(enumerator2);
				IEnumerator enumerator3 = (IEnumerator)obj.Method("TurnOffEmissions", Array.Empty<object>()).GetValue();
				((MonoBehaviour)__instance).StartCoroutine(enumerator3);
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError($"[BrutalREPO] We die in the dark: ошибка при запуске TurnOffLights/TurnOffEmissions: {arg}");
			}
		}
	}
	internal static class BossStatsPatch
	{
		private static float _pendingOrbValue;

		private static float _pendingOrbUntil;

		internal static bool AnyBossEvent()
		{
			if (!EventState.HasAnyEffect)
			{
				return false;
			}
			foreach (ChaosEvent item in EventState.Active)
			{
				if (item.BossHealthMultiplier != 1f || item.BossHealthAbsolute > 0f || item.BossSpeedMultiplier != 1f || item.BossDamageMultiplier != 1f || item.BossDamageAbsolute > 0f || item.BossOrbValueDollars > 0f || item.BossTintRed)
				{
					return true;
				}
			}
			return false;
		}

		internal static bool IsBoss(Component component)
		{
			if ((Object)(object)component == (Object)null)
			{
				return false;
			}
			EnemyParent componentInParent = component.GetComponentInParent<EnemyParent>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				return (Object)(object)((Component)componentInParent).GetComponentInChildren<EnemyHeadController>(true) != (Object)null;
			}
			return false;
		}

		internal static void SetPendingOrb(float value)
		{
			_pendingOrbValue = value;
			_pendingOrbUntil = Time.time + 6f;
		}

		internal static bool TryConsumeBossOrb(out float value)
		{
			value = _pendingOrbValue;
			if (_pendingOrbValue > 0f && Time.time <= _pendingOrbUntil)
			{
				_pendingOrbValue = 0f;
				return true;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(EnemyHealth), "Awake")]
	internal static class BossHealthPatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(0)]
		private static void Prefix(EnemyHealth __instance)
		{
			if (!BossStatsPatch.AnyBossEvent() || !BossStatsPatch.IsBoss((Component)(object)__instance))
			{
				return;
			}
			float num = 1f;
			float num2 = 0f;
			foreach (ChaosEvent item in EventState.Active)
			{
				num *= item.BossHealthMultiplier;
				if (item.BossHealthAbsolute > 0f)
				{
					num2 = item.BossHealthAbsolute;
				}
			}
			if (num2 > 0f)
			{
				__instance.health = Mathf.RoundToInt(num2);
			}
			else if (num != 1f)
			{
				__instance.health = Mathf.RoundToInt((float)__instance.health * num);
			}
		}

		[HarmonyPostfix]
		private static void Postfix(EnemyHealth __instance)
		{
			//IL_00ab: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
			if (!BossStatsPatch.AnyBossEvent() || !BossStatsPatch.IsBoss((Component)(object)__instance))
			{
				return;
			}
			bool flag = false;
			foreach (ChaosEvent item in EventState.Active)
			{
				flag |= item.BossTintRed;
			}
			if (!flag)
			{
				return;
			}
			try
			{
				EnemyParent componentInParent = ((Component)__instance).GetComponentInParent<EnemyParent>();
				Color val = default(Color);
				((Color)(ref val))..ctor(0.75f, 0.05f, 0.08f);
				Renderer[] componentsInChildren = ((Component)componentInParent).GetComponentsInChildren<Renderer>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					Material[] materials = componentsInChildren[i].materials;
					foreach (Material val2 in materials)
					{
						if ((Object)(object)val2 != (Object)null && val2.HasProperty("_Color"))
						{
							val2.color = Color.Lerp(val2.color, val, 0.65f);
						}
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning("[BrutalREPO] Кровавый оттенок Headman не применился: " + ex.Message);
			}
		}
	}
	[HarmonyPatch(typeof(EnemyNavMeshAgent), "Awake")]
	internal static class BossSpeedPatch
	{
		[HarmonyPrefix]
		private static void Prefix(EnemyNavMeshAgent __instance)
		{
			if (!BossStatsPatch.AnyBossEvent() || !BossStatsPatch.IsBoss((Component)(object)__instance))
			{
				return;
			}
			float num = 1f;
			foreach (ChaosEvent item in EventState.Active)
			{
				num *= item.BossSpeedMultiplier;
			}
			if (num != 1f)
			{
				NavMeshAgent component = ((Component)__instance).GetComponent<NavMeshAgent>();
				if ((Object)(object)component != (Object)null)
				{
					component.speed *= num;
					component.acceleration *= num;
				}
			}
		}
	}
	[HarmonyPatch(typeof(HurtCollider), "Awake")]
	internal static class BossDamagePatch
	{
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix(HurtCollider __instance)
		{
			if (!BossStatsPatch.AnyBossEvent() || __instance.playerDamage <= 0 || !BossStatsPatch.IsBoss((Component)(object)__instance))
			{
				return;
			}
			float num = 1f;
			float num2 = 0f;
			foreach (ChaosEvent item in EventState.Active)
			{
				num *= item.BossDamageMultiplier;
				if (item.BossDamageAbsolute > 0f)
				{
					num2 = item.BossDamageAbsolute;
				}
			}
			if (num2 > 0f)
			{
				__instance.playerDamage = Mathf.RoundToInt(num2);
			}
			else if (num != 1f)
			{
				__instance.playerDamage = Mathf.RoundToInt((float)__instance.playerDamage * num);
			}
		}
	}
	[HarmonyPatch(typeof(EnemyParent), "Despawn")]
	internal static class BossDespawnPatch
	{
		[HarmonyPrefix]
		private static void Prefix(EnemyParent __instance)
		{
			if (!BossStatsPatch.AnyBossEvent() || !BossStatsPatch.IsBoss((Component)(object)__instance))
			{
				return;
			}
			float num = 0f;
			foreach (ChaosEvent item in EventState.Active)
			{
				if (item.BossOrbValueDollars > 0f)
				{
					num = item.BossOrbValueDollars;
				}
			}
			if (!(num <= 0f) && Traverse.Create((object)__instance).Field("valuableSpawnTimer").GetValue<float>() > 0f)
			{
				BossStatsPatch.SetPendingOrb(num);
			}
		}
	}
	[HarmonyPatch(typeof(ChargingStation))]
	internal static class ChargingStationPatch
	{
		private static int _doneInstanceId = -1;

		private static int _doneRollId = -1;

		internal static bool OverridePurchasedCrystals;

		private static bool FillActive()
		{
			foreach (ChaosEvent item in EventState.Active)
			{
				if (item.FillChargingStation)
				{
					return true;
				}
			}
			return false;
		}

		private static bool InShop()
		{
			bool flag = (Object)(object)RunManager.instance != (Object)null && Traverse.Create((object)RunManager.instance).Field("levelIsShop").GetValue<bool>();
			return SemiFunc.RunIsShop() || flag;
		}

		[HarmonyPatch("Start")]
		[HarmonyPrefix]
		private static void Start_Prefix(ChargingStation __instance)
		{
			bool flag = EventState.HasAnyEffect && FillActive() && !InShop();
			Plugin.Log.LogInfo("[BrutalREPO] ChargingStation.Start: событие Extra power " + (flag ? "АКТИВНО" : "не активно (или магазин)") + " на момент старта станции.");
			if (flag)
			{
				OverridePurchasedCrystals = true;
				if ((Object)(object)StatsManager.instance != (Object)null)
				{
					StatsManager.instance.runStats["chargingStationChargeTotal"] = 100;
				}
			}
		}

		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void Start_Postfix(ChargingStation __instance)
		{
			if (OverridePurchasedCrystals)
			{
				OverridePurchasedCrystals = false;
				_doneInstanceId = ((Object)__instance).GetInstanceID();
				_doneRollId = EventState.RollId;
				Traverse val = Traverse.Create((object)__instance);
				Plugin.Log.LogInfo(string.Format("[BrutalREPO] Extra power (Start): chargeTotal={0}, ", val.Field("chargeTotal").GetValue<int>()) + string.Format("кристаллов на станции={0}, chargeInt={1}.", CountCrystals(__instance), val.Field("chargeInt").GetValue<int>()));
			}
		}

		private static int CountCrystals(ChargingStation station)
		{
			return Traverse.Create((object)station).Field("crystals").GetValue<ICollection>()?.Count ?? (-1);
		}

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void Update_Postfix(ChargingStation __instance)
		{
			if (!EventState.HasAnyEffect || !FillActive() || InShop())
			{
				return;
			}
			int instanceID = ((Object)__instance).GetInstanceID();
			if (_doneInstanceId == instanceID && _doneRollId == EventState.RollId)
			{
				return;
			}
			_doneInstanceId = instanceID;
			_doneRollId = EventState.RollId;
			Traverse val = Traverse.Create((object)__instance);
			int num = Mathf.Max(1, __instance.chargeSegments);
			int num2 = CountCrystals(__instance);
			val.Field("chargeTotal").SetValue((object)100);
			val.Field("chargeFloat").SetValue((object)1f);
			val.Field("chargeScale").SetValue((object)1f);
			val.Field("chargeScaleTarget").SetValue((object)1f);
			val.Field("chargeSegmentCurrent").SetValue((object)num);
			if ((Object)(object)StatsManager.instance != (Object)null)
			{
				StatsManager.instance.runStats["chargingStationChargeTotal"] = 100;
			}
			if (SemiFunc.IsMultiplayer() && SemiFunc.IsMasterClient())
			{
				PhotonView component = ((Component)__instance).GetComponent<PhotonView>();
				if ((Object)(object)component != (Object)null)
				{
					val.Field("lastSentSegment").SetValue((object)num);
					PhotonNetwork.RemoveBufferedRPCs(component.ViewID, "ChargingStationSegmentChangedRPC", (int[])null);
					component.RPC("ChargingStationSegmentChangedRPC", (RpcTarget)3, new object[1] { (byte)num });
				}
			}
			Plugin.Log.LogInfo($"[BrutalREPO] Extra power (Update, запасной путь): заряд выставлен на 100%, кристаллов на станции={num2}." + ((num2 <= 0) ? " Визуал станции (кристаллы/свет) вернуть нельзя — событие пришло после Start()." : ""));
		}
	}
	[HarmonyPatch(typeof(SemiFunc), "StatGetItemsPurchased")]
	internal static class PowerCrystalCountPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(string itemName, ref int __result)
		{
			if (!ChargingStationPatch.OverridePurchasedCrystals || itemName != "Item Power Crystal")
			{
				return true;
			}
			int value = 0;
			if ((Object)(object)StatsManager.instance != (Object)null)
			{
				StatsManager.instance.itemsPurchased.TryGetValue(itemName, out value);
			}
			__result = Mathf.Max(value, 10);
			return false;
		}
	}
	[HarmonyPatch(typeof(PlayerController))]
	internal static class DarknessDiagnosticPatch
	{
		private static bool _lastCrouch;

		private static bool _hasLast;

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void Update_Postfix(PlayerController __instance)
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			bool flag = false;
			foreach (ChaosEvent item in EventState.Active)
			{
				if (item.TriggerFullBlackout || item.DarknessBoost)
				{
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				_hasLast = false;
				return;
			}
			bool crouching = __instance.Crouching;
			if (_hasLast && crouching == _lastCrouch)
			{
				return;
			}
			bool num = !_hasLast;
			_hasLast = true;
			_lastCrouch = crouching;
			if (num)
			{
				return;
			}
			try
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.Append("[BrutalREPO][DARKDIAG] crouching=").Append(crouching);
				stringBuilder.Append(" ambient=").Append(RenderSettings.ambientLight);
				stringBuilder.Append(" fog=").Append(RenderSettings.fog).Append(" fogColor=")
					.Append(RenderSettings.fogColor)
					.Append(" fogStart=")
					.Append(RenderSettings.fogStartDistance)
					.Append(" fogEnd=")
					.Append(RenderSettings.fogEndDistance);
				FlashlightController instance = FlashlightController.Instance;
				if ((Object)(object)instance != (Object)null && (Object)(object)instance.spotlight != (Object)null)
				{
					stringBuilder.Append(" flashlight.enabled=").Append(((Behaviour)instance.spotlight).enabled).Append(" intensity=")
						.Append(instance.spotlight.intensity)
						.Append(" range=")
						.Append(instance.spotlight.range);
				}
				Vector3 pos = ((Component)__instance).transform.position;
				List<Light> list = (from l in Object.FindObjectsOfType<Light>()
					where (Object)(object)l != (Object)null && ((Behaviour)l).enabled && ((Component)l).gameObject.activeInHierarchy && l.intensity > 0.01f && Vector3.Distance(((Component)l).transform.position, pos) < 40f
					orderby l.intensity descending
					select l).ToList();
				stringBuilder.Append(" enabledLightsWithin40m=").Append(list.Count);
				foreach (Light item2 in list.Take(6))
				{
					stringBuilder.Append(" | ").Append(((Object)((Component)item2).gameObject).name).Append(" type=")
						.Append(item2.type)
						.Append(" int=")
						.Append(item2.intensity.ToString("0.00"))
						.Append(" dist=")
						.Append(Vector3.Distance(((Component)item2).transform.position, pos).ToString("0.0"));
				}
				Plugin.Log.LogInfo(stringBuilder.ToString());
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning("[BrutalREPO][DARKDIAG] ошибка: " + ex.Message);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerController))]
	internal static class DelayedSpawnPatch
	{
		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void Update_Postfix()
		{
			EventApplier.TryApplyDelayedSpawns();
		}
	}
	[HarmonyPatch(typeof(EnemyDirector))]
	internal static class EnemyCountPatch
	{
		private static readonly Random Rng = new Random();

		private static bool _namesDumped;

		[HarmonyPatch("AmountSetup")]
		[HarmonyPostfix]
		private static void AmountSetup_Postfix(EnemyDirector __instance)
		{
			if (!EventState.HasAnyEffect)
			{
				return;
			}
			Traverse val = Traverse.Create((object)__instance);
			List<EnemySetup> value = val.Field("enemyList").GetValue<List<EnemySetup>>();
			if (value == null)
			{
				return;
			}
			List<EnemySetup> value2 = val.Field("enemiesDifficulty1").GetValue<List<EnemySetup>>();
			List<EnemySetup> value3 = val.Field("enemiesDifficulty2").GetValue<List<EnemySetup>>();
			List<EnemySetup> value4 = val.Field("enemiesDifficulty3").GetValue<List<EnemySetup>>();
			List<EnemySetup> allKnownSetups = new List<EnemySetup>();
			CollectAll(value2);
			CollectAll(value3);
			CollectAll(value4);
			bool flag = false;
			int num = 0;
			float num2 = 1f;
			List<string> list = new List<string>();
			bool flag2 = false;
			HashSet<EnemySetup> forcedSetups = new HashSet<EnemySetup>();
			List<string> banNames = new List<string>();
			foreach (ChaosEvent item3 in EventState.Active)
			{
				if (item3.ForceAllEnemyTypes)
				{
					flag = true;
				}
				if (item3.EnemyCountDeltaMin != 0 || item3.EnemyCountDeltaMax != 0)
				{
					int minValue = Math.Min(item3.EnemyCountDeltaMin, item3.EnemyCountDeltaMax);
					int num3 = Math.Max(item3.EnemyCountDeltaMin, item3.EnemyCountDeltaMax);
					num += Rng.Next(minValue, num3 + 1);
				}
				if (!string.IsNullOrEmpty(item3.ForceSpecificEnemyExactName))
				{
					for (int i = 0; i < Math.Max(1, item3.ForceSpecificEnemyCount); i++)
					{
						list.Add(item3.ForceSpecificEnemyExactName);
					}
				}
				flag2 |= item3.OnlyForcedEnemies;
				if (item3.BanEnemyNamesContaining != null && item3.BanEnemyNamesContaining.Count > 0)
				{
					banNames.AddRange(item3.BanEnemyNamesContaining);
				}
				num2 *= item3.EnemyCountMultiplier;
			}
			int num4 = 0;
			int num5 = 0;
			if (!_namesDumped && allKnownSetups.Count > 0)
			{
				_namesDumped = true;
				Plugin.Log.LogInfo("[BrutalREPO][ENEMYNAMES] " + string.Join(" | ", from x in (from x in allKnownSetups
						where (Object)(object)x != (Object)null
						select ((Object)x).name).Distinct()
					orderby x
					select x));
			}
			if (flag)
			{
				foreach (EnemySetup item4 in allKnownSetups)
				{
					value.Add(item4);
					num4++;
				}
			}
			foreach (string exactName in list)
			{
				EnemySetup val2 = ((IEnumerable<EnemySetup>)allKnownSetups).FirstOrDefault((Func<EnemySetup, bool>)((EnemySetup s) => string.Equals(((Object)s).name, exactName, StringComparison.OrdinalIgnoreCase)));
				if ((Object)(object)val2 == (Object)null)
				{
					Plugin.Log.LogWarning("[BrutalREPO] ForceSpecificEnemyExactName=\"" + exactName + "\" не нашёл точного совпадения EnemySetup.");
					continue;
				}
				value.Add(val2);
				forcedSetups.Add(val2);
				num4++;
			}
			if (flag2 && forcedSetups.Count > 0)
			{
				int count = value.Count;
				value.RemoveAll((EnemySetup s2) => (Object)(object)s2 == (Object)null || !forcedSetups.Contains(s2));
				num5 += count - value.Count;
			}
			if (banNames.Count > 0)
			{
				int count2 = value.Count;
				value.RemoveAll((EnemySetup s) => (Object)(object)s != (Object)null && banNames.Any((string b) => ((Object)s).name.IndexOf(b, StringComparison.OrdinalIgnoreCase) >= 0));
				num5 += count2 - value.Count;
				if (value.Count == 0 && allKnownSetups.Count > 0)
				{
					EnemySetup val3 = ((IEnumerable<EnemySetup>)allKnownSetups).FirstOrDefault((Func<EnemySetup, bool>)((EnemySetup s) => !banNames.Any((string b) => ((Object)s).name.IndexOf(b, StringComparison.OrdinalIgnoreCase) >= 0)));
					if ((Object)(object)val3 != (Object)null)
					{
						value.Add(val3);
						num4++;
					}
				}
			}
			if (num < 0)
			{
				int num6 = Math.Min(-num, Math.Max(0, value.Count - 1));
				for (int num7 = 0; num7 < num6; num7++)
				{
					int index = Rng.Next(value.Count);
					value.RemoveAt(index);
					num5++;
				}
			}
			else if (num > 0)
			{
				for (int num8 = 0; num8 < num; num8++)
				{
					if (value.Count <= 0)
					{
						break;
					}
					EnemySetup item = value[Rng.Next(value.Count)];
					value.Add(item);
					num4++;
				}
			}
			if (num2 != 1f && value.Count > 0)
			{
				int num9 = Math.Max(value.Count, (int)Math.Round((float)value.Count * num2)) - value.Count;
				for (int num10 = 0; num10 < num9; num10++)
				{
					EnemySetup item2 = value[Rng.Next(value.Count)];
					value.Add(item2);
					num4++;
				}
			}
			if (num4 != 0 || num5 != 0)
			{
				int val4 = val.Field("totalAmount").GetValue<int>() + num4 - num5;
				val.Field("totalAmount").SetValue((object)Math.Max(0, val4));
			}
			void CollectAll(List<EnemySetup> pool)
			{
				if (pool == null)
				{
					return;
				}
				foreach (EnemySetup item5 in pool)
				{
					if ((Object)(object)item5 != (Object)null)
					{
						allKnownSetups.Add(item5);
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(HurtCollider))]
	internal static class EnemyDamagePatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void Awake_Postfix(HurtCollider __instance)
		{
			if (!EventState.HasAnyEffect)
			{
				return;
			}
			float num = 1f;
			foreach (ChaosEvent item in EventState.Active)
			{
				num *= item.EnemyDamageMultiplier;
			}
			if (num != 1f)
			{
				__instance.playerDamage = Mathf.RoundToInt((float)__instance.playerDamage * num);
			}
		}
	}
	[HarmonyPatch(typeof(EnemyHealth))]
	internal static class EnemyHealthPatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPrefix]
		private static void Awake_Prefix(EnemyHealth __instance)
		{
			if (!EventState.HasAnyEffect)
			{
				return;
			}
			float num = 1f;
			bool flag = false;
			foreach (ChaosEvent item in EventState.Active)
			{
				num *= item.EnemyHealthMultiplier;
				flag |= item.NoEnemyOrbs;
			}
			if (flag)
			{
				__instance.spawnValuable = false;
			}
			if (num != 1f)
			{
				__instance.health = Mathf.RoundToInt((float)__instance.health * num);
			}
		}
	}
	[HarmonyPatch(typeof(EnemyNavMeshAgent))]
	internal static class EnemySpeedPatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPrefix]
		private static void Awake_Prefix(EnemyNavMeshAgent __instance)
		{
			if (!EventState.HasAnyEffect)
			{
				return;
			}
			float num = 1f;
			foreach (ChaosEvent item in EventState.Active)
			{
				num *= item.EnemySpeedMultiplier;
			}
			if (num != 1f)
			{
				NavMeshAgent component = ((Component)__instance).GetComponent<NavMeshAgent>();
				if (!((Object)(object)component == (Object)null))
				{
					component.speed *= num;
					component.acceleration *= num;
				}
			}
		}
	}
	[HarmonyPatch(typeof(EnemyHealth))]
	internal static class EnemyTintPatch
	{
		private static readonly Color DarkTint = new Color(0.18f, 0.18f, 0.2f);

		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void Awake_Postfix(EnemyHealth __instance)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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)
			bool flag = false;
			foreach (ChaosEvent item in EventState.Active)
			{
				if (item.TintEnemiesDark)
				{
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				return;
			}
			Renderer[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Material[] materials = componentsInChildren[i].materials;
				foreach (Material val in materials)
				{
					if (val.HasProperty("_Color"))
					{
						val.color *= DarkTint;
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(EnemyVision), "Awake")]
	internal static class EnemyVisionPatch
	{
		[HarmonyPostfix]
		private static void Awake_Postfix(EnemyVision __instance)
		{
			if (!EventState.HasAnyEffect)
			{
				return;
			}
			float num = 1f;
			foreach (ChaosEvent item in EventState.Active)
			{
				num *= item.EnemyVisionMultiplier;
			}
			if (num != 1f)
			{
				__instance.VisionDistance *= num;
				__instance.VisionDistanceClose *= num;
				__instance.VisionDistanceCloseCrouch *= num;
			}
		}
	}
	[HarmonyPatch(typeof(PlayerController))]
	internal static class EnergyRegenPatch
	{
		[HarmonyPatch("Update")]
		[HarmonyPrefix]
		private static void Update_Prefix(PlayerController __instance, out float __state)
		{
			__state = __instance.EnergyCurrent;
		}

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void Update_Postfix(PlayerController __instance, float __state)
		{
			if (!EventState.HasAnyEffect)
			{
				return;
			}
			float num = 1f;
			foreach (ChaosEvent item in EventState.Active)
			{
				num *= item.EnergyRegenMultiplier;
			}
			if (num != 1f)
			{
				float num2 = __instance.EnergyCurrent - __state;
				if (!(num2 <= 0f))
				{
					float num3 = num2 * (num - 1f);
					__instance.EnergyCurrent = Mathf.Min(__instance.EnergyCurrent + num3, __instance.EnergyStart);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ExtractionPoint))]
	internal static class ExtractionMoneyPatch
	{
		private const int NoSnapshot = int.MinValue;

		[HarmonyPatch("StateComplete")]
		[HarmonyPrefix]
		private static void Complete_Prefix(out int __state)
		{
			__state = Snapshot();
		}

		[HarmonyPatch("StateComplete")]
		[HarmonyPostfix]
		private static void Complete_Postfix(int __state)
		{
			Adjust(__state);
		}

		[HarmonyPatch("StateTaxReturn")]
		[HarmonyPrefix]
		private static void TaxReturn_Prefix(out int __state)
		{
			__state = Snapshot();
		}

		[HarmonyPatch("StateTaxReturn")]
		[HarmonyPostfix]
		private static void TaxReturn_Postfix(int __state)
		{
			Adjust(__state);
		}

		private static int Snapshot()
		{
			if (!EventState.HasAnyEffect || !SemiFunc.IsMasterClientOrSingleplayer())
			{
				return int.MinValue;
			}
			return SemiFunc.StatGetRunCurrency();
		}

		private static void Adjust(int before)
		{
			if (before == int.MinValue)
			{
				return;
			}
			int num = SemiFunc.StatGetRunCurrency() - before;
			if (num <= 0)
			{
				return;
			}
			if (EventState.NoExtractionMoney)
			{
				SemiFunc.StatSetRunCurrency(before);
				Plugin.Log.LogInfo($"[BrutalREPO] The collector: отменено начисление {num}k за экстракцию.");
				return;
			}
			float extractionMoneyMultiplier = EventState.ExtractionMoneyMultiplier;
			if (extractionMoneyMultiplier != 1f)
			{
				int num2 = Mathf.Max(0, Mathf.RoundToInt((float)num * extractionMoneyMultiplier));
				SemiFunc.StatSetRunCurrency(before + num2);
			}
			float extractionBonusDollars = EventState.ExtractionBonusDollars;
			if (extractionBonusDollars > 0f)
			{
				EventApplier.AddDollarsToRunCurrency(extractionBonusDollars);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerHealth))]
	internal static class PlayerHealthEventsPatch
	{
		private static readonly Random Rng = new Random();

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

		[HarmonyPatch("Hurt")]
		[HarmonyPrefix]
		private static bool Hurt_Prefix(PlayerHealth __instance, int damage, bool savingGrace, int enemyIndex)
		{
			//IL_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			if (damage <= 0 || !EventState.HasAnyEffect)
			{
				return true;
			}
			Traverse val = Traverse.Create((object)__instance);
			PlayerAvatar value = val.Field("playerAvatar").GetValue<PlayerAvatar>();
			PhotonView value2 = val.Field("photonView").GetValue<PhotonView>();
			if ((Object)(object)value == (Object)null || val.Field("invincibleTimer").GetValue<float>() > 0f || val.Field("godMode").GetValue<bool>() || Traverse.Create((object)value).Field("deadSet").GetValue<bool>() || (SemiFunc.IsMultiplayer() && (Object)(object)value2 != (Object)null && !value2.IsMine))
			{
				return true;
			}
			if (enemyIndex >= 0)
			{
				float num = 0f;
				foreach (ChaosEvent item in EventState.Active)
				{
					num += item.DodgeChancePercent;
				}
				if (num > 0f && Rng.NextDouble() * 100.0 < (double)num)
				{
					Announce("Dodge!", new Color(0.4f, 0.9f, 1f));
					return false;
				}
			}
			bool flag = false;
			foreach (ChaosEvent item2 in EventState.Active)
			{
				flag |= item2.GrantExtraLife;
			}
			if (!flag)
			{
				return true;
			}
			int value3 = val.Field("health").GetValue<int>();
			int value4 = val.Field("maxHealth").GetValue<int>();
			if ((savingGrace && damage <= 25 && value3 > 5 && value3 <= 20) || value3 - damage > 0)
			{
				return true;
			}
			string value5 = Traverse.Create((object)value).Field("steamID").GetValue<string>();
			if (string.IsNullOrEmpty(value5))
			{
				Plugin.Log.LogWarning("[BrutalREPO] Give me one chance: у игрока пустой steamID — ревайв невозможен.");
				return true;
			}
			if (UsedRollIdPerPlayer.TryGetValue(value5, out var value6) && value6 == EventState.RollId)
			{
				return true;
			}
			UsedRollIdPerPlayer[value5] = EventState.RollId;
			int num2 = Mathf.Max(1, Mathf.RoundToInt((float)value4 * 0.5f));
			val.Field("health").SetValue((object)num2);
			val.Field("invincibleTimer").SetValue((object)2f);
			try
			{
				if ((Object)(object)StatsManager.instance != (Object)null)
				{
					StatsManager.instance.SetPlayerHealth(value5, num2, false);
				}
				if (SemiFunc.IsMultiplayer() && (Object)(object)value2 != (Object)null)
				{
					value2.RPC("UpdateHealthRPC", (RpcTarget)1, new object[4] { num2, value4, true, false });
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning("[BrutalREPO] Give me one chance: не удалось синхронизировать здоровье: " + ex.Message);
			}
			Plugin.Log.LogInfo($"[BrutalREPO] Give me one chance: смертельный удар ({damage} урона при {value3} HP) отменён, игрок поднят до {num2} HP.");
			Announce("Second chance!", new Color(0.3f, 1f, 0.4f));
			return false;
		}

		private static void Announce(string text, Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				SemiFunc.UIFocusText(text, color, color, 1.5f);
			}
			catch (Exception)
			{
			}
		}
	}
	[HarmonyPatch(typeof(EnvironmentDirector))]
	internal static class FogPatch
	{
		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void Update_Postfix(EnvironmentDirector __instance)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			bool flag = false;
			float num = float.MaxValue;
			Color val = Color.black;
			foreach (ChaosEvent item in EventState.Active)
			{
				if (item.TriggerFog)
				{
					flag = true;
					if (item.FogEndDistance < num)
					{
						num = item.FogEndDistance;
						val = item.FogColor;
					}
				}
			}
			if (flag)
			{
				Traverse obj = Traverse.Create((object)__instance);
				obj.Field("FogColor").SetValue((object)val);
				obj.Field("FogStartDistance").SetValue((object)1f);
				obj.Field("FogEndDistance").SetValue((object)num);
				obj.Field("FogTransitionLerp").SetValue((object)1f);
			}
		}
	}
	[HarmonyPatch(typeof(EnvironmentDirector))]
	internal static class DarknessPatch
	{
		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void Update_Postfix(EnvironmentDirector __instance)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			bool flag = false;
			foreach (ChaosEvent item in EventState.Active)
			{
				if (item.DarknessBoost)
				{
					flag = true;
					break;
				}
			}
			if (flag)
			{
				Traverse obj = Traverse.Create((object)__instance);
				obj.Field("AmbientColor").SetValue((object)new Color(0.02f, 0.02f, 0.03f));
				obj.Field("AmbientTransitionLerp").SetValue((object)1f);
			}
		}
	}
	[HarmonyPatch(typeof(RoundDirector))]
	internal static class GrenadePatch
	{
		private static readonly Random Rng = new Random();

		private static float _tickTimer;

		private static PrefabRef _grenadePrefabRef;

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void Update_Postfix()
		{
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: 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_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			float num = 0f;
			foreach (ChaosEvent item in EventState.Active)
			{
				num += item.GrenadePercentChancePerSecond;
			}
			if (num <= 0f || !SemiFunc.IsMasterClientOrSingleplayer() || (Object)(object)LevelGenerator.Instance == (Object)null || !LevelGenerator.Instance.Generated)
			{
				return;
			}
			_tickTimer += Time.deltaTime;
			if (_tickTimer < 1f)
			{
				return;
			}
			_tickTimer = 0f;
			if (Rng.NextDouble() * 100.0 >= (double)num)
			{
				return;
			}
			if (_grenadePrefabRef == null)
			{
				ExtractionPoint val = Object.FindObjectOfType<ExtractionPoint>();
				if ((Object)(object)val == (Object)null || val.grenadeRef == null)
				{
					return;
				}
				_grenadePrefabRef = val.grenadeRef;
			}
			List<PlayerAvatar> list = new List<PlayerAvatar>();
			foreach (PlayerAvatar item2 in SemiFunc.PlayerGetAll())
			{
				if (!((Object)(object)item2 == (Object)null))
				{
					Traverse val2 = Traverse.Create((object)item2);
					if (!val2.Field("deadSet").GetValue<bool>() && !val2.Field("isDisabled").GetValue<bool>())
					{
						list.Add(item2);
					}
				}
			}
			if (list.Count != 0)
			{
				PlayerAvatar obj = list[Rng.Next(list.Count)];
				Vector3 val3 = default(Vector3);
				((Vector3)(ref val3))..ctor((float)(Rng.NextDouble() - 0.5) * 1f, 0.6f, (float)(Rng.NextDouble() - 0.5) * 1f);
				Vector3 val4 = ((Component)obj).transform.position + val3;
				GameObject val5 = ((!SemiFunc.IsMultiplayer()) ? Object.Instantiate<GameObject>(((PrefabRef<GameObject>)(object)_grenadePrefabRef).Prefab, val4, Quaternion.identity) : PhotonNetwork.InstantiateRoomObject(((PrefabRef<GameObject>)(object)_grenadePrefabRef).ResourcePath, val4, Quaternion.identity, (byte)0, (object[])null));
				if ((Object)(object)val5 != (Object)null)
				{
					Activate(val5);
				}
			}
		}

		private static void Activate(GameObject grenadeObject)
		{
			ItemGrenade component = grenadeObject.GetComponent<ItemGrenade>();
			if ((Object)(object)component == (Object)null)
			{
				Plugin.Log.LogWarning("[BrutalREPO] Boooom?!: у заспавненного объекта нет ItemGrenade — активировать нечего.");
				return;
			}
			ItemGrenadeHuman component2 = grenadeObject.GetComponent<ItemGrenadeHuman>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.Initialize();
				component2.Spawn();
			}
			else
			{
				((MonoBehaviour)component).StartCoroutine(ActivateRoutine(grenadeObject, component));
			}
		}

		private static IEnumerator ActivateRoutine(GameObject go, ItemGrenade grenade)
		{
			PhysGrabObject physGrabObject = go.GetComponent<PhysGrabObject>();
			Rigidbody rb = go.GetComponent<Rigidbody>();
			ItemToggle toggle = go.GetComponent<ItemToggle>();
			float timeout = 5f;
			while (timeout > 0f && (Object)(object)go != (Object)null && ((!((Object)(object)physGrabObject == (Object)null) && !Traverse.Create((object)physGrabObject).Field("spawned").GetValue<bool>()) || (!((Object)(object)rb == (Object)null) && rb.isKinematic)))
			{
				timeout -= Time.deltaTime;
				yield return null;
			}
			if (!((Object)(object)go == (Object)null) && !((Object)(object)toggle == (Object)null))
			{
				grenade.isSpawnedGrenade = true;
				grenade.tickTime = Random.Range(2f, 3f);
				toggle.ToggleItem(true, -1);
				if ((Object)(object)rb != (Object)null && !rb.isKinematic)
				{
					rb.AddForce(Vector3.up * Random.Range(2f, 4f), (ForceMode)1);
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerController))]
	internal static class HastePatch
	{
		private struct Applied
		{
			public int RollId;

			public float Multiplier;
		}

		private static readonly Dictionary<PlayerController, Applied> LastApplied = new Dictionary<PlayerController, Applied>();

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void Update_Postfix(PlayerController __instance)
		{
			float num = 1f;
			foreach (ChaosEvent item in EventState.Active)
			{
				num *= item.PlayerSpeedMultiplier;
			}
			float num2 = 1f;
			if (LastApplied.TryGetValue(__instance, out var value))
			{
				if (value.RollId == EventState.RollId)
				{
					return;
				}
				num2 = value.Multiplier;
			}
			else if (num == 1f)
			{
				return;
			}
			LastApplied[__instance] = new Applied
			{
				RollId = EventState.RollId,
				Multiplier = num
			};
			float num3 = num / num2;
			if (num3 != 1f)
			{
				Traverse obj = Traverse.Create((object)__instance);
				float value2 = obj.Field("playerOriginalMoveSpeed").GetValue<float>();
				obj.Field("playerOriginalMoveSpeed").SetValue((object)(value2 * num3));
				__instance.MoveSpeed *= num3;
				float value3 = obj.Field("playerOriginalSprintSpeed").GetValue<float>();
				obj.Field("playerOriginalSprintSpeed").SetValue((object)(value3 * num3));
				__instance.SprintSpeed *= num3;
			}
		}
	}
	[HarmonyPatch(typeof(RoundDirector))]
	internal static class HaulGoalPatch
	{
		[HarmonyPatch("StartRoundLogic")]
		[HarmonyPrefix]
		private static void StartRoundLogic_Prefix(ref int value)
		{
			if (!EventState.HasAnyEffect)
			{
				return;
			}
			float num = 1f;
			foreach (ChaosEvent item in EventState.Active)
			{
				num *= item.HaulGoalMultiplier;
			}
			if (num != 1f)
			{
				value = Mathf.RoundToInt((float)value * num);
			}
		}
	}
	[HarmonyPatch(typeof(LevelGenerator))]
	internal static class LevelStartPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPrefix]
		private static void Start_Prefix()
		{
			ChaosPanelUI.EnsureCreated();
			ChaosNetworking.EnsureRegistered();
			TrickOrTreat.ResetRuntime();
			UpgradeSwap.RestoreIfApplied();
			bool num = SemiFunc.RunIsLevel();
			bool flag = SemiFunc.RunIsShop();
			if (!num && !flag)
			{
				EventState.SetActive(new List<ChaosEvent>());
				return;
			}
			if (SemiFunc.IsMultiplayer() && !SemiFunc.IsMasterClient())
			{
				ChaosNetworking.TryReadFromRoomNow();
				return;
			}
			List<ChaosEvent> list = null;
			if (Plugin.DebugModeEnabled.Value)
			{
				list = TryBuildDebugForcedList(flag);
			}
			int drop = 0;
			float difficulty = (flag ? (-1f) : DifficultyScale.Compute(out drop));
			if (list == null)
			{
				list = ((!flag) ? EventRoller.RollMultiple(Plugin.EventCountScale.Evaluate(difficulty), Plugin.AbsoluteMaxActiveEvents.Value, Plugin.ExtraEventChance.Value, (EventTier tier) => Plugin.WeightFor(tier, difficulty), (SemiFunc.PlayerGetAll() == null) ? 1 : SemiFunc.PlayerGetAll().Count) : EventRoller.RollShop(Plugin.WeightShopOnly.Value));
			}
			string stealVictimSteamId = PickStealVictimIfNeeded(list);
			string a = null;
			string b = null;
			PickSwapPairIfNeeded(list, out a, out b);
			int nameSeed = new Random().Next();
			int difficulty2 = ((difficulty < 0f) ? (-1) : Mathf.RoundToInt(difficulty));
			Dictionary<EventTier, float> dictionary = (flag ? null : EventRoller.ComputeTierShares((EventTier tier) => Plugin.WeightFor(tier, difficulty)));
			EventState.SetActive(list, stealVictimSteamId, nameSeed, difficulty2, drop);
			EventState.SetTierShares(dictionary);
			EventState.SetSwapPair(a, b);
			EventApplier.ApplyHostOnlyEffects();
			EventApplier.TryApplyLocalPlayerEffects();
			ChaosNetworking.PublishToRoom(list, stealVictimSteamId, nameSeed, difficulty2, drop, EventState.SerializeShares(dictionary), (a != null && b != null) ? (a + "|" + b) : "");
		}

		private static List<ChaosEvent> TryBuildDebugForcedList(bool isShop)
		{
			string value = Plugin.DebugForceEventId.Value;
			if (string.IsNullOrEmpty(value))
			{
				Plugin.DebugModeEnabled.Value = false;
				return null;
			}
			if (!EventTable.TryGetById(value, out var chaosEvent))
			{
				Plugin.Log.LogWarning("[BrutalREPO] DebugForceEventId=\"" + value + "\" не найден — обычный ролл.");
				Plugin.DebugModeEnabled.Value = false;
				return null;
			}
			if (chaosEvent.Tier == EventTier.ShopOnly != isShop)
			{
				return null;
			}
			Plugin.DebugModeEnabled.Value = false;
			return new List<ChaosEvent> { chaosEvent };
		}

		private static void PickSwapPairIfNeeded(List<ChaosEvent> chosen, out string a, out string b)
		{
			a = null;
			b = null;
			bool flag = false;
			foreach (ChaosEvent item in chosen)
			{
				if (item.SwapTwoPlayersUpgrades)
				{
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				return;
			}
			List<string> list = new List<string>();
			foreach (PlayerAvatar item2 in SemiFunc.PlayerGetAll())
			{
				string text = (((Object)(object)item2 != (Object)null) ? SemiFunc.PlayerGetSteamID(item2) : null);
				if (!string.IsNullOrEmpty(text) && !list.Contains(text))
				{
					list.Add(text);
				}
			}
			if (list.Count < 2)
			{
				return;
			}
			Random random = new Random();
			for (int i = 0; i < 16; i++)
			{
				int num = random.Next(list.Count);
				int num2 = random.Next(list.Count - 1);
				if (num2 >= num)
				{
					num2++;
				}
				a = list[num];
				b = list[num2];
				if (UpgradeSwap.TotalLevels(a) != UpgradeSwap.TotalLevels(b))
				{
					break;
				}
			}
		}

		private static string PickStealVictimIfNeeded(List<ChaosEvent> chosen)
		{
			bool flag = false;
			foreach (ChaosEvent item in chosen)
			{
				if (item.StealUpgradeFromOneRandomPlayer != 0)
				{
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				return null;
			}
			List<PlayerAvatar> list = new List<PlayerAvatar>(SemiFunc.PlayerGetAll());
			if (list.Count == 0)
			{
				return null;
			}
			Random random = new Random();
			return Traverse.Create((object)list[random.Next(list.Count)]).Field("steamID").GetValue<string>();
		}
	}
	[HarmonyPatch(typeof(LightManager))]
	internal static class LightsPatch
	{
		private static readonly Color RedTint = new Color(1f, 0.08f, 0.05f);

		private static float _rescanTimer;

		private static int _lastRollId = -1;

		private static readonly HashSet<int> Dimmed = new HashSet<int>();

		private static readonly List<Light> PartyCache = new List<Light>();

		private const float PartyHueSpeed = 0.12f;

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void Update_Postfix()
		{
			//IL_011b: 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)
			bool flag = false;
			bool flag2 = false;
			float num = 1f;
			foreach (ChaosEvent item in EventState.Active)
			{
				flag |= item.TintLightsRed;
				flag2 |= item.PartyLights;
				num *= item.LightIntensityMultiplier;
			}
			if (flag)
			{
				flag2 = false;
			}
			if ((!flag && !flag2 && num == 1f) || (Object)(object)LevelGenerator.Instance == (Object)null || !LevelGenerator.Instance.Generated)
			{
				return;
			}
			if (_lastRollId != EventState.RollId)
			{
				_lastRollId = EventState.RollId;
				Dimmed.Clear();
				_rescanTimer = 0f;
			}
			if (flag2)
			{
				float num2 = Time.time * 0.12f;
				for (int num3 = PartyCache.Count - 1; num3 >= 0; num3--)
				{
					Light val = PartyCache[num3];
					if ((Object)(object)val == (Object)null)
					{
						PartyCache.RemoveAt(num3);
					}
					else
					{
						float num4 = Mathf.Repeat(num2 + (float)num3 * 0.137f, 1f);
						val.color = Color.HSVToRGB(num4, 0.85f, 1f);
					}
				}
			}
			_rescanTimer -= Time.deltaTime;
			if (_rescanTimer > 0f)
			{
				return;
			}
			_rescanTimer = 4f;
			if (flag2)
			{
				PartyCache.Clear();
			}
			PropLight[] array = Object.FindObjectsOfType<PropLight>();
			foreach (PropLight val2 in array)
			{
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				Light value = Traverse.Create((object)val2).Field("lightComponent").GetValue<Light>();
				if (!((Object)(object)value == (Object)null))
				{
					if (flag)
					{
						value.color = RedTint;
					}
					if (flag2)
					{
						PartyCache.Add(value);
					}
					if (num != 1f && Dimmed.Add(((Object)val2).GetInstanceID()))
					{
						val2.SetIntensity(value.intensity * num);
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(InputManager))]
	internal static class MouseInvertPatch
	{
		[HarmonyPatch("GetMouseX")]
		[HarmonyPostfix]
		private static void GetMouseX_Postfix(ref float __result)
		{
			if (!EventState.HasAnyEffect)
			{
				return;
			}
			foreach (ChaosEvent item in EventState.Active)
			{
				if (item.InvertMouseX)
				{
					__result = 0f - __result;
					break;
				}
			}
		}
	}
	[HarmonyPatch(typeof(EnemyHealth))]
	internal static class OverPowerPatch
	{
		[HarmonyPatch("Hurt")]
		[HarmonyPrefix]
		private static void Hurt_Prefix(ref int _damage)
		{
			if (!EventState.HasAnyEffect)
			{
				return;
			}
			float num = 1f;
			foreach (ChaosEvent item in EventState.Active)
			{
				num *= item.PlayerDamageDealtMultiplier;
			}
			if (num != 1f)
			{
				_damage = Mathf.RoundToInt((float)_damage * num);
			}
		}
	}
	[HarmonyPatch(typeof(InputManager), "GetScrollY")]
	internal static class PanelScrollBlockPatch
	{
		[HarmonyPostfix]
		private static void Postfix(ref float __result)
		{
			if (ChaosPanelUI.IsHeld)
			{
				__result = 0f;
			}
		}
	}
	[HarmonyPatch(typeof(PlayerController))]
	internal static class PeriodicHealPatch
	{
		private static readonly Dictionary<PlayerController, float> Timers = new Dictionary<PlayerController, float>();

		private static float _carryHp;

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void Update_Postfix(PlayerController __instance)
		{
			float num = float.MaxValue;
			float num2 = 0f;
			foreach (ChaosEvent item in EventState.Active)
			{
				if (!(item.HealthRegenPercentPerTick <= 0f))
				{
					float num3 = Mathf.Max(0.1f, item.HealthRegenIntervalSeconds);
					num2 += item.HealthRegenPercentPerTick / num3;
					if (num3 < num)
					{
						num = num3;
					}
				}
			}
			if (num2 <= 0f)
			{
				Timers.Remove(__instance);
				_carryHp = 0f;
				return;
			}
			if (!Timers.TryGetValue(__instance, out var value))
			{
				value = 0f;
			}
			value += Time.deltaTime;
			if (value < num)
			{
				Timers[__instance] = value;
				return;
			}
			Timers[__instance] = 0f;
			PlayerAvatar val = SemiFunc.PlayerAvatarLocal();
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val.playerHealth == (Object)null))
			{
				int value2 = Traverse.Create((object)val.playerHealth).Field("maxHealth").GetValue<int>();
				_carryHp += (float)value2 * (num2 * num / 100f);
				int num4 = Ma