Decompiled source of HextechProtocolStellar v0.9.23

HexMod.dll

Decompiled 3 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace VoidHex;

[HarmonyPatch(typeof(AssemblerComponent), "InternalUpdate")]
public static class AssemblerCritPatch
{
	[HarmonyPostfix]
	public static void Post(AssemblerComponent __instance)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Effects.OnProduced(__instance);
		}
		catch (Exception)
		{
		}
	}
}
[HarmonyPatch(typeof(Mecha), "TakeDamage")]
public static class MechaDamagePatch
{
	[HarmonyPrefix]
	public static void Pre(Mecha __instance, ref int __0)
	{
		try
		{
			__0 = Effects.OnMechaDamage(__instance, __0);
		}
		catch (Exception)
		{
		}
	}
}
[HarmonyPatch(typeof(Mecha), "GameTick")]
public static class AmmoAllPatch
{
	[HarmonyPostfix]
	public static void Post(Mecha __instance)
	{
		try
		{
			if (__instance == null || !Effects.AmmoAllOn)
			{
				return;
			}
			__instance.laserActive = true;
			try
			{
				FieldInfo field = typeof(Mecha).GetField("bombActive", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					field.SetValue(__instance, true);
				}
			}
			catch (Exception)
			{
			}
		}
		catch (Exception)
		{
		}
	}
}
public enum Rarity
{
	Silver,
	Gold,
	Prism
}
[BepInPlugin("aimod.VoidHex", "Hextech Protocol: Stellar", "0.9.23")]
public class Plugin : BaseUnityPlugin
{
	public const string GUID = "aimod.VoidHex";

	public const string NAME = "Hextech Protocol: Stellar";

	public const string VERSION = "0.9.23";

	internal static ManualLogSource Log;

	private int tick;

	private void Awake()
	{
		Log = ((BaseUnityPlugin)this).Logger;
		try
		{
			Catalog.Build();
			Catalog.Verify();
			Compat.Detect();
			HexState.Load();
			foreach (string item in HexState.Owned)
			{
				Effects.OnAcquire(item);
			}
			Log.LogInfo((object)("0.9.23 installed, hexes=" + Catalog.All.Count));
		}
		catch (Exception ex)
		{
			Log.LogError((object)("awake: " + ex));
		}
	}

	private void Update()
	{
		try
		{
			Effects.CheckHotkey();
			string text = HexState.CurrentKey();
			if (text != null && text != HexState.LoadedKey)
			{
				HexState.LoadedKey = text;
				HexState.Load();
				foreach (string item in HexState.Owned)
				{
					Effects.OnAcquire(item);
				}
				Effects.RestoreApplied();
				Effects.InvalidateHard();
				Log.LogInfo((object)("save loaded: " + text + " (owned=" + HexState.Owned.Count + ", pending=" + HexState.Pending + ")"));
			}
			if (++tick % 30 == 0)
			{
				Watch.Award();
				Effects.Tick();
			}
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("update: " + ex.Message));
		}
	}

	private void OnGUI()
	{
		GUI.depth = ((!HexState.Drawing) ? 200 : 0);
		try
		{
			DrawUI.OnGUI();
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("gui: " + ex.Message));
		}
		GUI.depth = 200;
		try
		{
			MechaPanelBar.OnGUI();
		}
		catch (Exception ex2)
		{
			Log.LogWarning((object)("gui bar: " + ex2.Message));
		}
	}
}
public enum HexKind
{
	HpFlat,
	HpPct,
	ShieldPct,
	ShieldFromHp,
	WalkPct,
	JumpPct,
	SailPct,
	WarpPct,
	RegenHpPct,
	RegenShieldPct,
	FleetAdd,
	GrantMatrices,
	RerollAllPrism,
	StackBoost,
	AllStatsPct,
	WeaponDmgPct,
	DroneAllPct,
	KineticToBlast,
	BlastToEnergy,
	RangePct,
	LaserBoost,
	MuzzleAdd,
	PenetrationPct,
	KillHp,
	KillQuest,
	DroneDmgPct,
	DroneRofPct,
	DroneDurPct,
	StarLumPct,
	Fractionator,
	WarperRefund,
	AmmoAll,
	AmmoRofPct,
	CritHex,
	CritDouble,
	CritDmg,
	CritProd,
	SprayLight,
	SprayHeavy,
	KillBuff,
	EjectorSpeed,
	TurretBoost,
	VeinGuard,
	AssemblerSpeed,
	RecipeFree,
	BeltSpeed,
	PowerCut,
	WindBoost,
	DropBoost,
	StationMine,
	GenBoost
}
internal static class Compat
{
	internal static bool OrbitalRing;

	internal static bool GenesisBook;

	internal static bool Tcfv;

	internal static bool Mms;

	internal static void Detect()
	{
		OrbitalRing = HasGuid("org.ProfessorCat305.OrbitalRing") || Has("ProjectOrbitalRing");
		GenesisBook = HasGuid("org.LoShin.GenesisBook") || Has("ProjectGenesis");
		Tcfv = HasGuid("ckcz123.DSP_Battle") || Has("DSP_Battle");
		Mms = HasGuid("MoreMegaStructure") || Has("MoreMegaStructure") || Has("MMS");
		Plugin.Log.LogInfo((object)("compat: OrbitalRing=" + OrbitalRing + " GenesisBook=" + GenesisBook + " TCFV=" + Tcfv + " MMS=" + Mms));
	}

	private static bool HasGuid(string guid)
	{
		try
		{
			if (Chainloader.PluginInfos == null)
			{
				return false;
			}
			foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos)
			{
				if (pluginInfo.Key != null && pluginInfo.Key.ToLowerInvariant() == guid.ToLowerInvariant())
				{
					return true;
				}
			}
		}
		catch (Exception)
		{
		}
		return false;
	}

	private static bool Has(string assemblyName)
	{
		try
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				if (!(assembly == null))
				{
					string name = assembly.GetName().Name;
					if (name == assemblyName)
					{
						return true;
					}
				}
			}
		}
		catch (Exception)
		{
		}
		return false;
	}
}
internal static class IconStore
{
	private static readonly Dictionary<string, Texture2D> cache = new Dictionary<string, Texture2D>();

	internal static Texture2D Get(string id)
	{
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Expected O, but got Unknown
		if (string.IsNullOrEmpty(id))
		{
			return null;
		}
		if (cache.TryGetValue(id, out var value))
		{
			return value;
		}
		try
		{
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			Stream manifestResourceStream = executingAssembly.GetManifestResourceStream("VoidHex.icons." + id + ".png");
			if (manifestResourceStream == null)
			{
				return null;
			}
			byte[] array = new byte[manifestResourceStream.Length];
			manifestResourceStream.Read(array, 0, array.Length);
			value = new Texture2D(2, 2, (TextureFormat)4, false);
			if (!ImageConversion.LoadImage(value, array))
			{
				value = null;
			}
			cache[id] = value;
		}
		catch (Exception)
		{
		}
		return value;
	}
}
public class HexDef
{
	public string Id;

	public string Name;

	public string Desc;

	public Rarity R;

	public List<KeyValuePair<HexKind, double>> Mods = new List<KeyValuePair<HexKind, double>>();

	public bool Once;
}
internal static class Catalog
{
	internal static readonly List<HexDef> All = new List<HexDef>();

	private static readonly Dictionary<string, HexDef> map = new Dictionary<string, HexDef>();

	private static readonly HashSet<HexKind> Wired = new HashSet<HexKind>
	{
		HexKind.HpFlat,
		HexKind.HpPct,
		HexKind.ShieldPct,
		HexKind.ShieldFromHp,
		HexKind.WalkPct,
		HexKind.JumpPct,
		HexKind.SailPct,
		HexKind.WarpPct,
		HexKind.RegenHpPct,
		HexKind.RegenShieldPct,
		HexKind.FleetAdd,
		HexKind.WeaponDmgPct,
		HexKind.DroneDmgPct,
		HexKind.DroneRofPct,
		HexKind.DroneDurPct,
		HexKind.RangePct,
		HexKind.MuzzleAdd,
		HexKind.PenetrationPct,
		HexKind.KillHp,
		HexKind.KillQuest,
		HexKind.StackBoost,
		HexKind.KineticToBlast,
		HexKind.BlastToEnergy,
		HexKind.StarLumPct,
		HexKind.Fractionator,
		HexKind.WarperRefund,
		HexKind.AmmoAll,
		HexKind.AmmoRofPct,
		HexKind.GrantMatrices,
		HexKind.RerollAllPrism,
		HexKind.LaserBoost,
		HexKind.CritHex,
		HexKind.CritDouble,
		HexKind.CritDmg,
		HexKind.CritProd,
		HexKind.SprayLight,
		HexKind.SprayHeavy,
		HexKind.KillBuff,
		HexKind.EjectorSpeed,
		HexKind.TurretBoost,
		HexKind.VeinGuard,
		HexKind.AssemblerSpeed,
		HexKind.RecipeFree,
		HexKind.BeltSpeed,
		HexKind.PowerCut,
		HexKind.WindBoost,
		HexKind.DropBoost,
		HexKind.StationMine,
		HexKind.GenBoost,
		HexKind.AllStatsPct
	};

	internal static HexDef Get(string id)
	{
		HexDef value;
		return (id != null && map.TryGetValue(id, out value)) ? value : null;
	}

	private static HexDef Add(string id, string name, string desc, Rarity r, bool once, params object[] mods)
	{
		HexDef hexDef = new HexDef
		{
			Id = id,
			Name = name,
			Desc = desc,
			R = r,
			Once = once
		};
		for (int i = 0; i + 1 < mods.Length; i += 2)
		{
			hexDef.Mods.Add(new KeyValuePair<HexKind, double>((HexKind)mods[i], Convert.ToDouble(mods[i + 1])));
		}
		All.Add(hexDef);
		map[id] = hexDef;
		return hexDef;
	}

	internal static void Verify()
	{
		foreach (HexDef item in All)
		{
			List<string> list = new List<string>();
			bool flag = true;
			foreach (KeyValuePair<HexKind, double> mod in item.Mods)
			{
				bool flag2 = Wired.Contains(mod.Key);
				if (!flag2)
				{
					flag = false;
				}
				list.Add(mod.Key.ToString() + (flag2 ? "" : "(!)"));
			}
			if (!flag)
			{
				Plugin.Log.LogWarning((object)("hex NOT wired: " + item.Name + " [" + item.Id + "] " + string.Join(", ", list.ToArray())));
			}
		}
		Plugin.Log.LogInfo((object)("verify done, hexes=" + All.Count));
	}

	internal static void Build()
	{
		if (All.Count <= 0)
		{
			Add("weapon_all", "大力", "所有武器伤害系数(动能/能量/爆破/电磁)+20%", Rarity.Silver, false, HexKind.WeaponDmgPct, 0.2);
			Add("kinetic_to_blast", "物理转魔法", "将动能伤害系数 100% 转化为爆破伤害系数", Rarity.Silver, false, HexKind.KineticToBlast, 1.0);
			Add("blast_to_energy", "魔法转物理", "将爆破伤害系数 100% 转化为能量伤害系数", Rarity.Silver, false, HexKind.BlastToEnergy, 1.0);
			Add("hp_big", "星界体躯", "机甲耐久度 +100000,耐久上限 +10%,所有武器伤害系数 -10%", Rarity.Gold, false, HexKind.HpFlat, 100000, HexKind.HpPct, 0.1, HexKind.WeaponDmgPct, -0.1);
			Add("shield_from_hp", "由心及物", "获得相当于耐久度 200% 的能量盾上限", Rarity.Silver, false, HexKind.ShieldFromHp, 2.0);
			Add("move_all", "练腿日", "步行/低空飞行/太空航行/曲速飞行 速度 +100%", Rarity.Silver, false, HexKind.WalkPct, 1.0, HexKind.JumpPct, 1.0, HexKind.SailPct, 1.0, HexKind.WarpPct, 1.0);
			Add("regen_ocean", "海洋龙魂", "机甲耐久每秒回复 1%,能量盾每秒回复 0.1%", Rarity.Silver, false, HexKind.RegenHpPct, 0.01, HexKind.RegenShieldPct, 0.001);
			Add("stack_boost", "叠角龙", "所有叠层类海克斯的叠层效果 +100%", Rarity.Silver, false, HexKind.StackBoost, 1.0);
			Add("drone_all", "残暴之力", "地面无人机/太空战舰:伤害 +20%、攻速 +60%、耐久 +100%", Rarity.Silver, false, HexKind.DroneDmgPct, 0.2, HexKind.DroneRofPct, 0.6, HexKind.DroneDurPct, 1.0);
			Add("range", "更万用的瞄准镜", "机甲所有武器(子弹/炮弹/导弹/等离子)射程 +60%", Rarity.Gold, false, HexKind.RangePct, 0.6);
			Add("penetrate", "穿针引线", "忽略黑雾 25% 护甲(近似:全武器伤害系数 +25%)", Rarity.Gold, false, HexKind.PenetrationPct, 0.25);
			Add("kill_hp", "任务:钢化你心", "每击杀 1 个黑雾,机甲耐久度上限 +5(可无限叠)", Rarity.Gold, false, HexKind.KillHp, 5);
			Add("star_lum", "飞升仪式", "所有恒星功效系数 +100%", Rarity.Prism, false, HexKind.StarLumPct, 1.0);
			Add("fractionator", "易损", "分馏塔产出概率 ×50(上限 100%)", Rarity.Gold, false, HexKind.Fractionator, 1.0);
			Add("warper_refund", "狙神飞星", "星际运输船消耗翘曲器后自动返还", Rarity.Gold, false, HexKind.WarperRefund, 1.0);
			Add("ammo_all", "多重射击", "激光与炸弹武器始终激活;弹药攻击速度翻倍", Rarity.Prism, false, HexKind.AmmoAll, 1.0, HexKind.AmmoRofPct, 1.0);
			Add("crit_def", "会心防御", "获得 25% 暴击率;受到伤害时按暴击率独立抛骰,命中则伤害 -50%", Rarity.Silver, false, HexKind.CritHex, 0.25);
			Add("crit_prod", "珠光护手", "获得 25% 暴击率;制造设备产出可暴击(产出 ×2)", Rarity.Prism, false, HexKind.CritHex, 0.25, HexKind.CritProd, 1.0);
			Add("crit_dmg", "升级:无尽之刃", "获得 25% 暴击率;你造成的伤害可暴击,暴击伤害 ×2", Rarity.Gold, false, HexKind.CritHex, 0.25, HexKind.CritDmg, 1.0);
			Add("crit_double", "大腕", "获得 25% 暴击率;所有暴击类海克斯的效果翻倍", Rarity.Prism, false, HexKind.CritHex, 0.25, HexKind.CritDouble, 1.0);
			Add("spray_light", "虚幻武器", "制造台产出时 25% 概率额外产出 +1", Rarity.Gold, false, HexKind.SprayLight, 0.25);
			Add("spray_heavy", "秘术冲拳", "制造台产出时 75% 概率额外产出 +1;制造设备 +100%、传送带 ×2", Rarity.Prism, false, HexKind.SprayHeavy, 0.75);
			Add("kill_buff", "杀戮时间到了", "右键(F8)激活:2 分钟内造成的所有伤害翻倍,冷却 10 分钟", Rarity.Gold, false, HexKind.KillBuff, 1.0);
			Add("ejector", "神射法师", "太阳帆弹射器 / 火箭发射井 发射速度 +400%", Rarity.Gold, false, HexKind.EjectorSpeed, 1.0);
			Add("turret", "家园卫士", "防御塔 射程 +100%、射击速度 +100%", Rarity.Silver, false, HexKind.TurretBoost, 1.0);
			Add("vein", "注魔", "矿物不枯竕,所有采矿设备效率 +100%", Rarity.Silver, false, HexKind.VeinGuard, 1.0);
			Add("overload", "超负荷", "制造设备与采矿设备 生产效率 +100%", Rarity.Prism, false, HexKind.AssemblerSpeed, 1.0);
			Add("recipe_free", "尤里卡", "制造配方需要 3 种以上原料时,免除第 3 种原料的消耗", Rarity.Prism, false, HexKind.RecipeFree, 1.0);
			Add("power_cut", "灵巧", "粒子对撞机与垂直发射井的工作耗电 -90%", Rarity.Silver, false, HexKind.PowerCut, 1.0);
			Add("wind", "神圣干预", "所有行星的风能 / 光能利用率 +1000%", Rarity.Gold, false, HexKind.WindBoost, 1.0);
			Add("drop", "夺金", "黑雾掉落 +3000%,但黑雾建筑耐久 +50%", Rarity.Prism, false, HexKind.DropBoost, 1.0);
			Add("station_mine", "坦克引擎", "运输站能够挖取本星球的矿物", Rarity.Gold, false, HexKind.StationMine, 1.0);
			Add("zealot", "狂热者", "火力发电厂的发电功率 +300%", Rarity.Silver, false, HexKind.GenBoost, 1.0);
			Add("grant_matrix", "捐赠", "立刻获得六种矩阵各 1,000,000 个", Rarity.Gold, true, HexKind.GrantMatrices, 1000000);
			Add("fleet_baron", "男爵之手", "地面/太空编队数量 +4;无人机/战舰伤害 +25%", Rarity.Prism, false, HexKind.FleetAdd, 4, HexKind.DroneDmgPct, 0.25);
			Add("kill_quest", "任务:海牛阿福的勇士", "累计击杀 10000 个黑雾后:全属性 +25%", Rarity.Prism, false, HexKind.KillQuest, 10000, HexKind.AllStatsPct, 0.25);
			Add("laser_only", "回归基本功", "无法使用地面编队;激光武器伤害+1000%、射程+500%、射速+1000%", Rarity.Prism, false, HexKind.LaserBoost, 1.0);
			Add("double_shot", "双刀流", "武器开火口 +1(每次射击多一发),射速 -10%", Rarity.Prism, false, HexKind.MuzzleAdd, 1);
			Add("pandora", "潘朵拉的盒子", "将你已拥有的所有海克斯重铸为随机棱彩", Rarity.Prism, true, HexKind.RerollAllPrism, 1);
		}
	}

	internal static List<HexDef> Pool(Rarity r)
	{
		List<HexDef> list = new List<HexDef>();
		foreach (HexDef item in All)
		{
			if (item.R == r)
			{
				list.Add(item);
			}
		}
		return list;
	}

	internal static List<HexDef> Roll(Rarity r, Random rng)
	{
		return Pool(r);
	}
}
internal static class HexState
{
	[Serializable]
	private class Blob
	{
		public int awardedSteps;

		public int pending;

		public List<string> owned = new List<string>();

		public string[] options;

		public int refreshCount;

		public bool deleteUsed;

		public bool needRoll = true;

		public bool inited;

		public long killProgress;

		public List<string> onceDone = new List<string>();

		public List<string> baseKeys = new List<string>();

		public List<double> baseVals = new List<double>();

		public bool questDone;

		public List<string> appliedKeys = new List<string>();

		public List<double> appliedVals = new List<double>();
	}

	internal static int AwardedSteps;

	internal static int Pending;

	internal static readonly List<string> Owned = new List<string>();

	internal static string[] Options = new string[3];

	internal static int RefreshCount;

	internal static bool Drawing;

	internal static bool DeleteUsed;

	internal static bool NeedRoll = true;

	internal static bool Inited;

	internal static long KillProgress;

	internal static readonly List<string> OnceDone = new List<string>();

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

	internal static bool QuestDone;

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

	internal static string LoadedKey = "";

	private static string SavePath
	{
		get
		{
			string text = LoadedKey;
			if (string.IsNullOrEmpty(text))
			{
				text = CurrentKey();
			}
			if (string.IsNullOrEmpty(text))
			{
				text = "default";
			}
			return Path.Combine(Paths.ConfigPath, "VoidHex", text + ".json");
		}
	}

	internal static string CurrentKey()
	{
		try
		{
			return GameMain.data.gameName + "_" + GameMain.data.gameDesc.galaxySeed;
		}
		catch (Exception)
		{
			return null;
		}
	}

	internal static void Load()
	{
		try
		{
			if (string.IsNullOrEmpty(CurrentKey()))
			{
				return;
			}
			string savePath = SavePath;
			if (!File.Exists(savePath))
			{
				Pending = 1;
				AwardedSteps = 0;
				Inited = false;
				Bases.Clear();
				Applied.Clear();
				Save();
				Plugin.Log.LogInfo((object)"new save: free draw granted (pending=1)");
				return;
			}
			Blob blob = JsonUtility.FromJson<Blob>(File.ReadAllText(savePath));
			if (blob == null)
			{
				return;
			}
			AwardedSteps = blob.awardedSteps;
			Pending = blob.pending;
			Owned.Clear();
			if (blob.owned != null)
			{
				Owned.AddRange(blob.owned);
			}
			Options = blob.options ?? new string[3];
			RefreshCount = blob.refreshCount;
			DeleteUsed = blob.deleteUsed;
			NeedRoll = blob.needRoll;
			if (Options == null || Options.Length < 3 || string.IsNullOrEmpty(Options[0]))
			{
				NeedRoll = true;
			}
			for (int num = Owned.Count - 1; num >= 0; num--)
			{
				if (Owned.IndexOf(Owned[num]) != num)
				{
					Owned.RemoveAt(num);
				}
			}
			Inited = blob.inited;
			KillProgress = blob.killProgress;
			OnceDone.Clear();
			if (blob.onceDone != null)
			{
				OnceDone.AddRange(blob.onceDone);
			}
			Bases.Clear();
			if (blob.baseKeys != null && blob.baseVals != null)
			{
				for (int i = 0; i < blob.baseKeys.Count && i < blob.baseVals.Count; i++)
				{
					Bases[blob.baseKeys[i]] = blob.baseVals[i];
				}
			}
			QuestDone = blob.questDone;
			Applied.Clear();
			if (blob.appliedKeys != null && blob.appliedVals != null)
			{
				for (int j = 0; j < blob.appliedKeys.Count && j < blob.appliedVals.Count; j++)
				{
					Applied[blob.appliedKeys[j]] = blob.appliedVals[j];
				}
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("state load: " + ex.Message));
		}
	}

	internal static void Save()
	{
		try
		{
			string savePath = SavePath;
			Directory.CreateDirectory(Path.GetDirectoryName(savePath));
			Blob blob = new Blob
			{
				awardedSteps = AwardedSteps,
				pending = Pending,
				refreshCount = RefreshCount,
				deleteUsed = DeleteUsed,
				needRoll = NeedRoll,
				inited = Inited,
				killProgress = KillProgress,
				onceDone = new List<string>(OnceDone),
				questDone = QuestDone,
				options = Options
			};
			blob.owned.AddRange(Owned);
			foreach (KeyValuePair<string, double> basis in Bases)
			{
				blob.baseKeys.Add(basis.Key);
				blob.baseVals.Add(basis.Value);
			}
			foreach (KeyValuePair<string, double> item in Applied)
			{
				blob.appliedKeys.Add(item.Key);
				blob.appliedVals.Add(item.Value);
			}
			File.WriteAllText(savePath, JsonUtility.ToJson((object)blob, true));
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("state save: " + ex.Message));
		}
	}
}
internal static class Watch
{
	private static int techId = -1;

	private static int lastLogged = -1;

	private static int TechId()
	{
		if (techId > 0)
		{
			return techId;
		}
		TechProto[] array = (((Object)(object)LDB.techs != (Object)null) ? ((ProtoSet<TechProto>)(object)LDB.techs).dataArray : null);
		if (array == null)
		{
			return -1;
		}
		TechProto val = null;
		TechProto[] array2 = array;
		foreach (TechProto val2 in array2)
		{
			if (val2 != null && !(((Proto)val2).name != "机甲核心") && (val == null || val2.Level > val.Level))
			{
				val = val2;
			}
		}
		if (val == null)
		{
			TechProto[] array3 = array;
			foreach (TechProto val3 in array3)
			{
				if (val3 != null && ((Proto)val3).name != null && ((Proto)val3).name.Contains("机甲") && ((Proto)val3).name.Contains("核心"))
				{
					val = val3;
					break;
				}
			}
		}
		if (val == null)
		{
			List<string> list = new List<string>();
			TechProto[] array4 = array;
			foreach (TechProto val4 in array4)
			{
				if (val4 != null && ((Proto)val4).name != null && (((Proto)val4).name.Contains("核心") || ((Proto)val4).name.Contains("机甲")))
				{
					list.Add(((Proto)val4).name + "#" + ((Proto)val4).ID + " Lv" + val4.Level + "/max" + val4.MaxLevel);
				}
			}
			Plugin.Log.LogWarning((object)("机甲核心 NOT FOUND. candidates: " + string.Join(", ", list.ToArray())));
			return -1;
		}
		techId = ((Proto)val).ID;
		Plugin.Log.LogInfo((object)("mecha core tech id=" + techId + " name=" + ((Proto)val).name + " Level=" + val.Level + " MaxLevel=" + val.MaxLevel));
		return techId;
	}

	internal static void Award()
	{
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (GameMain.history == null || GameMain.history.techStates == null)
			{
				return;
			}
			int num = TechId();
			if (num <= 0 || !GameMain.history.techStates.TryGetValue(num, out var value))
			{
				return;
			}
			int curLevel = value.curLevel;
			int num2 = 0;
			try
			{
				if (GameMain.mainPlayer != null && GameMain.mainPlayer.mecha != null)
				{
					num2 = GameMain.mainPlayer.mecha.coreLevel;
				}
			}
			catch (Exception)
			{
			}
			int num3 = ((num2 > 0) ? num2 : curLevel);
			int num4 = Math.Max(0, (num3 - 1) / 10);
			if (num3 != lastLogged)
			{
				lastLogged = num3;
				Plugin.Log.LogInfo((object)("mecha core level " + num3 + " (tech " + curLevel + ", coreLevel " + num2 + ", max " + value.maxLevel + ", unlocked=" + value.unlocked + ", steps=" + num4 + ", awarded=" + HexState.AwardedSteps + ")"));
			}
			if (!HexState.Inited)
			{
				HexState.Inited = true;
				HexState.AwardedSteps = num4;
				HexState.Save();
				Plugin.Log.LogInfo((object)("baseline set at level " + num3 + " (steps=" + num4 + ")"));
			}
			else if (num4 > HexState.AwardedSteps)
			{
				int num5 = num4 - HexState.AwardedSteps;
				HexState.AwardedSteps = num4;
				HexState.Pending += num5;
				HexState.NeedRoll = true;
				HexState.Save();
				Plugin.Log.LogInfo((object)("mecha core reached step " + num4 + " (level " + num3 + ") -> +" + num5 + " draw(s), pending=" + HexState.Pending));
			}
		}
		catch (Exception ex2)
		{
			Plugin.Log.LogWarning((object)("watch: " + ex2.Message));
		}
	}
}
internal static class Effects
{
	private sealed class SeenProd
	{
		public int recipe;

		public int[] v;
	}

	private static readonly Dictionary<HexKind, double> applied = new Dictionary<HexKind, double>();

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

	private static int sig = -1;

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

	private static long lastKills = -1L;

	private static readonly Dictionary<long, int> lastWarper = new Dictionary<long, int>();

	private static bool starCompatLogged;

	internal static bool AmmoAllOn;

	internal static bool RecipeFreeOn;

	internal static bool CritProdOn;

	private static bool cCritDef;

	private static double cSpray;

	private static double cCrit;

	private static bool cCacheOk;

	private static readonly Random rng2 = new Random();

	private static ConditionalWeakTable<int[], SeenProd> seenProduced = new ConditionalWeakTable<int[], SeenProd>();

	private static bool asmWasOn;

	private static bool beltWasOn;

	private static bool fracWasOn;

	private static bool ejWasOn;

	private static bool buffOn;

	private static bool dmgSeed;

	private static bool dmgInvert;

	private static bool turretDone;

	private static bool powerCutDone;

	private static bool windLogged;

	private static bool dropLogged;

	private static bool turretLogged;

	private static bool genLogged;

	private static readonly Dictionary<int, long> baseGen = new Dictionary<int, long>();

	private static int globalPassCounter;

	private static readonly Dictionary<int, float> baseRange = new Dictionary<int, float>();

	private static readonly Dictionary<int, float> baseSpaceRange = new Dictionary<int, float>();

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

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

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

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

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

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

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

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

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

	private static readonly Dictionary<int, long> baseWork = new Dictionary<int, long>();

	private static readonly Dictionary<int, long> baseIdle = new Dictionary<int, long>();

	private static int counter2;

	private static int speedCounter;

	private static bool pcWasOn;

	private static bool genWasOn;

	private static bool windWasOn;

	private static bool dropWasOn;

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

	private static readonly Dictionary<long, long[]> pcWrote = new Dictionary<long, long[]>();

	private static bool pcIdsReady;

	private const int CapSlots = 48;

	private static bool laserApplied;

	private static bool ammoWasOn;

	private static double buffEnd;

	private static double nextBuffAllowed;

	private static double lastRegen = -1.0;

	private static int appliedFleet;

	private static bool convKinetic;

	private static bool convBlast;

	private static bool dirtyPass = true;

	internal static double Sum(HexKind k)
	{
		double num = 0.0;
		foreach (string item in HexState.Owned)
		{
			HexDef hexDef = Catalog.Get(item);
			if (hexDef == null)
			{
				continue;
			}
			foreach (KeyValuePair<HexKind, double> mod in hexDef.Mods)
			{
				if (mod.Key == k)
				{
					num += mod.Value;
				}
			}
		}
		return num;
	}

	internal static bool Has(HexKind k)
	{
		return Sum(k) != 0.0;
	}

	internal static void OnAcquire(string id)
	{
		HexDef hexDef = Catalog.Get(id);
		if (hexDef == null || !hexDef.Once || HexState.OnceDone.Contains(id))
		{
			return;
		}
		HexState.OnceDone.Add(id);
		HexState.Save();
		try
		{
			if (hexDef.Id == "grant_matrix")
			{
				GrantMatrices((int)Sum(HexKind.GrantMatrices));
			}
			else if (hexDef.Id == "pandora")
			{
				RerollPrism();
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("acquire " + id + ": " + ex.Message));
		}
	}

	private static void GrantMatrices(int each)
	{
		List<int> list = new List<int>();
		ItemProto[] dataArray = ((ProtoSet<ItemProto>)(object)LDB.items).dataArray;
		foreach (ItemProto val in dataArray)
		{
			if (val != null && ((Proto)val).name != null && ((Proto)val).name.Contains("矩阵"))
			{
				list.Add(((Proto)val).ID);
			}
		}
		int num = 0;
		int num5 = default(int);
		foreach (int item in list)
		{
			if (item <= 0)
			{
				continue;
			}
			try
			{
				if (!GameMain.history.ItemUnlocked(item))
				{
					continue;
				}
				int num2 = each;
				int num3 = 0;
				while (num2 > 0 && num3++ < 200)
				{
					int num4 = GameMain.mainPlayer.package.AddItem(item, num2, 0, ref num5, false);
					if (num4 <= 0)
					{
						break;
					}
					num2 -= num4;
					if (num5 <= 0)
					{
						break;
					}
				}
				num++;
				Plugin.Log.LogInfo((object)("granted " + item + ", left=" + num2));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("grant " + item + ": " + ex.Message));
			}
		}
		Plugin.Log.LogInfo((object)("granted " + each + " x" + num + " matrices"));
	}

	private static int ItemId(string name)
	{
		try
		{
			ItemProto[] dataArray = ((ProtoSet<ItemProto>)(object)LDB.items).dataArray;
			ItemProto[] array = dataArray;
			foreach (ItemProto val in array)
			{
				if (val != null && ((Proto)val).name == name)
				{
					return ((Proto)val).ID;
				}
			}
		}
		catch (Exception)
		{
		}
		return 0;
	}

	private static void RerollPrism()
	{
		Random random = new Random();
		List<HexDef> list = new List<HexDef>(Catalog.Pool(Rarity.Prism));
		if (list.Count == 0)
		{
			return;
		}
		for (int num = list.Count - 1; num > 0; num--)
		{
			int index = random.Next(num + 1);
			HexDef value = list[num];
			list[num] = list[index];
			list[index] = value;
		}
		List<string> list2 = new List<string>();
		foreach (string item in HexState.Owned)
		{
			if (!list2.Contains(item))
			{
				list2.Add(item);
			}
		}
		int count = list2.Count;
		if (count > list.Count)
		{
			Plugin.Log.LogWarning((object)("pandora: " + count + " slots but only " + list.Count + " prismatic hexes, duplicates allowed"));
		}
		List<string> list3 = new List<string>();
		for (int i = 0; i < count; i++)
		{
			list3.Add(list[i % list.Count].Id);
		}
		HexState.Owned.Clear();
		HexState.Owned.AddRange(list3);
		Invalidate();
		foreach (string item2 in HexState.Owned)
		{
			OnAcquire(item2);
		}
		HexState.Save();
		Plugin.Log.LogInfo((object)("pandora: rerolled " + count + " hexes to prismatic, distinct=" + ((list.Count >= count) ? count : list.Count)));
	}

	private static void ApplyDamageScales()
	{
		if (GameMain.history == null)
		{
			return;
		}
		GameHistoryData history = GameMain.history;
		double num = (1.0 + Sum(HexKind.WeaponDmgPct)) * (1.0 + Sum(HexKind.PenetrationPct));
		if (Sum(HexKind.CritDmg) > 0.0)
		{
			num *= 1.0 + CritChanceRaw();
		}
		if (HexState.QuestDone && Sum(HexKind.KillQuest) > 0.0)
		{
			num *= 1.25;
		}
		if (buffOn)
		{
			num *= 2.0;
		}
		if (dmgSeed)
		{
			BSet("dmgK_w", history.kineticDamageScale);
			BSet("dmgE_w", history.energyDamageScale);
			BSet("dmgB_w", history.blastDamageScale);
			BSet("dmgM_w", history.magneticDamageScale);
			dmgSeed = false;
			HexState.Save();
		}
		if (dmgInvert)
		{
			dmgInvert = false;
			if (num > 0.0)
			{
				BSet("dmgK", (double)history.kineticDamageScale / num);
				BSet("dmgE", (double)history.energyDamageScale / num);
				BSet("dmgB", (double)history.blastDamageScale / num);
				BSet("dmgM", (double)history.magneticDamageScale / num);
				BSet("dmgK_w", history.kineticDamageScale);
				BSet("dmgE_w", history.energyDamageScale);
				BSet("dmgB_w", history.blastDamageScale);
				BSet("dmgM_w", history.magneticDamageScale);
				Plugin.Log.LogInfo((object)("damage baseline recovered from 0.9.19 wipe (divided by " + num.ToString("0.###") + ")"));
			}
		}
		double num2 = DmgBase("dmgK", history.kineticDamageScale);
		double num3 = DmgBase("dmgE", history.energyDamageScale);
		double num4 = DmgBase("dmgB", history.blastDamageScale);
		double num5 = DmgBase("dmgM", history.magneticDamageScale);
		if (Sum(HexKind.KineticToBlast) > 0.0)
		{
			num4 += num2;
			num2 = 0.0;
		}
		if (Sum(HexKind.BlastToEnergy) > 0.0)
		{
			num3 += num4;
			num4 = 0.0;
		}
		num2 *= num;
		num3 *= num;
		num4 *= num;
		num5 *= num;
		history.kineticDamageScale = (float)num2;
		history.energyDamageScale = (float)num3;
		history.blastDamageScale = (float)num4;
		history.magneticDamageScale = (float)num5;
		BSet("dmgK_w", num2);
		BSet("dmgE_w", num3);
		BSet("dmgB_w", num4);
		BSet("dmgM_w", num5);
	}

	private static void ApplyMechaField(Mecha m, string name, double v, bool add)
	{
		try
		{
			FieldInfo field = typeof(Mecha).GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field == null)
			{
				if (loggedMissing.Add(name))
				{
					Plugin.Log.LogWarning((object)("mecha field not found: " + name));
				}
			}
			else if (field.FieldType == typeof(int))
			{
				field.SetValue(m, (int)((double)(int)field.GetValue(m) + (add ? v : ((double)(int)field.GetValue(m) * (v - 1.0)))));
			}
			else if (field.FieldType == typeof(float))
			{
				field.SetValue(m, (float)((double)(float)field.GetValue(m) * (add ? 1.0 : v)));
			}
		}
		catch (Exception)
		{
		}
	}

	private static void ApplyMechaRange(Mecha m, double factor)
	{
		string[] array = new string[8] { "bulletLocalAttackRange", "bulletSpaceAttackRange", "cannonLocalAttackRange", "cannonSpaceAttackRange", "missileLocalAttackRange", "missileSpaceAttackRange", "plasmaLocalAttackRange", "plasmaSpaceAttackRange" };
		string[] array2 = array;
		foreach (string name in array2)
		{
			ApplyMechaField(m, name, factor, add: false);
		}
	}

	private static double DmgBase(string key, double cur)
	{
		double num = BaseOf(key, cur);
		double num2 = BGet(key + "_w", num);
		double num3 = cur - num2;
		if (Math.Abs(num3) > 0.0001)
		{
			num += num3;
			BSet(key, num);
		}
		return num;
	}

	private static double BaseOf(string key, double cur)
	{
		if (HexState.Bases.TryGetValue(key, out var value))
		{
			return value;
		}
		HexState.Bases[key] = cur;
		HexState.Save();
		return cur;
	}

	private static void SetApplied(HexKind k, double v)
	{
		applied[k] = v;
		HexState.Applied[k.ToString()] = v;
		HexState.Save();
	}

	internal static void RestoreApplied()
	{
		applied.Clear();
		foreach (KeyValuePair<string, double> item in HexState.Applied)
		{
			if (Enum.TryParse<HexKind>(item.Key, out var result))
			{
				applied[result] = item.Value;
			}
		}
		Migrate();
		dmgInvert = !HexState.Bases.ContainsKey("dmgK") && HexState.Owned.Count > 0;
		if (dmgInvert)
		{
			Plugin.Log.LogInfo((object)"damage baseline missing (0.9.19 wipe), will recover on first apply");
		}
		cCacheOk = false;
		RefreshCache();
	}

	private static void Migrate()
	{
		if (HexState.Bases.TryGetValue("schema", out var value) && value >= 2.0)
		{
			return;
		}
		if (HexState.Bases.TryGetValue("hpBase", out var value2) && value2 > 0.0)
		{
			HexState.Bases["hpLegacyBase"] = value2;
		}
		try
		{
			if (GameMain.history != null)
			{
				if (HexState.Applied.TryGetValue("VeinGuard", out var value3) && value3 > 0.0 && Math.Abs(value3 - 1.0) > 1E-06)
				{
					double num = value3;
					if (HexState.Applied.TryGetValue("AssemblerSpeed", out value3) && value3 > 0.0 && Math.Abs(value3 - 1.0) > 1E-06)
					{
						num *= value3;
					}
					if (num > 1.0 && (double)GameMain.history.miningSpeedScale > num)
					{
						GameHistoryData history = GameMain.history;
						history.miningSpeedScale /= (float)num;
						Plugin.Log.LogInfo((object)("legacy mining speed normalized: /" + num));
					}
				}
				if (HexState.Applied.TryGetValue("DropBoost", out value3) && value3 > 1.0 && GameMain.history.enemyDropScale > (float)value3)
				{
					GameHistoryData history2 = GameMain.history;
					history2.enemyDropScale /= (float)value3;
					Plugin.Log.LogInfo((object)("legacy enemy drop normalized: /" + value3));
				}
			}
		}
		catch (Exception)
		{
		}
		if (HexState.Owned.Contains("laser_only"))
		{
			HexState.Bases["laserDone"] = 1.0;
		}
		if (HexState.Owned.Contains("fleet_baron"))
		{
			HexState.Bases["fleetDone"] = Sum(HexKind.FleetAdd);
		}
		dmgSeed = true;
		dmgInvert = !HexState.Bases.ContainsKey("dmgK") && HexState.Owned.Count > 0;
		if (HexState.Bases.ContainsKey("laserDone") && !HexState.Bases.ContainsKey("laserOn"))
		{
			BSet("laserLegacyFix", 1.0);
		}
		List<string> list = new List<string>();
		foreach (string key in HexState.Bases.Keys)
		{
			switch (key)
			{
			case "fleetDone":
			case "laserDone":
			case "schema":
				continue;
			}
			if (key == "hpLegacyBase")
			{
				continue;
			}
			switch (key)
			{
			case "dmgK":
			case "dmgE":
			case "dmgB":
				continue;
			}
			if (key == "dmgM")
			{
				continue;
			}
			switch (key)
			{
			case "dmgK_w":
			case "dmgE_w":
			case "dmgB_w":
				continue;
			}
			if (!(key == "dmgM_w") && !(key == "laserLegacyFix") && !(key == "questCore"))
			{
				list.Add(key);
			}
		}
		foreach (string item in list)
		{
			HexState.Bases.Remove(item);
		}
		HexState.Bases["schema"] = 2.0;
		HexState.Save();
		Plugin.Log.LogInfo((object)("state migrated to layer schema 2 (dropped " + list.Count + " legacy baselines)"));
	}

	internal static void Invalidate()
	{
		sig = -1;
		laserApplied = false;
		lastRegen = -1.0;
		dirtyPass = true;
	}

	internal static void InvalidateHard()
	{
		pcWrote.Clear();
		seenProduced = new ConditionalWeakTable<int[], SeenProd>();
		sig = -1;
		laserApplied = false;
		lastRegen = -1.0;
		lastKills = -1L;
		lastWarper.Clear();
		buffOn = false;
		buffEnd = 0.0;
		nextBuffAllowed = 0.0;
		ammoWasOn = false;
		convKinetic = false;
		convBlast = false;
		dirtyPass = true;
	}

	internal static void CheckHotkey()
	{
		try
		{
			if (GameMain.data == null || GameMain.mainPlayer == null || Sum(HexKind.KillBuff) <= 0.0)
			{
				return;
			}
			double gameTime = GameMain.gameTime;
			if (Input.GetKeyDown((KeyCode)289))
			{
				if (gameTime < nextBuffAllowed)
				{
					Plugin.Log.LogInfo((object)("kill buff on cooldown: " + (int)(nextBuffAllowed - gameTime) + "s"));
					return;
				}
				buffEnd = gameTime + 120.0;
				nextBuffAllowed = gameTime + 720.0;
				ApplyKillBuff(on: true);
				Plugin.Log.LogInfo((object)"kill buff activated (120s), next at +720s");
			}
			if (buffEnd > 0.0 && gameTime > buffEnd && buffOn)
			{
				ApplyKillBuff(on: false);
				buffEnd = 0.0;
			}
		}
		catch (Exception)
		{
		}
	}

	private static void ApplyKillBuff(bool on)
	{
		if (GameMain.history != null && on != buffOn)
		{
			buffOn = on;
			ApplyDamageScales();
			HexState.Save();
			Plugin.Log.LogInfo((object)("kill buff " + (on ? "on" : "off")));
		}
	}

	internal static void Tick()
	{
		try
		{
			if (GameMain.mainPlayer == null)
			{
				return;
			}
			Mecha mecha = GameMain.mainPlayer.mecha;
			if (mecha == null)
			{
				return;
			}
			int num = 17;
			foreach (string item in HexState.Owned)
			{
				num = num * 31 + item.GetHashCode();
			}
			if (num != sig)
			{
				sig = num;
				dirtyPass = true;
				ApplyAll(mecha);
			}
			KillTick(mecha);
			WarperTick();
			MiscTick();
			double num2 = ((lastRegen < 0.0) ? 0.0 : Math.Min(2.0, (double)Time.time - lastRegen));
			lastRegen = Time.time;
			double num3 = Sum(HexKind.RegenHpPct);
			double num4 = Sum(HexKind.RegenShieldPct);
			if (num3 > 0.0 && mecha.hp < mecha.hpMax)
			{
				mecha.hp = Math.Min(mecha.hpMax, mecha.hp + (int)Math.Ceiling((double)mecha.hpMax * num3 * num2));
			}
			if (num4 > 0.0 && mecha.energyShieldCapacity > 0 && mecha.energyShieldEnergy < mecha.energyShieldCapacity)
			{
				mecha.energyShieldEnergy = Math.Min(mecha.energyShieldCapacity, mecha.energyShieldEnergy + (long)Math.Ceiling((double)mecha.energyShieldCapacity * num4 * num2));
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("effects: " + ex.Message));
		}
	}

	internal static long TotalKills()
	{
		try
		{
			if (GameMain.data == null || GameMain.data.statistics == null)
			{
				return 0L;
			}
			KillStatistics kill = GameMain.data.statistics.kill;
			if (kill == null)
			{
				return 0L;
			}
			long num = 0L;
			if (kill.starKillStatPool != null)
			{
				AstroKillStat[] starKillStatPool = kill.starKillStatPool;
				foreach (AstroKillStat a in starKillStatPool)
				{
					num += SumAstro(a);
				}
			}
			if (kill.factoryKillStatPool != null)
			{
				AstroKillStat[] factoryKillStatPool = kill.factoryKillStatPool;
				foreach (AstroKillStat a2 in factoryKillStatPool)
				{
					num += SumAstro(a2);
				}
			}
			return num + SumAstro(kill.mechaKillStat);
		}
		catch (Exception)
		{
			return 0L;
		}
	}

	private static long SumAstro(AstroKillStat a)
	{
		if (a == null || a.killStatPool == null)
		{
			return 0L;
		}
		long num = 0L;
		KillStat[] killStatPool = a.killStatPool;
		foreach (KillStat val in killStatPool)
		{
			if (val != null && val.total != null)
			{
				int[] total = val.total;
				foreach (int num2 in total)
				{
					num += num2;
				}
			}
		}
		return num;
	}

	internal static void KillTick(Mecha m)
	{
		long num = TotalKills();
		if (lastKills < 0)
		{
			lastKills = num;
			return;
		}
		long num2 = num - lastKills;
		if (num2 < 0)
		{
			lastKills = num;
		}
		else
		{
			if (num2 == 0)
			{
				return;
			}
			lastKills = num;
			if (Sum(HexKind.KillHp) > 0.0)
			{
				double num3 = Sum(HexKind.KillHp) * ((Sum(HexKind.StackBoost) > 0.0) ? 2.0 : 1.0);
				m.hpMax += (int)Math.Round(num3 * (double)num2);
			}
			double num4 = Sum(HexKind.KillQuest);
			if (num4 > 0.0 && !HexState.QuestDone)
			{
				HexState.KillProgress += num2;
				if (HexState.KillProgress >= (long)num4)
				{
					HexState.QuestDone = true;
					HexState.Save();
					sig = -1;
					ApplyAll(m);
					Plugin.Log.LogInfo((object)"quest complete: all stats +25% (applied immediately)");
				}
				HexState.Save();
			}
		}
	}

	private static void ApplyStars()
	{
		try
		{
			double num = Sum(HexKind.StarLumPct);
			StarData[] array = ((GameMain.galaxy != null) ? GameMain.galaxy.stars : null);
			if (array == null)
			{
				return;
			}
			double num2 = 1.0 + num;
			if (num2 < 0.0001)
			{
				num2 = 1.0;
			}
			for (int i = 0; i < array.Length; i++)
			{
				if (array[i] != null)
				{
					array[i].luminosity = (float)ScaleFromBase("star" + i, array[i].luminosity, num2, num2);
				}
			}
			if (Compat.OrbitalRing && !starCompatLogged)
			{
				starCompatLogged = true;
				Plugin.Log.LogInfo((object)"stars: OrbitalRing detected, external luminosity writes are absorbed instead of re-multiplied");
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("stars: " + ex.Message));
		}
	}

	private static void WarperTick()
	{
		if (Sum(HexKind.WarperRefund) <= 0.0 || GameMain.data == null || GameMain.data.galacticTransport == null)
		{
			return;
		}
		StationComponent[] stationPool = GameMain.data.galacticTransport.stationPool;
		if (stationPool == null)
		{
			return;
		}
		foreach (StationComponent val in stationPool)
		{
			if (val == null || val.workShipDatas == null)
			{
				continue;
			}
			for (int j = 0; j < val.workShipDatas.Length; j++)
			{
				long key = (long)val.id * 100000L + j;
				int warperCnt = val.workShipDatas[j].warperCnt;
				if (lastWarper.TryGetValue(key, out var value) && warperCnt < value)
				{
					val.workShipDatas[j].warperCnt = value;
				}
				lastWarper[key] = warperCnt;
			}
		}
	}

	internal static double CritChanceRaw()
	{
		if (cCacheOk)
		{
			return cCrit;
		}
		double num = 0.0;
		foreach (string item in HexState.Owned)
		{
			HexDef hexDef = Catalog.Get(item);
			if (hexDef == null)
			{
				continue;
			}
			foreach (KeyValuePair<HexKind, double> mod in hexDef.Mods)
			{
				if (mod.Key == HexKind.CritHex)
				{
					num += mod.Value;
				}
			}
		}
		if (Sum(HexKind.CritDouble) > 0.0)
		{
			num *= 2.0;
		}
		return cCrit = Math.Min(1.0, num);
	}

	internal static double SprayChance()
	{
		if (cCacheOk)
		{
			return cSpray;
		}
		double val = Sum(HexKind.SprayLight) + Sum(HexKind.SprayHeavy);
		return cSpray = Math.Min(1.0, val);
	}

	internal static void RefreshCache()
	{
		try
		{
			AmmoAllOn = Sum(HexKind.AmmoAll) > 0.0;
			RecipeFreeOn = Sum(HexKind.RecipeFree) > 0.0;
			CritProdOn = Sum(HexKind.CritProd) > 0.0;
			cCritDef = HexState.Owned.Contains("crit_def");
			double num = 0.0;
			foreach (string item in HexState.Owned)
			{
				HexDef hexDef = Catalog.Get(item);
				if (hexDef == null)
				{
					continue;
				}
				foreach (KeyValuePair<HexKind, double> mod in hexDef.Mods)
				{
					if (mod.Key == HexKind.CritHex)
					{
						num += mod.Value;
					}
				}
			}
			if (Sum(HexKind.CritDouble) > 0.0)
			{
				num *= 2.0;
			}
			cCrit = Math.Min(1.0, num);
			cSpray = Math.Min(1.0, Sum(HexKind.SprayLight) + Sum(HexKind.SprayHeavy));
			cCacheOk = true;
		}
		catch (Exception)
		{
		}
	}

	internal static bool CritDefOn()
	{
		if (!cCacheOk)
		{
			RefreshCache();
		}
		return cCritDef;
	}

	internal static void OnProduced(AssemblerComponent a)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_01db: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_021c: Unknown result type (might be due to invalid IL or missing references)
		//IL_025d: Unknown result type (might be due to invalid IL or missing references)
		//IL_020a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0231: Unknown result type (might be due to invalid IL or missing references)
		//IL_0242: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (a.produced == null)
			{
				return;
			}
			if (!cCacheOk)
			{
				RefreshCache();
			}
			if (RecipeFreeOn && a.recipeId > 0 && a.served != null)
			{
				RecipeProto val = ((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(a.recipeId);
				if (val != null && val.Items != null && val.ItemCounts != null)
				{
					int num = 0;
					int num2 = Math.Min(val.Items.Length, val.ItemCounts.Length);
					for (int i = 0; i < num2 && i < a.served.Length; i++)
					{
						if (val.Items[i] <= 0 || val.ItemCounts[i] <= 0)
						{
							continue;
						}
						num++;
						if (num >= 3)
						{
							int num3 = val.ItemCounts[i] * 3;
							if (a.served[i] < num3)
							{
								a.served[i] = num3;
							}
						}
					}
				}
			}
			double num4 = (CritProdOn ? cCrit : 0.0) + cSpray;
			if (num4 > 1.0)
			{
				num4 = 1.0;
			}
			if (num4 <= 0.0)
			{
				return;
			}
			if (!seenProduced.TryGetValue(a.produced, out var value) || value.v == null || value.v.Length != a.produced.Length || value.recipe != a.recipeId)
			{
				SeenProd seenProd = new SeenProd();
				seenProd.recipe = a.recipeId;
				seenProd.v = new int[a.produced.Length];
				value = seenProd;
				for (int j = 0; j < a.produced.Length; j++)
				{
					value.v[j] = a.produced[j];
				}
				seenProduced.Remove(a.produced);
				seenProduced.Add(a.produced, value);
				return;
			}
			for (int k = 0; k < a.produced.Length; k++)
			{
				int num5 = a.produced[k];
				if (num5 > value.v[k])
				{
					int num6 = value.v[k];
					for (int l = num6; l < num5; l++)
					{
						if (rng2.NextDouble() < num4)
						{
							a.produced[k]++;
						}
					}
					value.v[k] = a.produced[k];
				}
				else
				{
					value.v[k] = num5;
				}
			}
		}
		catch (Exception)
		{
		}
	}

	internal static int OnMechaDamage(Mecha m, int dmg)
	{
		try
		{
			if (dmg <= 0)
			{
				return dmg;
			}
			if (!CritDefOn())
			{
				return dmg;
			}
			if (rng2.NextDouble() < CritChanceRaw())
			{
				return Math.Max(1, dmg / 2);
			}
		}
		catch (Exception)
		{
		}
		return dmg;
	}

	private static bool IsPowerCutTarget(int itemId)
	{
		if (!pcIdsReady)
		{
			BuildPowerCutIds();
		}
		return pcIds.Contains(itemId);
	}

	private static void BuildPowerCutIds()
	{
		pcIdsReady = true;
		try
		{
			ItemProto[] dataArray = ((ProtoSet<ItemProto>)(object)LDB.items).dataArray;
			foreach (ItemProto val in dataArray)
			{
				if (val != null && ((Proto)val).name != null)
				{
					string name = ((Proto)val).name;
					bool flag = name.IndexOf("对撞", StringComparison.Ordinal) >= 0 || name.IndexOf("发射井", StringComparison.Ordinal) >= 0 || name.IndexOf("发射台", StringComparison.Ordinal) >= 0;
					if (!flag)
					{
						flag = name.IndexOf("Collider", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Launch", StringComparison.OrdinalIgnoreCase) >= 0;
					}
					if (flag)
					{
						pcIds.Add(((Proto)val).ID);
					}
				}
			}
			Plugin.Log.LogInfo((object)("power cut targets: " + pcIds.Count + " ids [" + string.Join(",", new List<int>(pcIds).ConvertAll((int x) => x.ToString()).ToArray()) + "]"));
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("power cut ids: " + ex.Message));
		}
	}

	internal static void MiscTick()
	{
		try
		{
			if (GameMain.data == null)
			{
				return;
			}
			globalPassCounter++;
			bool flag = dirtyPass || globalPassCounter % (Compat.GenesisBook ? 60 : 600) == 0;
			bool flag2 = Sum(HexKind.VeinGuard) > 0.0;
			bool flag3 = Sum(HexKind.AssemblerSpeed) > 0.0;
			bool flag4 = Sum(HexKind.SprayHeavy) > 0.0;
			bool flag5 = Sum(HexKind.Fractionator) > 0.0;
			bool flag6 = Sum(HexKind.EjectorSpeed) > 0.0;
			bool flag7 = Sum(HexKind.TurretBoost) > 0.0;
			bool flag8 = Sum(HexKind.PowerCut) > 0.0;
			bool flag9 = Sum(HexKind.GenBoost) > 0.0;
			bool flag10 = Sum(HexKind.WindBoost) > 0.0;
			bool flag11 = Sum(HexKind.DropBoost) > 0.0;
			double value;
			if (flag2 || flag3)
			{
				double mul = (flag2 ? 2.0 : 1.0) * (flag3 ? 2.0 : 1.0);
				if (GameMain.history != null)
				{
					GameMain.history.miningSpeedScale = (float)Layer("mine", GameMain.history.miningSpeedScale, 0.0, mul);
				}
			}
			else if (GameMain.history != null && HexState.Bases.TryGetValue("mine#m", out value) && Math.Abs(value - 1.0) > 1E-09)
			{
				GameMain.history.miningSpeedScale = (float)Layer("mine", GameMain.history.miningSpeedScale, 0.0, 1.0);
			}
			if ((flag3 || flag4 || flag5 || flag6 || asmWasOn || beltWasOn || fracWasOn || ejWasOn) && (dirtyPass || ++speedCounter % 10 == 1))
			{
				FactorySpeedPass(flag3, flag4, flag5, flag6);
			}
			if (flag)
			{
				if (flag7 || turretDone)
				{
					TurretPass(flag7);
				}
				if (flag8 || pcWasOn)
				{
					PowerCutPass(flag8);
				}
				if (flag9 || genWasOn)
				{
					GenPass(flag9);
				}
				if (flag10 || windWasOn)
				{
					WindPass(flag10);
				}
				if (flag11 || dropWasOn)
				{
					DropPass(flag11);
				}
				if (flag2)
				{
					VeinKeepPass();
				}
				if (Compat.Mms)
				{
					ApplyStars();
				}
			}
			if (Sum(HexKind.StationMine) > 0.0 && counter2++ % 2 == 0)
			{
				StationMinePass();
			}
			dirtyPass = false;
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("misc: " + ex.Message));
		}
	}

	private static void FactorySpeedPass(bool over, bool spray, bool frac, bool eject)
	{
		double num = (over ? 2.0 : 1.0) * (spray ? 2.0 : 1.0);
		ItemProto[] dataArray = ((ProtoSet<ItemProto>)(object)LDB.items).dataArray;
		foreach (ItemProto val in dataArray)
		{
			if (val == null || val.prefabDesc == null)
			{
				continue;
			}
			PrefabDesc prefabDesc = val.prefabDesc;
			if (prefabDesc.isAssembler && prefabDesc.assemblerSpeed > 0)
			{
				if (!baseAssembler.TryGetValue(((Proto)val).ID, out var value))
				{
					baseAssembler[((Proto)val).ID] = prefabDesc.assemblerSpeed;
					value = prefabDesc.assemblerSpeed;
				}
				int num2 = (int)Math.Round((double)value * num);
				if (num2 < 1)
				{
					num2 = 1;
				}
				if (prefabDesc.assemblerSpeed != num2)
				{
					prefabDesc.assemblerSpeed = num2;
				}
			}
			if (prefabDesc.isBelt && prefabDesc.beltSpeed > 0)
			{
				if (!baseBelt.TryGetValue(((Proto)val).ID, out var value2))
				{
					baseBelt[((Proto)val).ID] = prefabDesc.beltSpeed;
					value2 = prefabDesc.beltSpeed;
				}
				int num3 = (spray ? (value2 * 2) : value2);
				if (prefabDesc.beltSpeed != num3)
				{
					prefabDesc.beltSpeed = num3;
				}
			}
			if (prefabDesc.isEjector)
			{
				if (!baseEjCharge.TryGetValue(((Proto)val).ID, out var value3))
				{
					baseEjCharge[((Proto)val).ID] = prefabDesc.ejectorChargeFrame;
					value3 = prefabDesc.ejectorChargeFrame;
				}
				if (!baseEjCold.TryGetValue(((Proto)val).ID, out var value4))
				{
					baseEjCold[((Proto)val).ID] = prefabDesc.ejectorColdFrame;
					value4 = prefabDesc.ejectorColdFrame;
				}
				prefabDesc.ejectorChargeFrame = (eject ? Math.Max(1, value3 / 5) : value3);
				prefabDesc.ejectorColdFrame = (eject ? Math.Max(1, value4 / 5) : value4);
			}
			if (prefabDesc.isSilo)
			{
				if (!baseSlCharge.TryGetValue(((Proto)val).ID, out var value5))
				{
					baseSlCharge[((Proto)val).ID] = prefabDesc.siloChargeFrame;
					value5 = prefabDesc.siloChargeFrame;
				}
				if (!baseSlCold.TryGetValue(((Proto)val).ID, out var value6))
				{
					baseSlCold[((Proto)val).ID] = prefabDesc.siloColdFrame;
					value6 = prefabDesc.siloColdFrame;
				}
				prefabDesc.siloChargeFrame = (eject ? Math.Max(1, value5 / 5) : value5);
				prefabDesc.siloColdFrame = (eject ? Math.Max(1, value6 / 5) : value6);
			}
		}
		ForEachFactory(delegate(PlanetFactory f)
		{
			FactorySystem factorySystem = f.factorySystem;
			if (factorySystem != null)
			{
				if (over || spray || asmWasOn)
				{
					AssemblerComponent[] assemblerPool = factorySystem.assemblerPool;
					if (assemblerPool != null)
					{
						int num4 = Math.Min(assemblerPool.Length, factorySystem.assemblerCursor);
						for (int j = 1; j < num4; j++)
						{
							if (assemblerPool[j].id == j)
							{
								ItemProto val2 = ProtoOf(f, assemblerPool[j].entityId);
								if (val2 != null && val2.prefabDesc != null)
								{
									int assemblerSpeed = val2.prefabDesc.assemblerSpeed;
									if (assemblerSpeed > 0 && assemblerPool[j].speed != assemblerSpeed)
									{
										assemblerPool[j].speed = assemblerSpeed;
									}
								}
							}
						}
					}
				}
				if (frac || fracWasOn)
				{
					FractionatorComponent[] fractionatorPool = factorySystem.fractionatorPool;
					if (fractionatorPool != null)
					{
						int num5 = Math.Min(fractionatorPool.Length, factorySystem.fractionatorCursor);
						for (int k = 1; k < num5; k++)
						{
							if (fractionatorPool[k].id == k)
							{
								float num6 = BaseFracProb(fractionatorPool[k].fluidId);
								float num7 = (frac ? Math.Min(1f, num6 * 50f) : num6);
								if (num6 > 0f && Math.Abs(fractionatorPool[k].produceProb - num7) > 1E-05f)
								{
									fractionatorPool[k].produceProb = num7;
								}
							}
						}
					}
				}
				if (spray || beltWasOn)
				{
					BeltComponent[] array = null;
					try
					{
						if (f.cargoTraffic != null)
						{
							array = f.cargoTraffic.beltPool;
						}
					}
					catch (Exception)
					{
					}
					if (array != null)
					{
						for (int l = 1; l < array.Length; l++)
						{
							if (array[l].id == l)
							{
								ItemProto val3 = ProtoOf(f, array[l].entityId);
								if (val3 != null && val3.prefabDesc != null)
								{
									int beltSpeed = val3.prefabDesc.beltSpeed;
									if (beltSpeed > 0 && array[l].speed != beltSpeed)
									{
										array[l].speed = beltSpeed;
									}
								}
							}
						}
					}
				}
				if (eject || ejWasOn)
				{
					EjectorComponent[] ejectorPool = factorySystem.ejectorPool;
					if (ejectorPool != null)
					{
						int num8 = Math.Min(ejectorPool.Length, factorySystem.ejectorCursor);
						for (int m = 1; m < num8; m++)
						{
							if (ejectorPool[m].id == m && !ejectorPool[m].boost)
							{
								ItemProto val4 = ProtoOf(f, ejectorPool[m].entityId);
								if (val4 != null && val4.prefabDesc != null)
								{
									int num9 = val4.prefabDesc.ejectorChargeFrame * 10000;
									if (num9 > 0 && ejectorPool[m].chargeSpend != num9)
									{
										ejectorPool[m].chargeSpend = num9;
									}
									int num10 = val4.prefabDesc.ejectorColdFrame * 10000;
									if (num10 > 0 && ejectorPool[m].coldSpend != num10)
									{
										ejectorPool[m].coldSpend = num10;
									}
								}
							}
						}
					}
					SiloComponent[] siloPool = factorySystem.siloPool;
					if (siloPool != null)
					{
						int num11 = Math.Min(siloPool.Length, factorySystem.siloCursor);
						for (int n = 1; n < num11; n++)
						{
							if (siloPool[n].id == n)
							{
								ItemProto val5 = ProtoOf(f, siloPool[n].entityId);
								if (val5 != null && val5.prefabDesc != null)
								{
									int num12 = val5.prefabDesc.siloChargeFrame * 10000;
									if (num12 > 0 && siloPool[n].chargeSpend != num12)
									{
										siloPool[n].chargeSpend = num12;
									}
									int num13 = val5.prefabDesc.siloColdFrame * 10000;
									if (num13 > 0 && siloPool[n].coldSpend != num13)
									{
										siloPool[n].coldSpend = num13;
									}
								}
							}
						}
					}
				}
			}
		});
		asmWasOn = over || spray;
		beltWasOn = spray;
		fracWasOn = frac;
		ejWasOn = eject;
	}

	private static float BaseFracProb(int fluidId)
	{
		try
		{
			RecipeProto[] fractionatorRecipes = RecipeProto.fractionatorRecipes;
			if (fractionatorRecipes == null)
			{
				return 0f;
			}
			foreach (RecipeProto val in fractionatorRecipes)
			{
				if (val != null && val.Items != null && val.Items[0] == fluidId)
				{
					int num = ((val.ItemCounts == null || val.ItemCounts.Length == 0) ? 1 : val.ItemCounts[0]);
					int num2 = ((val.Results != null && val.Results.Length != 0) ? val.Results[0] : 0);
					int num3 = ((val.ResultCounts == null || val.ResultCounts.Length == 0) ? 1 : val.ResultCounts[0]);
					if (num <= 0)
					{
						return 0f;
					}
					return (num2 > 0) ? ((float)num3 / (float)num) : 0f;
				}
			}
		}
		catch (Exception)
		{
		}
		return 0f;
	}

	private static void VeinKeepPass()
	{
		ForEachFactory(delegate(PlanetFactory f)
		{
			VeinData[] array = null;
			try
			{
				array = f.veinPool;
			}
			catch (Exception)
			{
			}
			if (array != null)
			{
				for (int i = 1; i < array.Length; i++)
				{
					if (array[i].id == i && array[i].amount > 0 && array[i].amount < 500000)
					{
						array[i].amount = 500000;
					}
				}
			}
		});
	}

	private static void TurretPass(bool on)
	{
		turretDone = on;
		int num = 0;
		ItemProto[] dataArray = ((ProtoSet<ItemProto>)(object)LDB.items).dataArray;
		foreach (ItemProto val in dataArray)
		{
			if (val == null || val.prefabDesc == null)
			{
				continue;
			}
			PrefabDesc prefabDesc = val.prefabDesc;
			if (prefabDesc.isTurret && !prefabDesc.isEnemy && !prefabDesc.isDFGroundTurret && !prefabDesc.isDFSpaceTurret)
			{
				if (!baseRange.TryGetValue(((Proto)val).ID, out var value))
				{
					baseRange[((Proto)val).ID] = prefabDesc.turretMaxAttackRange;
					value = prefabDesc.turretMaxAttackRange;
				}
				if (!baseSpaceRange.TryGetValue(((Proto)val).ID, out var value2))
				{
					baseSpaceRange[((Proto)val).ID] = prefabDesc.turretSpaceAttackRange;
					value2 = prefabDesc.turretSpaceAttackRange;
				}
				if (!baseRof.TryGetValue(((Proto)val).ID, out var value3))
				{
					baseRof[((Proto)val).ID] = prefabDesc.turretROF;
					value3 = prefabDesc.turretROF;
				}
				if (!baseMuzzleIv.TryGetValue(((Proto)val).ID, out var value4))
				{
					baseMuzzleIv[((Proto)val).ID] = prefabDesc.turretMuzzleInterval;
					value4 = prefabDesc.turretMuzzleInterval;
				}
				if (!baseRoundIv.TryGetValue(((Proto)val).ID, out var value5))
				{
					baseRoundIv[((Proto)val).ID] = prefabDesc.turretRoundInterval;
					value5 = prefabDesc.turretRoundInterval;
				}
				float num2 = (on ? (value * 2f) : value);
				float num3 = ((on && value2 > 0f) ? (value2 * 2f) : value2);
				int num4 = ((on && value3 > 0) ? (value3 * 2) : value3);
				if (prefabDesc.turretMaxAttackRange != num2)
				{
					prefabDesc.turretMaxAttackRange = num2;
				}
				if (prefabDesc.turretSpaceAttackRange != num3)
				{
					prefabDesc.turretSpaceAttackRange = num3;
				}
				if (prefabDesc.turretMuzzleInterval != value4)
				{
					prefabDesc.turretMuzzleInterval = value4;
				}
				if (prefabDesc.turretRoundInterval != value5)
				{
					prefabDesc.turretRoundInterval = value5;
				}
				if (prefabDesc.turretROF != num4)
				{
					prefabDesc.turretROF = num4;
				}
				num++;
			}
		}
		if (!turretLogged)
		{
			turretLogged = true;
			Plugin.Log.LogInfo((object)("turret prefab scan: " + num + " turrets"));
		}
	}

	private static void PowerCutPass(bool on)
	{
		pcWasOn = on;
		int num = 0;
		ItemProto[] dataArray = ((ProtoSet<ItemProto>)(object)LDB.items).dataArray;
		foreach (ItemProto val in dataArray)
		{
			if (val != null && ((Proto)val).name != null && val.prefabDesc != null && IsPowerCutTarget(((Proto)val).ID))
			{
				if (!baseWork.TryGetValue(((Proto)val).ID, out var value))
				{
					baseWork[((Proto)val).ID] = val.prefabDesc.workEnergyPerTick;
					value = val.prefabDesc.workEnergyPerTick;
				}
				if (!baseIdle.TryGetValue(((Proto)val).ID, out var value2))
				{
					baseIdle[((Proto)val).ID] = val.prefabDesc.idleEnergyPerTick;
					value2 = val.prefabDesc.idleEnergyPerTick;
				}
				long num2 = (on ? Math.Max(1L, value / 10) : value);
				long num3 = (on ? (value2 / 10) : value2);
				if (val.prefabDesc.workEnergyPerTick != num2)
				{
					val.prefabDesc.workEnergyPerTick = num2;
				}
				if (val.prefabDesc.idleEnergyPerTick != num3)
				{
					val.prefabDesc.idleEnergyPerTick = num3;
				}
				num++;
			}
		}
		int m = 0;
		ForEachFactory(delegate(PlanetFactory f)
		{
			PowerSystem powerSystem = f.powerSystem;
			if (powerSystem != null && powerSystem.consumerPool != null)
			{
				int num4 = ((f.planet != null) ? f.planet.id : 0);
				int num5 = Math.Min(powerSystem.consumerCursor, powerSystem.consumerPool.Length);
				for (int j = 1; j < num5; j++)
				{
					if (powerSystem.consumerPool[j].id == j)
					{
						int entityId = powerSystem.consumerPool[j].entityId;
						ItemProto val2 = ProtoOf(f, entityId);
						if (val2 != null && val2.prefabDesc != null && IsPowerCutTarget(((Proto)val2).ID))
						{
							long workEnergyPerTick = val2.prefabDesc.workEnergyPerTick;
							long idleEnergyPerTick = val2.prefabDesc.idleEnergyPerTick;
							long key = ((long)num4 << 40) + (uint)entityId;
							long value4;
							if (pcWrote.TryGetValue(key, out var value3))
							{
								if (powerSystem.consumerPool[j].workEnergyPerTick == value3[0])
								{
									if (powerSystem.consumerPool[j].workEnergyPerTick != workEnergyPerTick)
									{
										powerSystem.consumerPool[j].workEnergyPerTick = workEnergyPerTick;
									}
									if (powerSystem.consumerPool[j].idleEnergyPerTick == value3[1] && powerSystem.consumerPool[j].idleEnergyPerTick != idleEnergyPerTick)
									{
										powerSystem.consumerPool[j].idleEnergyPerTick = idleEnergyPerTick;
									}
									value3[0] = workEnergyPerTick;
									value3[1] = idleEnergyPerTick;
									m++;
								}
								else
								{
									pcWrote.Remove(key);
								}
							}
							else if (baseWork.TryGetValue(((Proto)val2).ID, out value4))
							{
								if (!baseIdle.TryGetValue(((Proto)val2).ID, out var value5))
								{
									value5 = idleEnergyPerTick;
								}
								if (powerSystem.consumerPool[j].workEnergyPerTick == value4)
								{
									powerSystem.consumerPool[j].workEnergyPerTick = workEnergyPerTick;
									if (powerSystem.consumerPool[j].idleEnergyPerTick == value5)
									{
										powerSystem.consumerPool[j].idleEnergyPerTick = idleEnergyPerTick;
									}
									pcWrote[key] = new long[2] { workEnergyPerTick, idleEnergyPerTick };
									m++;
								}
							}
						}
					}
				}
			}
		});
		if (!powerCutDone)
		{
			powerCutDone = true;
			Plugin.Log.LogInfo((object)("power cut: " + num + " prefabs, " + m + " built consumers"));
		}
	}

	private static void GenPass(bool on)
	{
		genWasOn = on;
		int num = 0;
		ItemProto[] dataArray = ((ProtoSet<ItemProto>)(object)LDB.items).dataArray;
		foreach (ItemProto val in dataArray)
		{
			if (val == null || val.prefabDesc == null)
			{
				continue;
			}
			PrefabDesc prefabDesc = val.prefabDesc;
			if (prefabDesc.isPowerGen && prefabDesc.genEnergyPerTick > 0 && (prefabDesc.useFuelPerTick > 0 || prefabDesc.fuelMask != 0 || prefabDesc.powerCatalystId > 0))
			{
				if (!baseGen.TryGetValue(((Proto)val).ID, out var value))
				{
					baseGen[((Proto)val).ID] = prefabDesc.genEnergyPerTick;
					value = prefabDesc.genEnergyPerTick;
				}
				long num2 = (on ? (value * 4) : value);
				if (prefabDesc.genEnergyPerTick != num2)
				{
					prefabDesc.genEnergyPerTick = num2;
				}
				num++;
			}
		}
		ForEachFactory(delegate(PlanetFactory f)
		{
			PowerSystem powerSystem = f.powerSystem;
			if (powerSystem != null && powerSystem.genPool != null)
			{
				int num3 = Math.Min(powerSystem.genCursor, powerSystem.genPool.Length);
				for (int j = 1; j < num3; j++)
				{
					if (powerSystem.genPool[j].id == j)
					{
						ItemProto val2 = ProtoOf(f, powerSystem.genPool[j].entityId);
						if (val2 != null && val2.prefabDesc != null && ((Proto)val2).name != null && baseGen.TryGetValue(((Proto)val2).ID, out var value2))
						{
							long num4 = (on ? (value2 * 4) : value2);
							if (powerSystem.genPool[j].genEnergyPerTick != num4)
							{
								powerSystem.genPool[j].genEnergyPerTick = num4;
							}
						}
					}
				}
			}
		});
		if (!genLogged)
		{
			genLogged = true;
			Plugin.Log.LogInfo((object)("thermal power buildings: " + num));
		}
	}

	private static void WindPass(bool on)
	{
		windWasOn = on;
		int num = 0;
		try
		{
			StarData[] array = ((GameMain.galaxy != null) ? GameMain.galaxy.stars : null);
			if (array == null)
			{
				return;
			}
			double mul = (on ? 11.0 : 1.0);
			StarData[] array2 = array;
			foreach (StarData val in array2)
			{
				if (val == null || val.planets == null)
				{
					continue;
				}
				PlanetData[] planets = val.planets;
				foreach (PlanetData val2 in planets)
				{
					if (val2 != null)
					{
						val2.windStrength = (float)ScaleFromBase("wind" + val2.id, val2.windStrength, mul, 11.0);
						val2.luminosity = (float)ScaleFromBase("lum" + val2.id, val2.luminosity, mul, 11.0);
						num++;
					}
				}
			}
		}
		catch (Exception)
		{
		}
		if (!windLogged)
		{
			windLogged = true;
			Plugin.Log.LogInfo((object)("wind/solar x11 on " + num + " planets"));
		}
	}

	private static void DropPass(bool on)
	{
		dropWasOn = on;
		int num = 0;
		ItemProto[] dataArray = ((ProtoSet<ItemProto>)(object)LDB.items).dataArray;
		foreach (ItemProto val in dataArray)
		{
			if (val == null || val.prefabDesc == null || (BGet("ehp" + ((Proto)val).ID, -1.0) < 0.0 && val.prefabDesc.enemyMaxEnergy <= 0))
			{
				continue;
			}
			if (val.prefabDesc.enemyMaxEnergy > 0 && BGet("ehp" + ((Proto)val).ID, -1.0) < 0.0)
			{
				BSet("ehp" + ((Proto)val).ID, val.prefabDesc.enemyMaxEnergy);
			}
			double num2 = BGet("ehp" + ((Proto)val).ID, -1.0);
			if (!(num2 <= 0.0))
			{
				int num3 = (int)Math.Round(num2 * (on ? 1.5 : 1.0));
				if (val.prefabDesc.enemyMaxEnergy != num3)
				{
					val.prefabDesc.enemyMaxEnergy = num3;
				}
				num++;
			}
		}
		if (GameMain.history != null)
		{
			GameMain.history.enemyDropScale = (float)Layer("drop", GameMain.history.enemyDropScale, 0.0, on ? 31.0 : 1.0);
		}
		if (!dropLogged)
		{
			dropLogged = true;
			Plugin.Log.LogInfo((object)("drop boost on " + num + " enemy prefabs"));
		}
	}

	private static void StationMinePass()
	{
		StationComponent[] sp = ((GameMain.data.galacticTransport != null) ? GameMain.data.galacticTransport.stationPool : null);
		if (sp == null)
		{
			return;
		}
		ForEachFactory(delegate(PlanetFactory f)
		{
			PlanetData planet = f.planet;
			if (planet != null)
			{
				VeinData[] veinPool = f.veinPool;
				if (veinPool != null)
				{
					List<int> list = new List<int>();
					int num = Math.Min(f.veinCursor, veinPool.Length);
					for (int i = 1; i < num; i++)
					{
						if (veinPool[i].id == i && veinPool[i].productId > 0 && !list.Contains(veinPool[i].productId))
						{
							list.Add(veinPool[i].productId);
						}
					}
					if (list.Count != 0)
					{
						StationComponent[] array = sp;
						foreach (StationComponent val in array)
						{
							if (val != null && val.storage != null && val.planetId == planet.id)
							{
								foreach (int item in list)
								{
									for (int k = 0; k < val.storage.Length; k++)
									{
										if (val.storage[k].itemId == item)
										{
											int max = val.storage[k].max;
											if (max > 0)
											{
												int val2 = val.storage[k].count + 2;
												val.storage[k].count = Math.Min(max, val2);
												break;
											}
										}
									}
								}
							}
						}
					}
				}
			}
		});
	}

	private static double ScaleFromBase(string key, double cur, double mul, double lastMul)
	{
		double num = BGet(key, double.NaN);
		double num2 = BGet(key + "#w", double.NaN);
		if (double.IsNaN(num) || num <= 0.0)
		{
			num = cur;
		}
		if (!double.IsNaN(num2) && Math.Abs(cur - num2) > Math.Abs(num2) * 0.01 + 1E-06)
		{
			num = cur / ((lastMul > 1E-06) ? lastMul : 1.0);
		}
		double num3 = num * mul;
		BSet(key, num);
		BSet(key + "#w", num3);
		return num3;
	}

	private static void ApplyAll(Mecha m)
	{
		double num = BGet("hpLegacyBase", -1.0);
		if (num >= 0.0)
		{
			double num2 = (double)m.hpMax - num;
			BSet("hp#f", (num2 > 0.0) ? num2 : 0.0);
			HexState.Bases.Remove("hpLegacyBase");
		}
		double num3 = ((HexState.QuestDone && Sum(HexKind.KillQuest) > 0.0) ? (1.0 + Sum(HexKind.AllStatsPct)) : 1.0);
		int num4 = (int)Math.Round(Layer("hp", m.hpMax, Sum(HexKind.HpFlat), (1.0 + Sum(HexKind.HpPct)) * num3));
		if (num4 < 1000)
		{
			num4 = 1000;
		}
		if (m.hpMax != num4)
		{
			m.hpMax = num4;
		}
		if (m.hp > m.hpMax)
		{
			m.hp = m.hpMax;
		}
		int num5;
		if (Sum(HexKind.ShieldFromHp) > 0.0)
		{
			num5 = ShieldFromHpTarget(m);
		}
		else if (BGet("shOn", 0.0) > 0.0)
		{
			double num6 = 1.0 + Sum(HexKind.ShieldPct);
			num5 = (int)Math.Round(BGet("shBase", 0.0) * num6);
			HexState.Bases["shield#f"] = 0.0;
			HexState.Bases["shield#m"] = num6;
			HexState.Bases["shOn"] = 0.0;
		}
		else
		{
			num5 = (int)Math.Round(Layer("shield", m.energyShieldCapacity, 0.0, (1.0 + Sum(HexKind.ShieldPct)) * num3));
		}
		if (num5 < 0)
		{
			num5 = 0;
		}
		if (Math.Abs(m.energyShieldCapacity - num5) > 1)
		{
			m.energyShieldCapacity = num5;
		}
		if (m.energyShieldEnergy > m.energyShieldCapacity)
		{
			m.energyShieldEnergy = m.energyShieldCapacity;
		}
		m.walkSpeed = (float)Layer("walk", m.walkSpeed, 0.0, (1.0 + Sum(HexKind.WalkPct)) * num3);
		m.jumpSpeed = (float)Layer("jump", m.jumpSpeed, 0.0, (1.0 + Sum(HexKind.JumpPct)) * num3);
		m.maxSailSpeed = (float)Layer("sail", m.maxSailSpeed, 0.0, (1.0 + Sum(HexKind.SailPct)) * num3);
		m.maxWarpSpeed = (float)Layer("warp", m.maxWarpSpeed, 0.0, (1.0 + Sum(HexKind.WarpPct)) * num3);
		if (BGet("questCore", 0.0) > 0.0 && BGet("coreMig", 0.0) <= 0.0)
		{
			BSet("coreMig", 1.0);
			if (!HexState.Bases.ContainsKey("core"))
			{
				BSet("core", m.coreEnergyCap / 1.25);
			}
		}
		m.coreEnergyCap = Layer("core", m.coreEnergyCap, 0.0, num3);
		ApplyDamageScales();
		ApplyHistory(HexKind.DroneDmgPct, 1.0 + Sum(HexKind.DroneDmgPct), delegate(GameHistoryData h, double v)
		{
			float num16 = (float)v;
			h.combatDroneDamageRatio *= num16;
			h.combatShipDamageRatio *= num16;
		});
		ApplyHistory(HexKind.DroneRofPct, 1.0 + Sum(HexKind.DroneRofPct), delegate(GameHistoryData h, double v)
		{
			float num16 = (float)v;
			h.combatDroneROFRatio *= num16;
			h.combatShipROFRatio *= num16;
		});
		ApplyHistory(HexKind.DroneDurPct, 1.0 + Sum(HexKind.DroneDurPct), delegate(GameHistoryData h, double v)
		{
			float num16 = (float)v;
			h.combatDroneDurabilityRatio *= num16;
			h.combatShipDurabilityRatio *= num16;
		});
		ApplyStars();
		double num7 = 1.0 + Sum(HexKind.AmmoRofPct);
		int num8 = (int)Math.Round(Sum(HexKind.MuzzleAdd));
		double mul = num7 * Math.Pow(0.9090909090909091, num8);
		string[] array = new string[4] { "bulletMuzzleCount", "cannonMuzzleCount", "plasmaMuzzleCount", "missileMuzzleCount" };
		string[] array2 = new string[4] { "bulletROF", "cannonROF", "plasmaROF", "missileROF" };
		string[] array3 = array;
		foreach (string text in array3)
		{
			SetMechaIntLayer(m, text, "muz_" + text, num8, 1.0, 1);
		}
		string[] array4 = array2;
		foreach (string text2 in array4)
		{
			SetMechaIntLayer(m, text2, "rof_" + text2, 0.0, mul, 1);
		}
		bool flag = Sum(HexKind.AmmoAll) > 0.0;
		if (!flag && ammoWasOn)
		{
			m.laserActive = false;
			try
			{
				FieldInfo field = typeof(Mecha).GetField("bombActive", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					field.SetValue(m, false);
				}
			}
			catch (Exception)
			{
			}
			Plugin.Log.LogInfo((object)"ammo all removed: laser/bomb toggles restored");
		}
		ammoWasOn = flag;
		double num11 = 1.0 + Sum(HexKind.RangePct);
		applied.TryGetValue(HexKind.RangePct, out var value);
		if (value <= 0.0)
		{
			value = 1.0;
		}
		if (Math.Abs(num11 - value) > 1E-06)
		{
			ApplyMechaRange(m, num11 / value);
			SetApplied(HexKind.RangePct, num11);
		}
		double num12 = Sum(HexKind.LaserBoost);
		if (GameMain.mainPlayer != null && GameMain.mainPlayer.mecha != null)
		{
			Mecha mecha = GameMain.mainPlayer.mecha;
			if (num12 > 0.0)
			{
				laserApplied = true;
				if (!HexState.Bases.ContainsKey("laserOn"))
				{
					if (BGet("laserLegacyFix", 0.0) > 0.0)
					{
						BSet("laserB_dL", (double)mecha.laserLocalDamage / 11.0);
						BSet("laserB_dS", (double)mecha.laserSpaceDamage / 11.0);
						BSet("laserB_rL", (double)mecha.laserLocalAttackRange / 6.0);
						BSet("laserB_rS", (double)mecha.laserSpaceAttackRange / 6.0);
						BSet("laserB_iL", (double)mecha.laserLocalInterval * 11.0);
						BSet("laserB_iS", (double)mecha.laserSpaceInterval * 11.0);
						BSet("laserB_fleet", 0.0);
						HexState.Bases.Remove("laserLegacyFix");
					}
					else
					{
						BSet("laserB_dL", mecha.laserLocalDamage);
						BSet("laserB_dS", mecha.laserSpaceDamage);
						BSet("laserB_rL", mecha.laserLocalAttackRange);
						BSet("laserB_rS", mecha.laserSpaceAttackRange);
						BSet("laserB_iL", mecha.laserLocalInterval);
						BSet("laserB_iS", mecha.laserSpaceInterval);
						try
						{
							if (mecha.groundCombatModule != null)
							{
								BSet("laserB_fleet", mecha.groundCombatModule.fleetCount);
							}
						}
						catch (Exception)
						{
						}
						mecha.laserLocalDamage = (int)((float)mecha.laserLocalDamage * 11f);
						mecha.laserSpaceDamage = (int)((float)mecha.laserSpaceDamage * 11f);
						mecha.laserLocalAttackRange *= 6f;
						mecha.laserSpaceAttackRange *= 6f;
						if (mecha.laserLocalInterval > 0)
						{
							mecha.laserLocalInterval = Math.Max(1, mecha.laserLocalInterval / 11);
						}
						if (mecha.laserSpaceInterval > 0)
						{
							mecha.laserSpaceInterval = Math.Max(1, mecha.laserSpaceInterval / 11);
						}
						try
						{
							if (mecha.groundCombatModule != null)
							{
								mecha.groundCombatModule.fleetCount = 0;
							}
						}
						catch (Exception)
						{
						}
					}
					BSet("laserOn", 1.0);
					HexState.Bases["laserDone"] = 1.0;
					HexState.Save();
					Plugin.Log.LogInfo((object)"laser boost applied (baseline cached)");
				}
			}
			else if (laserApplied || HexState.Bases.ContainsKey("laserOn") || HexState.Bases.ContainsKey("laserDone"))
			{
				laserApplied = false;
				if (HexState.Bases.ContainsKey("laserOn"))
				{
					mecha.laserLocalDamage = (int)BGet("laserB_dL", mecha.laserLocalDamage);
					mecha.laserSpaceDamage = (int)BGet("laserB_dS", mecha.laserSpaceDamage);
					mecha.laserLocalAttackRange = (float)BGet("laserB_rL", mecha.laserLocalAttackRange);
					mecha.laserSpaceAttackRange = (float)BGet("laserB_rS", mecha.laserSpaceAttackRange);
					mecha.laserLocalInterval = (int)BGet("laserB_iL", mecha.laserLocalInterval);
					mecha.laserSpaceInterval = (int)BGet("laserB_iS", mecha.laserSpaceInterval);
					try
					{
						if (mecha.groundCombatModule != null && HexState.Bases.ContainsKey("laserB_fleet"))
						{
							mecha.groundCombatModule.fleetCount = (int)BGet("laserB_fleet", mecha.groundCombatModule.fleetCount);
						}
					}
					catch (Exception)
					{
					}
				}
				RemoveBases("laser");
				HexState.Save();
				Plugin.Log.LogInfo((object)"laser boost rolled back (card removed)");
			}
		}
		if (GameMain.history != null)
		{
			if (Sum(HexKind.KineticToBlast) > 0.0 && !convKinetic)
			{
				GameHistoryData history = GameMain.history;
				history.blastDamageScale += GameMain.history.kineticDamageScale;
				GameMain.history.kineticDamageScale = 0f;
				convKinetic = true;
				Plugin.Log.LogInfo((object)"kinetic damage converted to blast");
			}
			if (Sum(HexKind.BlastToEnergy) > 0.0 && !convBlast)
			{
				GameHistoryData history2 = GameMain.history;
				history2.energyDamageScale += GameMain.history.blastDamageScale;
				GameMain.history.blastDamageScale = 0f;
				convBlast = true;
				Plugin.Log.LogInfo((object)"blast damage converted to energy");
			}
		}
		int num13 = (int)Math.Round(Sum(HexKind.FleetAdd));
		int num14 = (int)BaseOf("fleetDone", appliedFleet);
		if (num13 != num14)
		{
			int num15 = num13 - num14;
			try
			{
				bool flag2 = false;
				if (m.groundCombatModule != null)
				{
					m.groundCombatModule.fleetCount = Math.Max(0, Math.Min(48, m.groundCombatModule.fleetCount + num15));
					flag2 = true;
				}
				if (m.spaceCombatModule != null)
				{
					m.spaceCombatModule.fleetCount = Math.Max(0, Math.Min(48, m.spaceCombatModule.fleetCount + num15));
					flag2 = true;
				}
				if (flag2)
				{
					appliedFleet = num13;
					HexState.Bases["fleetDone"] = num13;
					HexState.Save();
					Plugin.Log.LogInfo((object)("fleet +" + num13));
				}
			}
			catch (Exception)
			{
			}
		}
		RefreshCache();
		Plugin.Log.LogInfo((object)("effects applied, owned=" + HexState.Owned.Count));
	}

	private static void RemoveBases(string prefix)
	{
		List<string> list = new List<string>();
		foreach (string key in HexState.Bases.Keys)
		{
			if (key.StartsWith(prefix, StringComparison.Ordinal))
			{
				list.Add(key);
			}
		}
		foreach (string item in list)
		{
			HexState.Bases.Remove(item);
		}
	}

	private static double BGet(string key, double dflt)
	{
		double value;
		return HexState.Bases.TryGetValue(key, out value) ? value : dflt;
	}

	private static void BSet(string key, double v)
	{
		HexState.Bases[key] = v;
	}

	private static double Layer(string key, double cur, double flat, double mul)
	{
		double num = BGet(key + "#m", 1.0);
		if (num <= 1E-09 || num > 1000000000.0)
		{
			num = 1.0;
		}
		double num2 = (cur - BGet(key + "#f", 0.0)) / num;
		BSet(key + "#f", flat);
		BSet(key + "#m", mul);
		return num2 * mul + flat;
	}

	private static void SetMechaIntLayer(Mecha m, string fieldName, string key, double flat, double mul, int min)
	{
		try
		{
			FieldInfo field = typeof(Mecha).GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field == null)
			{
				if (loggedMissing.Add(fieldName))
				{
					Plugin.Log.LogWarning((object)("mecha field not found: " + fieldName));
				}
				return;
			}
			int num = Convert.ToInt32(field.GetValue(m));
			int num2 = (int)Math.Round(Layer(key, num, flat, mul));
			if (num2 < min)
			{
				num2 = min;
			}
			if (num2 != num)
			{
				field.SetValue(m, num2);
			}
		}
		catch (Exception)
		{
		}
	}

	private static int ShieldFromHpTarget(Mecha m)
	{
		double num = 1.0 + Sum(HexKind.ShieldPct);
		double num2 = BGet("shield#m", 1.0);
		if (num2 <= 1E-09)
		{
			num2 = 1.0;
		}
		double num3 = ((double)m.energyShieldCapacity - BGet("shield#f", 0.0)) / num2;
		double num4 = BGet("shBase", -1.0);
		if (num4 < 0.0)
		{
			num4 = Math.Max(0.0, num3);
		}
		else if (num3 > num4 * 1.02 + 256.0)
		{
			num4 = num3;
		}
		BSet("shBase", num4);
		BSet("shield#f", 0.0);
		BSet("shield#m", num);
		BSet("shOn", 1.0);
		double a = Math.Max(num4, (double)m.hpMax * Sum(HexKind.ShieldFromHp)) * num;
		return (int)Math.Round(a);
	}

	private static void ForEachFactory(Action<PlanetFactory> act)
	{
		try
		{
			if (GameMain.data == null)
			{
				return;
			}
			PlanetFactory[] factories = GameMain.data.factories;
			if (factories == null)
			{
				return;
			}
			int num = Math.Min(GameMain.data.factoryCount, factories.Length);
			for (int i = 0; i < num; i++)
			{
				PlanetFactory val = factories[i];
				if (val != null && val.factorySystem != null)
				{
					try
					{
						act(val);
					}
					catch (Exception)
					{
					}
				}
			}
		}
		catch (Exception)
		{
		}
	}

	private static ItemProto ProtoOf(PlanetFactory f, int entityId)
	{
		try
		{
			if (entityId <= 0 || f.entityPool == null || entityId >= f.entityPool.Length)
			{
				return null;
			}
			if (f.entityPool[entityId].id != entityId)
			{
				return null;
			}
			return ((ProtoSet<ItemProto>)(object)LDB.items).Select((int)f.entityPool[entityId].protoId);
		}
		catch (Exception)
		{
			return null;
		}
	}

	private static void ApplyHistory(HexKind k, double target, Action<GameHistoryData, double> setter)
	{
		if (GameMain.history == null)
		{
			return;
		}
		applied.TryGetValue(k, out var value);
		if (value <= 0.0)
		{
			value = 1.0;
		}
		if (Math.Abs(target - value) < 1E-06)
		{
			return;
		}
		try
		{
			setter(GameMain.history, target / value);
			SetApplied(k, target);
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("apply hist " + k.ToString() + ": " + ex.Message));
		}
	}
}
internal static class DrawUI
{
	private static GUIStyle box;

	private static GUIStyle title;

	private static GUIStyle subtitle;

	private static GUIStyle name;

	private static GUIStyle desc;

	private static GUIStyle btn;

	private static GUIStyle smallBox;

	private static GUIStyle rarityLbl;

	private static GUIStyle statusBig;

	private static Font font;

	private static Texture2D panelTex;

	private static Texture2D cardTex;

	internal static bool CancelMode;

	internal static readonly Color[] RarityColor = (Color[])(object)new Color[3]
	{
		new Color(0.78f, 0.82f, 0.88f),
		new Color(1f, 0.78f, 0.25f),
		new Color(0.8f, 0.55f, 1f)
	};

	private static readonly Random rng = new Random();

	private static void Init()
	{
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Expected O, but got Unknown
		//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)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Expected O, but got Unknown
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Expected O, but got Unknown
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: Expected O, but got Unknown
		//IL_011a: 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_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0134: Unknown result type (might be due to invalid IL or missing references)
		//IL_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Expected O, but got Unknown
		//IL_0153: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: Unknown result type (might be due to invalid IL or missing references)
		//IL_016d: Unknown result type (might be due to invalid IL or missing references)
		//IL_017a: Expected O, but got Unknown
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_0189: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_019e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ab: Expected O, but got Unknown
		//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_01c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cf: 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_01e4: Expected O, but got Unknown
		//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0208: Unknown result type (might be due to invalid IL or missing references)
		//IL_0210: Unknown result type (might be due to invalid IL or missing references)
		//IL_021d: Expected O, but got Unknown
		if (box == null)
		{
			font = Font.CreateDynamicFontFromOSFont(new string[3] { "Microsoft YaHei", "SimHei", "Arial" }, 16);
			box = new GUIStyle(GUI.skin.box)
			{
				font = font,
				fontSize = 16,
				wordWrap = true
			};
			title = new GUIStyle(GUI.skin.label)
			{
				font = font,
				fontSize = 30,
				fontStyle = (FontStyle)1,
				alignment = (TextAnchor)4
			};
			subtitle = new GUIStyle(GUI.skin.label)
			{
				font = font,
				fontSize = 16,
				alignment = (TextAnchor)4
			};
			name = new GUIStyle(GUI.skin.label)
			{
				font = font,
				fontSize = 23,
				fontStyle = (FontStyle)1,
				alignment = (TextAnchor)4
			};
			desc = new GUIStyle(GUI.skin.label)
			{
				font = font,
				fontSize = 16,
				wordWrap = true,
				alignment = (TextAnchor)1
			};
			btn = new GUIStyle(GUI.skin.button)
			{
				font = font,
				fontSize = 17,
				fontStyle = (FontStyle)1
			};
			smallBox = new GUIStyle(GUI.skin.box)
			{
				font = font,
				fontSize = 14,
				alignment = (TextAnchor)4
			};
			rarityLbl = new GUIStyle(GUI.skin.label)
			{
				font = font,
				fontSize = 16,
				fontStyle = (FontStyle)1,
				alignment = (TextAnchor)4
			};
			statusBig = new GUIStyle(GUI.skin.label)
			{
				font = font,
				fontSize = 18,
				fontStyle = (FontStyle)1,
				alignment = (TextAnchor)4
			};
			panelTex = Texture2D.whiteTexture;
			cardTex = Texture2D.whiteTexture;
		}
	}

	internal static void InitStyles()
	{
		Init();
	}

	internal static GUIStyle Small()
	{
		Init();
		return smallBox;
	}

	internal static void OnGUI()
	{
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: 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_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_0173: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b2: 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_028b: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e8: 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_0309: Unknown result type (might be due to invalid IL or missing references)
		//IL_033c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0352: Unknown result type (might be due to invalid IL or missing references)
		//IL_035d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0373: Unknown result type (might be due to invalid IL or missing references)
		//IL_037e: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_03fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0405: Unknown result type (might be due to invalid IL or missing references)
		//IL_0452: Unknown result type (might be due to invalid IL or missing references)
		//IL_047c: Unknown result type (might be due to invalid IL or missing references)
		if (HexState.Drawing)
		{
			Init();
			Rect r = default(Rect);
			((Rect)(ref r))..ctor((float)((Screen.width - 1250) / 2), (float)((Screen.height - 700) / 2), 1250f, 700f);
			Fill(r, new Color(0.03f, 0.04f, 0.07f, 0.97f));
			Outline(r, new Color(0.42f, 0.66f, 1f, 0.95f), 2);
			Fill(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y, 1250f, 4f), new Color(0.42f, 0.66f, 1f, 1f));
			Rect r2 = default(Rect);
			((Rect)(ref r2))..ctor(((Rect)(ref r)).x, ((Rect)(ref r)).y + 6f, 1250f, 78f);
			FillGrad(r2, new Color(0.1f, 0.16f, 0.3f, 0.95f), new Color(0.05f, 0.07f, 0.12f, 0.95f));
			GUI.Label(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y + 12f, 1250f, 40f), "海克斯 · 3 选 1", title);
			GUI.Label(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y + 54f, 1250f, 26f), "每 10 级机甲核心获得一次抽取", subtitle);
			if (GUI.Button(new Rect(((Rect)(ref r)).x + 1250f - 52f, ((Rect)(ref r)).y + 12f, 38f, 34f), "X", btn))
			{
				Close();
			}
			for (int i = 0; i < 3; i++)
			{
				Card(((Rect)(ref r)).x + 40f + (float)(i * 392), ((Rect)(ref r)).y + 104f, 372f, 440f, HexState.Options[i], i);
			}
			float num = ((Rect)(ref r)).y + 566f;
			int num2 = RefreshCost();
			string label = ((num2 <= 0) ? "刷新(免费)" : ("刷新(" + num2 + " 宇宙矩阵)"));
			GradientButton(new Rect(((Rect)(ref r)).x + 40f, num, 300f, 46f), label, new Color(0.16f, 0.42f, 0.7f), Refresh);
			string label2 = (HexState.DeleteUsed ? "本次抽奖已删除过" : "删除一个已有的海克斯(每次抽奖限一次)");
			Color tint = (HexState.DeleteUsed ? new Color(0.25f, 0.25f, 0.28f) : new Color(0.52f, 0.22f, 0.24f));
			GradientButton(new Rect(((Rect)(ref r)).x + 356f, num, 420f, 46f), label2, tint, ToggleDelete);
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((Rect)(ref r)).x + 820f, num, 190f, 46f);
			Fill(val, new Color(0.1f, 0.14f, 0.22f, 0.95f));
			Outline(val, new Color(0.42f, 0.66f, 1f, 0.6f));
			GUI.Label(val, "待抽 " + HexState.Pending + " 次", statusBig);
			Rect val2 = default(Rect);
			((Rect)(ref val2))..ctor(((Rect)(ref r)).x + 1024f, num, 186f, 46f);
			Fill(val2, new Color(0.1f, 0.14f, 0.22f, 0.95f));
			Outline(val2, new Color(0.8f, 0.65f, 0.3f, 0.7f));
			GUI.Label(val2, "已拥有 " + HexState.Owned.Count + "/10", statusBig);
			GUI.Label(new Rect(((Rect)(ref r)).x + 40f, num + 56f, 1168f, 40f), "当前:" + OwnedText(), desc);
			if (CancelMode)
			{
				DeleteList(r);
			}
		}
	}

	private static void Card(float x, float y, float w, float h, string id, int idx)
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: 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_0068: 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_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: 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_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_0199: Unknown result type (might be due to invalid IL or missing references)
		//IL_019f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b0: 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_01ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_021d: Unknown result type (might be due to invalid IL or missing references)
		//IL_024f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		HexDef hexDef = Catalog.Get(id);
		Color val = (Color)((hexDef != null) ? RarityColor[(int)hexDef.R] : new Color(0.35f, 0.35f, 0.35f));
		Rect val2 = default(Rect);
		((Rect)(ref val2))..ctor(x, y, w, h);
		bool flag = ((Rect)(ref val2)).Contains(Event.current.mousePosition);
		Fill(val2, flag ? new Color(0.11f, 0.13f, 0.19f, 1f) : new Color(0.08f, 0.09f, 0.14f, 1f));
		Outline(val2, val, flag ? 3 : 2);
		FillGrad(new Rect(((Rect)(ref val2)).x + 2f, ((Rect)(ref val2)).y + 2f, ((Rect)(ref val2)).width - 4f, 6f), new Color(val.r, val.g, val.b, 0.95f), new Color(val.r, val.g, val.b, 0.15f));
		if (hexDef == null)
		{
			GUI.Label(val2, "空", name);
			return;
		}
		Texture2D val3 = IconStore.Get(hexDef.Id);
		if ((Object)(object)val3 != (Object)null)
		{
			GUI.DrawTexture(new Rect(x + (w - 160f) / 2f, y + 26f, 160f, 160f), (Texture)(object)val3, (ScaleMode)2);
		}
		Rect val4 = default(Rect);
		((Rect)(ref val4))..ctor(x + 26f, y + 200f, w - 52f, 32f);
		Fill(val4, new Color(val.r, val.g, val.b, 0.22f));
		GUI.Label(val4, RarityName(hexDef.R), rarityLbl);
		GUI.Label(new Rect(x + 10f, y + 240f, w - 20f, 34f), hexDef.Name, name);
		GUI.Label(new Rect(x + 26f, y + 284f, w - 52f, 90f), hexDef.Desc, desc);
		if (GUI.Button(new Rect(x + 60f, y + h - 62f, w - 120f, 44f), "选择", btn))
		{
			Pick(idx);
		}
	}

	private static void DeleteList(Rect r)
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
		Rect r2 = default(Rect);
		((Rect)(ref r2))..ctor(((Rect)(ref r)).x + 820f, ((Rect)(ref r)).y + 104f, 390f, 440f);
		Fill(r2, new Color(0.06f, 0.07f, 0.11f, 0.98f));
		Outline(r2, new Color(0.85f, 0.35f, 0.35f, 0.95f), 2);
		GUI.Label(new Rect(((Rect)(ref r2)).x, ((Rect)(ref r2)).y + 8f, ((Rect)(ref r2)).width, 26f), "选择要删除的海克斯", rarityLbl);
		Rect val = default(Rect);
		for (int i = 0; i < HexState.Owned.Count; i++)
		{
			HexDef hexDef = Catalog.Get(HexState.Owned[i]);
			((Rect)(ref val))..ctor(((Rect)(ref r2)).x + 12f, ((Rect)(ref r2)).y + 44f + (float)(i * 38), ((Rect)(ref r2)).width - 24f, 34f);
			if (GUI.Button(val, i + 1 + ". " + ((hexDef != null) ? hexDef.Name : HexState.Owned[i]), btn))
			{
				HexState.Owned.RemoveAt(i);
				HexState.DeleteUsed = true;
				CancelMode = false;
				HexState.Save();
				Effects.Tick();
				Plugin.Log.LogInfo((object)("deleted a hex, owned=" + HexState.Owned.Count));
				break;
			}
		}
	}

	internal static void Fill(Rect r, Color c)
	{
		//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_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		Color color = GUI.color;
		GUI.color = c;
		GUI.DrawTexture(r, (Texture)(object)panelTex);
		GUI.color = color;
	}

	internal static void FillGrad(Rect r, Color top, Color bottom)
	{
		//IL_0028: 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_0034: 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_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		int num = Math.Max(2, (int)(((Rect)(ref r)).height / 4f));
		Color c = default(Color);
		for (int i = 0; i < num; i++)
		{
			float num2 = (float)i / (float)(num - 1);
			((Color)(ref c))..ctor(top.r + (bottom.r - top.r) * num2, top.g + (bottom.g - top.g) * num2, top.b + (bottom.b - top.b) * num2, top.a + (bottom.a - top.a) * num2);
			Fill(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y + ((Rect)(ref r)).height * (float)i / (float)num, ((Rect)(ref r)).width, ((Rect)(ref r)).height / (float)num + 1f), c);
		}
	}

	internal static void Outline(Rect r, Color c)
	{
		//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)
		Outline(r, c, 1);
	}

	internal static void Outline(Rect r, Color c, int w)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to inv