Decompiled source of IcarusBoost v1.0.0

IcarusBoost.dll

Decompiled 6 hours ago
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyCompany("Loki Moon Labs")]
[assembly: InternalsVisibleTo("IcarusBoost.Tests")]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyTitle("Icarus Boost")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace LokiMoonLabs.IcarusBoost;

[HarmonyPatch(typeof(MechaForge), "GameTick")]
internal static class CraftingProgress
{
	internal static int Add(int current, float progress)
	{
		if (Plugin.Options == null || !Plugin.Options.Enabled.Value)
		{
			return current + (int)progress;
		}
		if (float.IsNaN(progress) || float.IsInfinity(progress) || progress < 0f)
		{
			return current;
		}
		return (int)Math.Max(-2147483648.0, Math.Min(2147483647.0, (double)current + Math.Truncate(progress)));
	}

	[HarmonyTranspiler]
	internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> source)
	{
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Expected O, but got Unknown
		List<CodeInstruction> list = new List<CodeInstruction>(source);
		int num = 0;
		for (int i = 0; i + 2 < list.Count; i++)
		{
			if (list[i].opcode == OpCodes.Conv_I4 && list[i + 1].opcode == OpCodes.Add && CodeInstructionExtensions.StoresField(list[i + 2], AccessTools.Field(typeof(ForgeTask), "tick")))
			{
				CodeInstruction val = new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(CraftingProgress), "Add", (Type[])null, (Type[])null));
				val.labels.AddRange(list[i].labels);
				val.labels.AddRange(list[i + 1].labels);
				val.blocks.AddRange(list[i].blocks);
				val.blocks.AddRange(list[i + 1].blocks);
				list[i] = val;
				list.RemoveAt(i + 1);
				num++;
			}
		}
		if (num != 1)
		{
			throw new InvalidOperationException("Unsupported crafting progress IL: " + num);
		}
		return list;
	}
}
[HarmonyPatch(typeof(PlayerController), "ApplyLocalForce")]
internal static class FlightAltitude
{
	internal static bool Finite(double value)
	{
		if (!double.IsNaN(value))
		{
			return !double.IsInfinity(value);
		}
		return false;
	}

	internal static bool Eligible(bool enabled, EMovementState current, EMovementState next, double nativeWalk, double boostedWalk, double energy, bool gas)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Invalid comparison between Unknown and I4
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Invalid comparison between Unknown and I4
		if (enabled && (int)current == 2 && (int)next == 2 && Finite(nativeWalk) && nativeWalk > 0.0 && Finite(boostedWalk) && boostedWalk > nativeWalk && Finite(energy))
		{
			return energy >= (double)(gas ? 120000000 : 10000);
		}
		return false;
	}

	internal static bool TryCorrection(double radius, double targetRadius, double horizontal, double radial, double force, double dt, out double correction)
	{
		correction = 0.0;
		if (!Finite(radius) || !Finite(targetRadius) || !Finite(horizontal) || !Finite(radial) || !Finite(force) || !Finite(dt) || radius < 10.0 || targetRadius < 10.0 || horizontal < 0.0 || dt < 0.016666566666666667 || dt > 0.050001)
		{
			return false;
		}
		double num = Math.Max(-20.0, Math.Min(20.0, (targetRadius - radius) * 2.0));
		double num2 = radius + num * dt;
		double num3 = horizontal * dt;
		double num4 = num2 * num2 - num3 * num3;
		if (num4 <= 0.0 || !Finite(num4))
		{
			return false;
		}
		double num5 = (num2 - radius) / dt - num3 * num3 / (dt * (Math.Sqrt(num4) + num2));
		double num6 = (num5 - radial) / dt - force;
		if (!Finite(num6) || Math.Abs(num6) > 12000.0)
		{
			return false;
		}
		correction = num6;
		return true;
	}

	[HarmonyPriority(0)]
	[HarmonyPrefix]
	internal static void Prefix(PlayerController __instance, ref VectorLF3 ____lForce)
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Invalid comparison between Unknown and I4
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Invalid comparison between Unknown and I4
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Invalid comparison between Unknown and I4
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: 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_0100: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		//IL_0133: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01de: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
		if (Plugin.Options == null || !Plugin.Options.Enabled.Value || (Object)(object)__instance == (Object)null)
		{
			return;
		}
		Player player = __instance.player;
		if (player == null || !player.isAlive || (int)player.movementState != 2 || (int)__instance.movementStateInFrame != 2 || player.planetData == null)
		{
			return;
		}
		Mecha mecha = player.mecha;
		PlayerMove_Fly actionFly = __instance.actionFly;
		if (mecha == null || actionFly == null || !Eligible(enabled: true, player.movementState, __instance.movementStateInFrame, mecha.walkSpeed, Modifiers.FlightWalk(mecha.walkSpeed), mecha.coreEnergy, (int)player.planetData.type == 5))
		{
			return;
		}
		Vector3 position = player.position;
		double num = ((Vector3)(ref position)).magnitude;
		if (!Finite(num) || num < 10.0)
		{
			return;
		}
		Vector3 val = position / (float)num;
		double num2 = Math.Max(1.0 / 60.0, Math.Min(0.05, Time.fixedDeltaTime));
		Vector3 velocity = __instance.velocity;
		double radial = Vector3.Dot(velocity, val);
		Vector3 val2 = velocity + VectorLF3.op_Implicit(____lForce * num2);
		double num3 = Vector3.Dot(val2, val);
		Vector3 val3 = val2 - val * (float)num3;
		double num4 = ((Vector3)(ref val3)).magnitude;
		if (!(num4 <= (double)mecha.walkSpeed * 2.5) && !(num4 > 504.0))
		{
			double force = ____lForce.x * (double)val.x + ____lForce.y * (double)val.y + ____lForce.z * (double)val.z;
			if (TryCorrection(num, player.planetData.realRadius + actionFly.targetAltitude, num4, radial, force, num2, out var correction))
			{
				____lForce += VectorLF3.op_Implicit(val * (float)correction);
			}
		}
	}
}
internal static class LegacyCleanup
{
	private static bool Valid(float value)
	{
		if (value > 0f && !float.IsNaN(value))
		{
			return !float.IsInfinity(value);
		}
		return false;
	}

	private static bool ValidCost(double value)
	{
		if (value >= 0.0 && !double.IsNaN(value))
		{
			return !double.IsInfinity(value);
		}
		return false;
	}

	private static bool Near(float actual, double expected)
	{
		return Math.Abs((double)actual - expected) <= Math.Max(1E-05, Math.Abs(expected) * 1E-05);
	}

	internal static bool Apply(Mecha mecha, ModeConfig baseline)
	{
		if (mecha == null || (Object)(object)baseline == (Object)null || !Valid(baseline.mechaMiningSpeed) || !Valid(baseline.mechaReplicateSpeed) || !Valid(baseline.mechaWalkSpeed) || !ValidCost(baseline.droneEjectEnergy) || !ValidCost(baseline.droneEnergyPerMeter))
		{
			return false;
		}
		if (!Valid(mecha.miningSpeed) || !Valid(mecha.replicateSpeed) || !Valid(mecha.walkSpeed) || !Near(mecha.miningSpeed, (double)baseline.mechaMiningSpeed * 10.0) || (double)mecha.replicateSpeed + 1E-05 < (double)baseline.mechaReplicateSpeed * 10.0 || (double)mecha.walkSpeed + 1E-05 < (double)baseline.mechaWalkSpeed * 2.0 || mecha.droneEjectEnergy != 0.0 || mecha.droneEnergyPerMeter != 0.0)
		{
			return false;
		}
		float num = (float)((double)mecha.replicateSpeed - (double)baseline.mechaReplicateSpeed * 9.0);
		float num2 = mecha.walkSpeed - baseline.mechaWalkSpeed;
		if (!Valid(num) || !Valid(num2))
		{
			return false;
		}
		mecha.miningSpeed = baseline.mechaMiningSpeed;
		mecha.replicateSpeed = num;
		mecha.walkSpeed = num2;
		mecha.droneEjectEnergy = baseline.droneEjectEnergy;
		mecha.droneEnergyPerMeter = baseline.droneEnergyPerMeter;
		return true;
	}
}
[HarmonyPatch(typeof(PlayerAction_Mine), "GameTick")]
internal static class MiningPerformance
{
	[ThreadStatic]
	private static int depth;

	internal static bool Active
	{
		get
		{
			if (Plugin.Options != null)
			{
				return Plugin.Options.Enabled.Value;
			}
			return false;
		}
	}

	internal static bool Muted => depth > 0;

	[HarmonyPrefix]
	internal static void Prefix(out bool __state)
	{
		__state = Active;
		if (__state)
		{
			depth++;
		}
	}

	[HarmonyFinalizer]
	internal static void Finalizer(bool __state)
	{
		if (__state)
		{
			depth--;
		}
	}

	internal static int BatchCount(int ticks, int miningTime, int amount, bool infinite)
	{
		long num = (long)miningTime * 10000L;
		if (ticks <= 0 || num <= 0 || num > int.MaxValue || amount <= 0)
		{
			return 0;
		}
		long num2 = ticks / num;
		if (!infinite)
		{
			num2 = Math.Min(num2, amount);
		}
		return (int)Math.Max(0L, num2 - 1);
	}

	internal static void BatchBeforeNative(PlayerAction_Mine action)
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Invalid comparison between Unknown and I4
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Invalid comparison between Unknown and I4
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Expected I4, but got Unknown
		if (!Active || action == null || ((PlayerAction)action).player == null || (int)action.miningType != 2)
		{
			return;
		}
		PlanetFactory factory = ((PlayerAction)action).player.factory;
		int miningId = action.miningId;
		if (factory == null || miningId <= 0 || miningId >= factory.veinPool.Length)
		{
			return;
		}
		VeinData val = factory.veinPool[miningId];
		if (val.id != miningId || (int)val.type == 7)
		{
			return;
		}
		VeinProto val2 = ((ProtoSet<VeinProto>)(object)LDB.veins).Select((int)val.type);
		if (val2 == null)
		{
			return;
		}
		bool isInfiniteResource = GameMain.data.gameDesc.isInfiniteResource;
		int num = BatchCount(action.miningTick, val2.MiningTime, val.amount, isInfiniteResource);
		if (num != 0)
		{
			int num2 = ((PlayerAction)action).player.TryAddItemToPackage(val2.MiningItem, num, 0, true, 0, false);
			action.AddProductionStat(val2.MiningItem, num, factory);
			((PlayerAction)action).controller.gameData.history.AddFeatureValue(2200000 + val2.MiningItem, num);
			if (!isInfiniteResource)
			{
				ref VeinData reference = ref factory.veinPool[miningId];
				reference.amount -= num;
				ref VeinGroup reference2 = ref factory.veinGroups[val.groupIndex];
				reference2.amount -= num;
			}
			action.miningTick -= (int)((long)num * (long)val2.MiningTime * 10000);
			if (num2 > 0)
			{
				UIItemup.Up(val2.MiningItem, num2);
			}
		}
	}

	internal static void Effect(int id, Vector3 pos, Quaternion rot)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		if (!Active)
		{
			VFEffectEmitter.Emit(id, pos, rot);
		}
	}

	internal static void Popup(int item, int count, Vector3 pos, int index)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		if (!Active)
		{
			UIRealtimeTip.PopupItemGet(item, count, pos, index);
		}
	}

	[HarmonyTranspiler]
	internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> source)
	{
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Expected O, but got Unknown
		//IL_016a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0174: Expected O, but got Unknown
		List<CodeInstruction> list = new List<CodeInstruction>(source);
		int num = 0;
		int num2 = 0;
		int num3 = 0;
		for (int i = 0; i < list.Count; i++)
		{
			MethodInfo methodInfo = list[i].operand as MethodInfo;
			if (methodInfo == null)
			{
				continue;
			}
			if (methodInfo.DeclaringType == typeof(PlayerAction_Mine) && methodInfo.Name == "set_percent" && i + 1 < list.Count && list[i + 1].opcode == OpCodes.Br)
			{
				bool flag = false;
				for (int j = Math.Max(0, i - 10); j < i; j++)
				{
					FieldInfo fieldInfo = list[j].operand as FieldInfo;
					if (fieldInfo != null && fieldInfo.DeclaringType == typeof(VeinProto) && fieldInfo.Name == "MiningTime")
					{
						flag = true;
					}
				}
				if (flag)
				{
					CodeInstruction val = new CodeInstruction(OpCodes.Ldarg_0, (object)null);
					val.labels.AddRange(list[i + 1].labels);
					list[i + 1].labels.Clear();
					list.Insert(i + 1, val);
					list.Insert(i + 2, new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(MiningPerformance), "BatchBeforeNative", (Type[])null, (Type[])null)));
					num++;
				}
			}
			if (methodInfo.DeclaringType == typeof(VFEffectEmitter) && methodInfo.Name == "Emit" && methodInfo.GetParameters().Length == 3)
			{
				list[i].operand = AccessTools.Method(typeof(MiningPerformance), "Effect", (Type[])null, (Type[])null);
				num2++;
			}
			if (methodInfo.DeclaringType == typeof(UIRealtimeTip) && methodInfo.Name == "PopupItemGet")
			{
				list[i].operand = AccessTools.Method(typeof(MiningPerformance), "Popup", (Type[])null, (Type[])null);
				num3++;
			}
		}
		if (num != 1 || num2 != 3 || num3 != 3)
		{
			throw new InvalidOperationException("Unsupported hand-mining IL: batch=" + num + ", effects=" + num2 + ", popups=" + num3);
		}
		return list;
	}
}
[HarmonyPatch]
internal static class MiningAudio
{
	[HarmonyTargetMethods]
	internal static IEnumerable<MethodBase> Targets()
	{
		foreach (MethodInfo method in AccessTools.GetDeclaredMethods(typeof(VFAudio)))
		{
			ParameterInfo[] p = method.GetParameters();
			if (method.Name == "Create" && method.IsStatic && method.ReturnType == typeof(VFAudio) && p.Length == 7 && (p[0].ParameterType == typeof(int) || p[0].ParameterType == typeof(string)))
			{
				yield return method;
			}
		}
	}

	[HarmonyPrefix]
	internal static bool Prefix()
	{
		return !MiningPerformance.Muted;
	}
}
[HarmonyPatch]
internal static class Consumers
{
	internal static readonly Dictionary<string, string> Fields = new Dictionary<string, string>
	{
		{ "miningSpeed", "Mining" },
		{ "replicateSpeed", "Crafting" },
		{ "walkSpeed", "Walking" },
		{ "jumpSpeed", "Jump" },
		{ "droneEjectEnergy", "Launch" }
	};

	internal static IEnumerable<MethodBase> Targets()
	{
		string[] types = new string[13]
		{
			"PlayerAction_Mine", "PlayerMove_Drift", "PlayerMove_Drift", "PlayerMove_Fly", "PlayerMove_Fly", "PlayerMove_Walk", "PlayerMove_Walk", "PlayerController", "Mecha", "MechaForge",
			"UITechTree", "PlayerMove_Walk", "PlayerAnimator"
		};
		string[] methods = new string[13]
		{
			"GameTick", "GameTick", "UseDriftEnergy", "GameTick", "UseFlyEnergy", "GameTick", "UseWalkEnergy", "HandleCollision", "CheckEjectConstructionDroneCondition", "GameTick",
			"RefreshDataValueText", "Init", "CalculateJumpWeights"
		};
		for (int i = 0; i < types.Length; i++)
		{
			Type type = typeof(Mecha).Assembly.GetType(types[i]);
			MethodInfo method = ((type == null) ? null : AccessTools.Method(type, methods[i], (Type[])null, (Type[])null));
			if (method == null)
			{
				throw new MissingMethodException(types[i], methods[i]);
			}
			yield return method;
		}
		Type replacement = AccessTools.TypeByName("GalacticScale.PatchOnPlayerMove_Fly");
		if (replacement != null)
		{
			MethodInfo method2 = AccessTools.Method(replacement, "GameTick", new Type[1] { typeof(PlayerMove_Fly).MakeByRefType() }, (Type[])null);
			if (method2 == null || method2.ReturnType != typeof(bool))
			{
				throw new MissingMethodException(replacement.FullName, "GameTick(ref PlayerMove_Fly)");
			}
			yield return method2;
		}
	}

	[HarmonyTargetMethods]
	private static IEnumerable<MethodBase> TargetMethods()
	{
		return Targets();
	}

	[HarmonyTranspiler]
	internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> source, MethodBase __originalMethod)
	{
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: Expected O, but got Unknown
		List<CodeInstruction> list = new List<CodeInstruction>();
		int num = 0;
		foreach (CodeInstruction item in source)
		{
			list.Add(item);
			FieldInfo fieldInfo = item.operand as FieldInfo;
			if (item.opcode == OpCodes.Ldfld && fieldInfo != null && fieldInfo.DeclaringType == typeof(Mecha) && Fields.TryGetValue(fieldInfo.Name, out var value))
			{
				if (fieldInfo.Name == "walkSpeed" && __originalMethod != null && (__originalMethod.DeclaringType == typeof(PlayerMove_Fly) || __originalMethod.DeclaringType.FullName == "GalacticScale.PatchOnPlayerMove_Fly"))
				{
					value = "FlightWalk";
				}
				list.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Modifiers), value, (Type[])null, (Type[])null)));
				num++;
			}
		}
		if (num == 0)
		{
			throw new InvalidOperationException("No expected mecha stat reads in " + __originalMethod);
		}
		return list;
	}
}
[HarmonyPatch(typeof(Mecha), "UseEnergy")]
internal static class EnergyUse
{
	[HarmonyPriority(0)]
	[HarmonyPrefix]
	internal static void Prefix(ref double __0)
	{
		__0 = Modifiers.Energy(__0);
	}
}
[HarmonyPatch]
internal static class DroneTravel
{
	[HarmonyTargetMethod]
	internal static MethodBase Target()
	{
		foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(typeof(DroneComponent)))
		{
			ParameterInfo[] parameters = declaredMethod.GetParameters();
			if (declaredMethod.Name == "InternalUpdate" && parameters.Length == 10 && parameters[5].ParameterType == typeof(double).MakeByRefType() && parameters[6].ParameterType == typeof(double).MakeByRefType() && parameters[7].ParameterType == typeof(double) && parameters[9].ParameterType == typeof(float).MakeByRefType())
			{
				return declaredMethod;
			}
		}
		throw new MissingMethodException("Icarus DroneComponent.InternalUpdate overload");
	}

	[HarmonyPrefix]
	internal static void Prefix(ref DroneComponent __instance, ref double __7)
	{
		if (__instance.owner == 0)
		{
			__7 = Modifiers.Travel(__7);
		}
	}
}
[BepInIncompatibility("dsp.mechboost.btn")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("LokiMoonLabs.IcarusBoost", "Icarus Boost", "1.0.0")]
public sealed class Plugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(GameMain), "Begin")]
	private static class Loaded
	{
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix()
		{
			if (Options == null || !Options.Enabled.Value || GameMain.mainPlayer == null)
			{
				return;
			}
			Mecha mecha = GameMain.mainPlayer.mecha;
			if (mecha == null)
			{
				return;
			}
			float miningSpeed = mecha.miningSpeed;
			float replicateSpeed = mecha.replicateSpeed;
			float walkSpeed = mecha.walkSpeed;
			bool flag = LegacyCleanup.Apply(mecha, Configs.freeMode);
			if (!((Object)(object)instance == (Object)null))
			{
				if (flag)
				{
					((BaseUnityPlugin)instance).Logger.LogInfo((object)string.Format(CultureInfo.InvariantCulture, "Removed saved DSP MechBoost starting bonuses; research retained. Mining {0}->{1}; crafting {2}->{3}; walking {4}->{5}; native drone energy fields restored. Configured runtime multipliers now apply.", miningSpeed, mecha.miningSpeed, replicateSpeed, mecha.replicateSpeed, walkSpeed, mecha.walkSpeed));
				}
				else
				{
					((BaseUnityPlugin)instance).Logger.LogInfo((object)"No complete saved DSP MechBoost pattern found; current saved stats were retained. Configured runtime multipliers apply.");
				}
			}
		}
	}

	public const string Guid = "LokiMoonLabs.IcarusBoost";

	internal static Settings Options;

	private static Plugin instance;

	private Harmony harmony;

	private void Awake()
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Expected O, but got Unknown
		Options = new Settings(((BaseUnityPlugin)this).Config);
		((BaseUnityPlugin)this).Config.Save();
		instance = this;
		harmony = new Harmony("LokiMoonLabs.IcarusBoost");
		try
		{
			harmony.PatchAll(typeof(Plugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Icarus Boost ready. Config: " + ((BaseUnityPlugin)this).Config.ConfigFilePath));
		}
		catch (Exception ex)
		{
			harmony.UnpatchSelf();
			Options = null;
			((BaseUnityPlugin)this).Logger.LogError((object)("Icarus Boost could not install its patches; all of its patches were removed. " + ex));
		}
	}

	private void OnDestroy()
	{
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		if ((Object)(object)instance == (Object)(object)this)
		{
			instance = null;
			Options = null;
		}
	}
}
internal sealed class Settings
{
	internal const float MiningMaximum = 500f;

	internal const float CraftingMaximum = 1000f;

	internal const float WalkingMaximum = 20f;

	internal const float JumpMaximum = 100f;

	internal const float FlightMaximum = 20f;

	internal const float EnergyMaximum = 5f;

	internal const float MiningCeiling = 20000f;

	internal const float CraftingCeiling = 10000f;

	internal const float WalkingCeiling = 240f;

	internal const float JumpCeiling = 120f;

	internal const float FlightCeiling = 480f;

	internal readonly ConfigEntry<bool> Enabled;

	internal readonly ConfigEntry<float> Mining;

	internal readonly ConfigEntry<float> Crafting;

	internal readonly ConfigEntry<float> Walking;

	internal readonly ConfigEntry<float> JumpHeight;

	internal readonly ConfigEntry<float> Flight;

	internal readonly ConfigEntry<float> Energy;

	internal readonly ConfigEntry<float> Launch;

	internal readonly ConfigEntry<float> Travel;

	internal Settings(ConfigFile file)
	{
		Enabled = file.Bind<bool>("General", "Enabled", true, "Master switch for all boosts, quiet batched mining and flight altitude stabilization. Also enables one-time cleanup of recognizable saved DSP MechBoost bonuses while preserving research. Restart the game after changing this file.");
		Mining = Number(file, "Speeds", "MiningSpeedMultiplier", 500f, 0.1f, 500f, "Icarus hand-mining speed. 1 = native speed; 500 = maximum multiplier. Does not affect mining machines. Ore extraction is batched; mining sounds, particle bursts and floating pickup popups are suppressed. Item-count feedback remains. Added speed is capped at 20000 native stat units.");
		Crafting = Number(file, "Speeds", "CraftingSpeedMultiplier", 1000f, 0.1f, 1000f, "Icarus replicator speed, including researched crafting upgrades. 1 = native speed; 1000 = maximum multiplier. Keeps recipe ingredients, research and normal completion rules. Added speed is capped at 10000 native stat units; final queue progress is protected against integer overflow.");
		Walking = Number(file, "Speeds", "WalkingSpeedMultiplier", 20f, 0.25f, 20f, "Icarus walking speed. 1 = native speed; 20 = maximum multiplier. Also affects native movement calculations that use walking speed. Added ground speed is capped at 240 m/s.");
		JumpHeight = Number(file, "Movement", "JumpHeightMultiplier", 100f, 1f, 100f, "Approximate jump height. 1 = native height; 100 = maximum multiplier. Launch speed uses the square root of this value and is capped at 120 m/s for added boosts. Terrain, gravity and transitions into flight affect actual height.");
		Flight = Number(file, "Movement", "FlightSpeedMultiplier", 20f, 0.25f, 20f, "Extra horizontal speed in planetary flight. 1 = no extra flight boost; 20 = maximum multiplier. Combines with WalkingSpeedMultiplier, up to 480 m/s added flight speed. Altitude stabilization follows the normal target height, including Galactic Scale flight. Manual ascent/descent, landing and space transitions remain available. Does not change sailing or warp speed.");
		Energy = Number(file, "Energy", "MechaEnergyUseMultiplier", 0.5f, 0f, 5f, "Multiplier for costs routed through the native Mecha.UseEnergy method. 1 is normal, 0.5 is half and 0 is free. Other energy paths are not all routed through this method.");
		Launch = Number(file, "Energy", "DroneLaunchEnergyMultiplier", 0f, 0f, 5f, "Icarus construction-drone launch energy requirement multiplier. 0 removes the requirement, 1 keeps the saved/native amount. Does not change battlefield-base drones.");
		Travel = Number(file, "Energy", "DroneTravelEnergyMultiplier", 0f, 0f, 5f, "Icarus construction-drone travel energy multiplier. 0 is free travel and 1 is normal. Does not change battlefield-base drones or drone repair energy.");
	}

	private static ConfigEntry<float> Number(ConfigFile file, string section, string key, float fallback, float minimum, float maximum, string description)
	{
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Expected O, but got Unknown
		string text = ((section == "Energy") ? string.Empty : " Existing native/saved speeds above an added-speed cap are retained.");
		ConfigEntry<float> val = file.Bind<float>(section, key, fallback, new ConfigDescription(description + text + " Restart after editing this file.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(minimum, maximum), new object[0]));
		val.Value = Bound(val.Value, fallback, minimum, maximum);
		return val;
	}

	internal static float Bound(float value, float fallback, float minimum, float maximum)
	{
		if (!float.IsNaN(value) && !float.IsInfinity(value))
		{
			return Math.Max(minimum, Math.Min(maximum, value));
		}
		return fallback;
	}
}
internal static class Modifiers
{
	private static bool Active
	{
		get
		{
			if (Plugin.Options != null)
			{
				return Plugin.Options.Enabled.Value;
			}
			return false;
		}
	}

	internal static float Mining(float value)
	{
		if (!Active)
		{
			return value;
		}
		return LimitedSpeed(value, Settings.Bound(Plugin.Options.Mining.Value, 500f, 0.1f, 500f), 20000f);
	}

	internal static float Crafting(float value)
	{
		if (!Active)
		{
			return value;
		}
		return LimitedSpeed(value, Settings.Bound(Plugin.Options.Crafting.Value, 1000f, 0.1f, 1000f), 10000f);
	}

	internal static float Walking(float value)
	{
		if (!Active)
		{
			return value;
		}
		return LimitedSpeed(value, Settings.Bound(Plugin.Options.Walking.Value, 20f, 0.25f, 20f), 240f);
	}

	internal static float Jump(float value)
	{
		if (!Active)
		{
			return value;
		}
		return LimitedSpeed(value, (float)Math.Sqrt(Settings.Bound(Plugin.Options.JumpHeight.Value, 100f, 1f, 100f)), 120f);
	}

	internal static float FlightWalk(float value)
	{
		if (!Active)
		{
			return value;
		}
		float num = Walking(value);
		float num2 = Settings.Bound(Plugin.Options.Flight.Value, 20f, 0.25f, 20f);
		if (value <= 0f || float.IsNaN(value) || float.IsInfinity(value))
		{
			return value;
		}
		return (float)Math.Min(Math.Max(value, 192f), (double)num * (double)num2);
	}

	internal static double Launch(double value)
	{
		if (!Active)
		{
			return value;
		}
		return Cost(value, Settings.Bound(Plugin.Options.Launch.Value, 0f, 0f, 5f));
	}

	internal static double Travel(double value)
	{
		if (!Active)
		{
			return value;
		}
		return Cost(value, Settings.Bound(Plugin.Options.Travel.Value, 0f, 0f, 5f));
	}

	internal static double Energy(double value)
	{
		if (!Active)
		{
			return value;
		}
		return Cost(value, Settings.Bound(Plugin.Options.Energy.Value, 0.5f, 0f, 5f));
	}

	internal static float LimitedSpeed(float value, float multiplier, float ceiling)
	{
		return Math.Min(Speed(value, multiplier), Math.Max(value, ceiling));
	}

	internal static float Speed(float value, float multiplier)
	{
		if (value <= 0f || float.IsNaN(value) || float.IsInfinity(value) || float.IsNaN(multiplier) || float.IsInfinity(multiplier) || multiplier < 0f)
		{
			return value;
		}
		return (float)Math.Min(8.5070586659632215E+37, (double)value * (double)multiplier);
	}

	internal static double Cost(double value, float multiplier)
	{
		if (value <= 0.0 || double.IsNaN(value) || double.IsInfinity(value) || float.IsNaN(multiplier) || float.IsInfinity(multiplier) || multiplier < 0f)
		{
			return value;
		}
		return Math.Min(4.4942328371557893E+307, value * (double)multiplier);
	}
}