Decompiled source of SacrificeHelper v2.4.8

SacrificeHelper.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BTD_Mod_Helper;
using BTD_Mod_Helper.Api;
using BTD_Mod_Helper.Api.Components;
using BTD_Mod_Helper.Api.Data;
using BTD_Mod_Helper.Api.Helpers;
using BTD_Mod_Helper.Api.ModOptions;
using BTD_Mod_Helper.Api.Towers;
using BTD_Mod_Helper.Extensions;
using HarmonyLib;
using Il2Cpp;
using Il2CppAssets.Scripts.Data.ParagonData;
using Il2CppAssets.Scripts.Models;
using Il2CppAssets.Scripts.Models.Entities;
using Il2CppAssets.Scripts.Models.TowerSets;
using Il2CppAssets.Scripts.Models.Towers;
using Il2CppAssets.Scripts.Models.Towers.Behaviors;
using Il2CppAssets.Scripts.Models.Towers.Mutators;
using Il2CppAssets.Scripts.Models.Towers.Upgrades;
using Il2CppAssets.Scripts.Simulation.Objects;
using Il2CppAssets.Scripts.Simulation.Towers;
using Il2CppAssets.Scripts.Simulation.Towers.Behaviors;
using Il2CppAssets.Scripts.Simulation.Towers.Mutators;
using Il2CppAssets.Scripts.Unity;
using Il2CppAssets.Scripts.Unity.Bridge;
using Il2CppAssets.Scripts.Unity.UI_New.InGame;
using Il2CppAssets.Scripts.Unity.UI_New.InGame.TowerSelectionMenu;
using Il2CppAssets.Scripts.Unity.UI_New.InGame.TowerSelectionMenu.TowerSelectionMenuThemes;
using Il2CppAssets.Scripts.Unity.UI_New.Popups;
using Il2CppAssets.Scripts.Unity.UI_New.Utils;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.IO;
using Il2CppTMPro;
using MelonLoader;
using Microsoft.CodeAnalysis;
using SacrificeHelper;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(SacrificeHelperMod), "Sacrifice Helper", "2.4.8", "doombubbles", null)]
[assembly: MelonGame("Ninja Kiwi", "BloonsTD6")]
[assembly: MelonGame("Ninja Kiwi", "BloonsTD6-Epic")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("SacrificeHelper")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+34462f8fb877883dbd7bd25d7dcae74ab212ad1f")]
[assembly: AssemblyProduct("SacrificeHelper")]
[assembly: AssemblyTitle("SacrificeHelper")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class ExtensionMarkerAttribute : Attribute
	{
		private readonly string <Name>k__BackingField;

		public string Name => <Name>k__BackingField;

		public ExtensionMarkerAttribute(string name)
		{
			<Name>k__BackingField = name;
		}
	}
}
namespace SacrificeHelper
{
	public static class ModHelperData
	{
		public const string WorksOnVersion = "56.0";

		public const string Version = "2.4.8";

		public const string Name = "Sacrifice Helper";

		public const string Description = "Adds more UI information when doing Temple and Paragon sacrifices so you know exactly what you'll get.\n\nAlso adds settings for customizing how sacrifices happen, such as Auto Sacrifice mode.";

		public const string RepoOwner = "doombubbles";

		public const string PrevRepoName = "sacrifice-helper";

		public const string RepoName = "SacrificeHelper";
	}
	public class SacrificeHelperMod : BloonsTD6Mod
	{
		[HarmonyPatch(typeof(MonkeyTemple), "StartSacrifice")]
		public class MonkeyTemple_StartSacrifice
		{
			[HarmonyPrefix]
			public static bool Prefix()
			{
				return !templeSacrificesOff && AutoSacrificeMode == AutoSacrificeMode.Off;
			}

			[HarmonyPostfix]
			public static void Postfix(MonkeyTemple __instance)
			{
				//IL_008e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0093: Unknown result type (might be due to invalid IL or missing references)
				//IL_0099: Unknown result type (might be due to invalid IL or missing references)
				//IL_009c: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b2: Expected I4, but got Unknown
				//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b7: Invalid comparison between Unknown and I4
				if (AutoSacrificeMode == AutoSacrificeMode.Off)
				{
					return;
				}
				__instance.checkTCBOO = __instance.monkeyTempleModel.checkForThereCanOnlyBeOne;
				if (__instance.selectedTowers == null)
				{
					Dictionary<TowerSet, float> val = (__instance.selectedTowers = new Dictionary<TowerSet, float>());
				}
				TowerMutator val4 = default(TowerMutator);
				foreach (TempleTowerMutatorGroup item in MonoLinqHelper.ToArray<TempleTowerMutatorGroup>(((RootBehavior)__instance).entity.GetBehaviorsInDependants<TempleTowerMutatorGroup>()))
				{
					bool flag = __instance.monkeyTempleModel.templeId != "TrueTemple";
					bool flag2 = flag;
					if (flag2)
					{
						AutoSacrificeMode autoSacrificeMode = AutoSacrificeMode;
						TowerSet towerSet = item.templeTowerMutatorGroupModel.towerSet;
						if (1 == 0)
						{
						}
						AutoSacrificeMode autoSacrificeMode2;
						switch (towerSet - 1)
						{
						default:
							if ((int)towerSet != 8)
							{
								goto case 2;
							}
							autoSacrificeMode2 = AutoSacrificeMode.Sacrifice2221;
							break;
						case 0:
							autoSacrificeMode2 = AutoSacrificeMode.Sacrifice1222;
							break;
						case 1:
							autoSacrificeMode2 = AutoSacrificeMode.Sacrifice2122;
							break;
						case 3:
							autoSacrificeMode2 = AutoSacrificeMode.Sacrifice2212;
							break;
						case 2:
							autoSacrificeMode2 = AutoSacrificeMode.Off;
							break;
						}
						if (1 == 0)
						{
						}
						flag2 = autoSacrificeMode == autoSacrificeMode2;
					}
					if (flag2)
					{
						continue;
					}
					List<RootBehavior> val3 = new List<RootBehavior>();
					Entity entity = ((RootBehavior)__instance).entity;
					Model[] array = (Model[])(object)Il2CppReferenceArrayExt.ToArray<TowerMutatorModel>(((TowerMutatorGroupModel)item.templeTowerMutatorGroupModel).mutators);
					entity.AddBehaviorsOrUpdateModels(val3, Il2CppReferenceArray<Model>.op_Implicit(array));
					Enumerator<RootBehavior> enumerator2 = val3.GetEnumerator();
					while (enumerator2.MoveNext())
					{
						RootBehavior current2 = enumerator2.Current;
						if (Il2CppSystemObjectExt.Is<TowerMutator>((Il2CppObjectBase)(object)current2, ref val4) && val4.EvaluateConditional())
						{
							__instance.mutatorsToApply.Add(val4.mutator);
						}
					}
				}
			}
		}

		[HarmonyPatch(typeof(MonkeyTemple), "GetSaveMetaData")]
		internal static class MonkeyTemple_GetSaveMetaData
		{
			[HarmonyPrefix]
			internal static void Prefix(MonkeyTemple __instance)
			{
				if (AutoSacrificeMode == AutoSacrificeMode.Off)
				{
					return;
				}
				MonkeyTemple val = __instance;
				if (val.templeTowers == null)
				{
					Dictionary<TowerSet, float> val2 = (val.templeTowers = new Dictionary<TowerSet, float>());
				}
				if (AutoSacrificeMode != AutoSacrificeMode.Sacrifice1222)
				{
					__instance.templeTowers[(TowerSet)1] = 50001f;
				}
				if (AutoSacrificeMode != AutoSacrificeMode.Sacrifice2122)
				{
					__instance.templeTowers[(TowerSet)2] = 50001f;
				}
				if (AutoSacrificeMode != AutoSacrificeMode.Sacrifice2212)
				{
					__instance.templeTowers[(TowerSet)4] = 50001f;
				}
				if (AutoSacrificeMode != AutoSacrificeMode.Sacrifice2221)
				{
					__instance.templeTowers[(TowerSet)8] = 50001f;
				}
				if (!(__instance.monkeyTempleModel.templeId != "TrueTemple"))
				{
					val = __instance;
					if (val.trueTempleTowers == null)
					{
						Dictionary<TowerSet, float> val2 = (val.trueTempleTowers = new Dictionary<TowerSet, float>());
					}
					__instance.trueTempleTowers[(TowerSet)1] = 50001f;
					__instance.trueTempleTowers[(TowerSet)2] = 50001f;
					__instance.trueTempleTowers[(TowerSet)4] = 50001f;
					__instance.trueTempleTowers[(TowerSet)8] = 50001f;
				}
			}
		}

		private static readonly ModSettingEnum<AutoSacrificeMode> AutoSacrifice = new ModSettingEnum<AutoSacrificeMode>(AutoSacrificeMode.Off)
		{
			description = "Mode for automatically applying sacrifice benefits to temples via increasing the upgrade cost a corresponding amount instead of sacrificing nearby towers. Temple syntax is for example 2221 meaning all sacrifices are 50k except for Support on the Tier 4 sacrifice. Still works for becoming a Vengeful Temple.",
			labelFunction = (AutoSacrificeMode mode) => mode.ToString().Replace("Sacrifice", "Sacrifice ")
		};

		public static readonly ModSettingBool FourCategorySunTemples = new ModSettingBool(false)
		{
			displayName = "Four-Category Sun Temple Sacrifices",
			description = "Allows Sun Temples to benefit from all four tower category sacrifices instead of only three. Warning: When enabled, a Vengeful True Sun God requires a fully maxed 2222 Sun Temple; the base-game 2221 setup will no longer qualify.",
			icon = "080c12903611a654b8d3281aef7fe553",
			requiresRestart = true
		};

		public static readonly ModSettingDouble SliderContributionPenalty;

		public static readonly ModSettingCategory ParagonPowerMaximums;

		public static readonly ModSettingInt MaxPowerFromPops;

		public static readonly ModSettingInt MaxPowerFromCash;

		public static readonly ModSettingInt MaxPowerFromNonTier5s;

		public static readonly ModSettingInt MaxPowerFromTier5s;

		public static readonly ModSettingCategory ParagonPowerWeights;

		private static readonly ModSettingInt PopsScaleFactor;

		private static readonly ModSettingInt CashScaleFactor;

		private static readonly ModSettingInt NonTier5ScaleFactor;

		private static readonly ModSettingInt Tier5ScaleFactor;

		public static readonly ModSettingCategory TempleAlternateCosts;

		public static readonly ModSettingDouble TempleAlternateCostMod;

		public static readonly ModSettingDouble GodAlternateCostMod;

		public static bool templeSacrificesOff;

		public static AutoSacrificeMode AutoSacrificeMode => ModSettingEnum<AutoSacrificeMode>.op_Implicit(AutoSacrifice);

		public override void OnNewGameModel(GameModel result)
		{
			ParagonDegreeDataModel paragonDegreeDataModel = result.paragonDegreeDataModel;
			paragonDegreeDataModel.maxPowerFromPops = ModSettingInt.op_Implicit(MaxPowerFromPops);
			if (paragonDegreeDataModel.maxPowerFromPops < 0)
			{
				paragonDegreeDataModel.maxPowerFromPops = paragonDegreeDataModel.MaxInvestment;
			}
			paragonDegreeDataModel.maxPowerFromMoneySpent = ModSettingInt.op_Implicit(MaxPowerFromCash);
			if (paragonDegreeDataModel.maxPowerFromMoneySpent < 0)
			{
				paragonDegreeDataModel.maxPowerFromMoneySpent = paragonDegreeDataModel.MaxInvestment;
			}
			paragonDegreeDataModel.maxPowerFromNonTier5Count = ModSettingInt.op_Implicit(MaxPowerFromNonTier5s);
			if (paragonDegreeDataModel.maxPowerFromNonTier5Count < 0)
			{
				paragonDegreeDataModel.maxPowerFromNonTier5Count = paragonDegreeDataModel.MaxInvestment;
			}
			paragonDegreeDataModel.maxPowerFromTier5Count = ModSettingInt.op_Implicit(MaxPowerFromTier5s);
			if (paragonDegreeDataModel.maxPowerFromTier5Count < 0)
			{
				paragonDegreeDataModel.maxPowerFromTier5Count = paragonDegreeDataModel.MaxInvestment;
			}
			paragonDegreeDataModel.popsOverX = ModSettingInt.op_Implicit(PopsScaleFactor);
			paragonDegreeDataModel.moneySpentOverX = ModSettingInt.op_Implicit(CashScaleFactor);
			paragonDegreeDataModel.nonTier5TowersMultByX = ModSettingInt.op_Implicit(NonTier5ScaleFactor);
			paragonDegreeDataModel.tier5TowersMultByX = ModSettingInt.op_Implicit(Tier5ScaleFactor);
			paragonDegreeDataModel.paidContributionPenalty = ModSettingDouble.op_Implicit(SliderContributionPenalty);
			templeSacrificesOff = false;
			SacrificeHelperUtility.UpdateUpgradeCosts(result);
		}

		static SacrificeHelperMod()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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_0097: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Expected O, but got Unknown
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected O, but got Unknown
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected O, but got Unknown
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Expected O, but got Unknown
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Expected O, but got Unknown
			//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_0111: Expected O, but got Unknown
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Expected O, but got Unknown
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Expected O, but got Unknown
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Expected O, but got Unknown
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Expected O, but got Unknown
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Expected O, but got Unknown
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Expected O, but got Unknown
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Expected O, but got Unknown
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Expected O, but got Unknown
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Expected O, but got Unknown
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Expected O, but got Unknown
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Expected O, but got Unknown
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Expected O, but got Unknown
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Expected O, but got Unknown
			//IL_0295: 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)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Expected O, but got Unknown
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: 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_02da: Expected O, but got Unknown
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Expected O, but got Unknown
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_0320: Unknown result type (might be due to invalid IL or missing references)
			//IL_032d: Expected O, but got Unknown
			//IL_032d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0338: Unknown result type (might be due to invalid IL or missing references)
			//IL_034e: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Expected O, but got Unknown
			//IL_0363: Unknown result type (might be due to invalid IL or missing references)
			//IL_036d: Expected O, but got Unknown
			//IL_0376: Unknown result type (might be due to invalid IL or missing references)
			//IL_037b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0386: Unknown result type (might be due to invalid IL or missing references)
			//IL_039a: Expected O, but got Unknown
			//IL_039a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a7: Expected O, but got Unknown
			//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d8: Expected O, but got Unknown
			//IL_03e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0405: Expected O, but got Unknown
			//IL_0405: Unknown result type (might be due to invalid IL or missing references)
			//IL_0412: Expected O, but got Unknown
			//IL_0412: Unknown result type (might be due to invalid IL or missing references)
			//IL_041d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0428: Unknown result type (might be due to invalid IL or missing references)
			//IL_0433: Unknown result type (might be due to invalid IL or missing references)
			//IL_0443: Expected O, but got Unknown
			ModSettingDouble val = new ModSettingDouble(0.05000000074505806)
			{
				description = "The popup added in BTD6 v39 comes with a default 5% penalty to manually invested cash.\nSetting this to 0 would stop it, or negative would counteract it.",
				stepSize = 0.01f
			};
			((ModSettingNumber<double>)val).min = -0.99;
			((ModSettingNumber<double>)val).max = 1.0;
			((ModSetting)val).icon = "Ui[UpgradeContainerParagonUnlocked]";
			SliderContributionPenalty = val;
			ParagonPowerMaximums = new ModSettingCategory("Paragon Power Maximums");
			ModSettingInt val2 = new ModSettingInt(90000)
			{
				displayName = "Max Paragon Power From Pops\n(-1 for unlimited)"
			};
			((ModSettingNumber<long>)val2).min = -1L;
			((ModSettingNumber<long>)val2).max = 200000L;
			((ModSetting)val2).icon = "IngameUi[PopIcon]";
			((ModSetting)val2).category = ParagonPowerMaximums;
			MaxPowerFromPops = val2;
			ModSettingInt val3 = new ModSettingInt(60000)
			{
				displayName = "Max Paragon Power From Cash\n(-1 for unlimited)"
			};
			((ModSettingNumber<long>)val3).min = -1L;
			((ModSettingNumber<long>)val3).max = 200000L;
			((ModSetting)val3).icon = "Ui[CoinIcon]";
			((ModSetting)val3).category = ParagonPowerMaximums;
			MaxPowerFromCash = val3;
			ModSettingInt val4 = new ModSettingInt(10000)
			{
				displayName = "Max Paragon Power From Non Tier 5s\n(-1 for unlimited)"
			};
			((ModSettingNumber<long>)val4).min = -1L;
			((ModSettingNumber<long>)val4).max = 200000L;
			((ModSetting)val4).icon = "Ui[UpgradeContainerGrey]";
			((ModSetting)val4).modifyOption = delegate(ModHelperOption option)
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				((ModHelperComponent)option.Icon).AddText(new Info("Text", (InfoPreset)0), "<5", 100f);
			};
			((ModSetting)val4).category = ParagonPowerMaximums;
			MaxPowerFromNonTier5s = val4;
			ModSettingInt val5 = new ModSettingInt(50000)
			{
				displayName = "Max Paragon Power From Tier 5s\n(-1 for unlimited)"
			};
			((ModSettingNumber<long>)val5).min = -1L;
			((ModSettingNumber<long>)val5).max = 200000L;
			((ModSetting)val5).icon = "Ui[UpgradeContainerTier5]";
			((ModSetting)val5).modifyOption = delegate(ModHelperOption option)
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				((ModHelperComponent)option.Icon).AddText(new Info("Text", (InfoPreset)0), "5", 100f);
			};
			((ModSetting)val5).category = ParagonPowerMaximums;
			MaxPowerFromTier5s = val5;
			ParagonPowerWeights = new ModSettingCategory("Paragon Power Weights");
			ModSettingInt val6 = new ModSettingInt(180)
			{
				displayName = "Pops per Point of Paragon Power"
			};
			((ModSettingNumber<long>)val6).min = 1L;
			((ModSetting)val6).icon = "IngameUi[PopIcon]";
			((ModSetting)val6).category = ParagonPowerWeights;
			PopsScaleFactor = val6;
			ModSettingInt val7 = new ModSettingInt(20000)
			{
				displayName = "Paragon Power Scale Factor for Cash"
			};
			((ModSettingNumber<long>)val7).min = 1L;
			((ModSetting)val7).icon = "Ui[CoinIcon]";
			((ModSetting)val7).category = ParagonPowerWeights;
			((ModSetting)val7).description = "As of v39, the Paragon Upgrade Price is divided by this to get the final value";
			CashScaleFactor = val7;
			ModSettingInt val8 = new ModSettingInt(100)
			{
				displayName = "Paragon Power Scale Factor for Non Tier 5s"
			};
			((ModSettingNumber<long>)val8).min = 0L;
			((ModSetting)val8).icon = "Ui[UpgradeContainerGrey]";
			((ModSetting)val8).modifyOption = delegate(ModHelperOption option)
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				((ModHelperComponent)option.Icon).AddText(new Info("Text", (InfoPreset)0), "<5", 100f);
			};
			((ModSetting)val8).category = ParagonPowerWeights;
			NonTier5ScaleFactor = val8;
			ModSettingInt val9 = new ModSettingInt(6000)
			{
				displayName = "Paragon Power Scale Factor for Tier 5s"
			};
			((ModSettingNumber<long>)val9).min = 0L;
			((ModSetting)val9).icon = "Ui[UpgradeContainerTier5]";
			((ModSetting)val9).modifyOption = delegate(ModHelperOption option)
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				((ModHelperComponent)option.Icon).AddText(new Info("Text", (InfoPreset)0), "5", 100f);
			};
			((ModSetting)val9).category = ParagonPowerWeights;
			Tier5ScaleFactor = val9;
			TempleAlternateCosts = new ModSettingCategory("Template Alternate Costs");
			ModSettingDouble val10 = new ModSettingDouble(0.5)
			{
				displayName = "Alternate Sun Temple Cost"
			};
			((ModSettingNumber<double>)val10).min = 0.0;
			((ModSettingNumber<double>)val10).max = 1.0;
			val10.stepSize = 0.01f;
			((ModSetting)val10).icon = "080c12903611a654b8d3281aef7fe553";
			((ModSetting)val10).description = "What portion the cost should be if you decide to get a Sun Temple without doing sacrifices";
			((ModSetting)val10).category = TempleAlternateCosts;
			TempleAlternateCostMod = val10;
			ModSettingDouble val11 = new ModSettingDouble(0.2)
			{
				displayName = "Alternate True Sun God Cost"
			};
			((ModSettingNumber<double>)val11).min = 0.0;
			((ModSettingNumber<double>)val11).max = 1.0;
			val11.stepSize = 0.01f;
			((ModSetting)val11).icon = "a04463dfa8e4c704c8b660dd6e5d64b4";
			((ModSetting)val11).description = "What portion the cost should be if you decide to get a True Sun God without doing sacrifices";
			((ModSetting)val11).category = TempleAlternateCosts;
			GodAlternateCostMod = val11;
		}
	}
	public enum AutoSacrificeMode
	{
		Off,
		Sacrifice1222,
		Sacrifice2122,
		Sacrifice2212,
		Sacrifice2221,
		Sacrifice2222
	}
	public class SacrificeHelperUtility : IModSettings, IModContent
	{
		public class SacrificeHelperTsm : ModVanillaTsmTheme
		{
			public const int InfoWidth = 500;

			public const int InfoHeight = 100;

			private static bool showingExtraParagonInfo;

			private ModHelperPanel paragonStuff = null;

			private ModHelperButton degreeButton = null;

			private ModHelperText degreeText = null;

			private ModHelperPanel extraParagonInfo = null;

			private List<ModHelperText> paragonDetails = null;

			private ModHelperPanel templeStuff = null;

			private ModHelperButton sacrificeToggle = null;

			private ModHelperPanel extraSacrificeInfo = null;

			private List<ModHelperText> sacrificeTowerSets = null;

			private static bool showingExtraTempleInfo => !SacrificeHelperMod.templeSacrificesOff && SacrificeHelperMod.AutoSacrificeMode == AutoSacrificeMode.Off;

			private static void ToggleShowingExtraInfo()
			{
				SacrificeHelperMod.templeSacrificesOff = !SacrificeHelperMod.templeSacrificesOff;
			}

			public override void SetupTheme(BaseTSMTheme theme)
			{
				if (ModSettingBool.op_Implicit(ParagonSacrificeInfo))
				{
					CreateParagonStuff(theme);
				}
				if (ModSettingBool.op_Implicit(TempleSacrificeInfo))
				{
					CreateTempleStuff(theme);
				}
			}

			private void CreateParagonStuff(BaseTSMTheme theme)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0048: Unknown result type (might be due to invalid IL or missing references)
				//IL_007a: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
				paragonStuff = GameObjectExt.AddModHelperPanel(((Component)theme).gameObject, new Info("ParagonStuff", (InfoPreset)0), (string)null, (Axis?)null, 50f, 0);
				degreeButton = ((ModHelperComponent)paragonStuff).AddButton(new Info("ParagonButton", 375f, -75f, 135f), "Ui[UpgradeContainerParagon]", Action.op_Implicit((Action)delegate
				{
					showingExtraParagonInfo = !showingExtraParagonInfo;
					UpdateExtraInfo();
				}));
				degreeText = ((ModHelperComponent)degreeButton).AddText(new Info("DegreeText", (InfoPreset)0), "0", 60f);
				ModHelperPanel obj = paragonStuff;
				Info val = default(Info);
				((Info)(ref val))..ctor("ExtraParagonInfo", 50f, -50f, 500f);
				((Info)(ref val)).set_PivotY(1f);
				extraParagonInfo = ((ModHelperComponent)obj).AddPanel(val, (string)null, (Axis?)(Axis)1);
				paragonDetails = IEnumerableExt.ToIl2CppList<ModHelperText>(ParagonDetail.CreateTexts(extraParagonInfo));
			}

			private unsafe void CreateTempleStuff(BaseTSMTheme theme)
			{
				//IL_0027: 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_0096: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
				templeStuff = GameObjectExt.AddModHelperPanel(((Component)theme).gameObject, new Info("TempleStuff", (InfoPreset)0), (string)null, (Axis?)null, 50f, 0);
				sacrificeToggle = ((ModHelperComponent)templeStuff).AddButton(new Info("TempleButton", 375f, -75f, 120f), "Ui[NotificationYellow]", Action.op_Implicit((Action)delegate
				{
					ToggleShowingExtraInfo();
					UpdateUpgradeCosts();
					TowerSelectionMenu componentInParent = ((Component)theme).GetComponentInParent<TowerSelectionMenu>();
					for (int i = 0; i < ((Il2CppArrayBase<UpgradeObject>)(object)componentInParent.upgradeButtons).Count; i++)
					{
						UpgradeObject val2 = ((Il2CppArrayBase<UpgradeObject>)(object)componentInParent.upgradeButtons)[i];
						val2.UpdateCost();
						val2.UpdateVisuals(i, false);
					}
					UpdateExtraInfo();
				}));
				((ModHelperComponent)sacrificeToggle).AddImage(new Info("SacrificeIcon", 80f), "UiBuffIcons[BuffIconBloodSacrifice]");
				ModHelperPanel obj = templeStuff;
				Info val = default(Info);
				((Info)(ref val))..ctor("ExtraSacrificeInfo", 50f, -50f, 500f);
				((Info)(ref val)).set_PivotY(1f);
				extraSacrificeInfo = ((ModHelperComponent)obj).AddPanel(val, (string)null, (Axis?)(Axis)1);
				IEnumerable<ModHelperText> enumerable = from s in ((TowerSet)15).Enumerate()
					select CreateInfoLine(extraSacrificeInfo, ((object)(*(TowerSet*)(&s))/*cast due to .constrained prefix*/).ToString(), $"MainMenuUiAtlas[{s}Btn]");
				sacrificeTowerSets = IEnumerableExt.ToIl2CppList<ModHelperText>(enumerable);
			}

			public override void TowerChanged(BaseTSMTheme theme, TowerToSimulation tower)
			{
				if (tower != null)
				{
					if (ModSettingBool.op_Implicit(ParagonSacrificeInfo))
					{
						UpdateParagonStuff(tower);
					}
					if (ModSettingBool.op_Implicit(TempleSacrificeInfo))
					{
						UpdateTempleStuff(tower);
					}
					UpdateExtraInfo();
				}
			}

			private void UpdateParagonStuff(TowerToSimulation tower)
			{
				//IL_006a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0063: Unknown result type (might be due to invalid IL or missing references)
				//IL_009d: Unknown result type (might be due to invalid IL or missing references)
				bool flag = TowerSelectionMenuUtils.CanUpgradeToParagon(tower, true);
				((ModHelperComponent)paragonStuff).SetActive(flag);
				if (flag)
				{
					InvestmentInfo investmentInfo;
					long paragonDegree = Utils.GetParagonDegree(tower, out investmentInfo);
					degreeText.SetText($"{paragonDegree}");
					((Graphic)degreeText.Text).color = ((paragonDegree >= 100) ? Color.green : Color.white);
					List<ModHelperText> list = Il2CppGenericsExt.ToList<ModHelperText>(paragonDetails);
					for (int i = 0; i < ParagonDetail.AllDetails.Count; i++)
					{
						ParagonDetail.AllDetails[i].Update(list[i], investmentInfo);
					}
				}
			}

			private unsafe void UpdateTempleStuff(TowerToSimulation tower)
			{
				//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
				//IL_0133: Unknown result type (might be due to invalid IL or missing references)
				Il2CppReferenceArray<UpgradePathModel> upgrades = tower.Def.upgrades;
				bool flag = upgrades != null && Il2CppReferenceArray.Any<UpgradePathModel>(upgrades, (Func<UpgradePathModel, bool>)((UpgradePathModel model) => model.upgrade == "Sun Temple"));
				Il2CppReferenceArray<UpgradePathModel> upgrades2 = tower.Def.upgrades;
				bool flag2 = upgrades2 != null && Il2CppReferenceArray.Any<UpgradePathModel>(upgrades2, (Func<UpgradePathModel, bool>)((UpgradePathModel model) => model.upgrade == "True Sun God"));
				((ModHelperComponent)templeStuff).SetActive(flag || flag2);
				if (flag || flag2)
				{
					Dictionary<string, float> towerWorths = Utils.GetTowerWorths(tower.tower);
					Dictionary<string, Color> colors = Utils.GetColors(towerWorths, flag2);
					List<TowerSet> list = ((TowerSet)15).Enumerate().ToList();
					List<ModHelperText> list2 = Il2CppGenericsExt.ToList<ModHelperText>(sacrificeTowerSets);
					for (int num = 0; num < list2.Count; num++)
					{
						TowerSet val = list[num];
						ModHelperText val2 = list2[num];
						val2.SetText($"${towerWorths[((object)(*(TowerSet*)(&val))/*cast due to .constrained prefix*/).ToString()]:N0}");
						((Graphic)val2.Text).color = colors[((object)(*(TowerSet*)(&val))/*cast due to .constrained prefix*/).ToString()];
					}
				}
			}

			private void UpdateExtraInfo()
			{
				if (ModSettingBool.op_Implicit(ParagonSacrificeInfo))
				{
					((ModHelperComponent)extraParagonInfo).SetActive(showingExtraParagonInfo);
				}
				if (ModSettingBool.op_Implicit(TempleSacrificeInfo))
				{
					((ModHelperComponent)extraSacrificeInfo).SetActive(showingExtraTempleInfo);
				}
			}

			private static ModHelperText CreateInfoLine(ModHelperPanel parent, string id, string icon)
			{
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				ModHelperPanel val = ((ModHelperComponent)parent).AddPanel(new Info(id, 500f, 100f), (string)null, (Axis?)(Axis)0, 25f);
				((ModHelperComponent)val).AddImage(new Info("Icon", 100f), icon);
				ModHelperText val2 = ((ModHelperComponent)val).AddText(new Info("Amount", 350f, 100f), "", 69f);
				((TMP_Text)val2.Text).alignment = (TextAlignmentOptions)4097;
				return val2;
			}
		}

		public class ParagonDetail
		{
			private float current;

			private float max;

			public static List<ParagonDetail> AllDetails { get; }

			public string Name { get; }

			public string Icon { get; }

			public Func<InvestmentInfo, float> Current { get; }

			public Func<ParagonDegreeDataModel, float>? Max { get; }

			public Action<ModHelperComponent>? ModifyIcon { get; }

			static ParagonDetail()
			{
				AllDetails = new List<ParagonDetail>(5)
				{
					new ParagonDetail("Money Spent", "Ui[CoinIcon]", (InvestmentInfo info) => info.powerFromMoneySpent, (ParagonDegreeDataModel model) => model.maxPowerFromMoneySpent),
					new ParagonDetail("Pops / Generated Cash", "IngameUi[PopIcon]", (InvestmentInfo info) => info.powerFromPops, (ParagonDegreeDataModel model) => model.maxPowerFromPops),
					new ParagonDetail("Non Tier 5 Upgrades Purchased", "Ui[UpgradeContainerGrey]", (InvestmentInfo info) => info.powerFromNonTier5Tiers, (ParagonDegreeDataModel model) => model.maxPowerFromNonTier5Count, delegate(ModHelperComponent image)
					{
						//IL_0007: Unknown result type (might be due to invalid IL or missing references)
						image.AddText(new Info("Text", (InfoPreset)0), "<5", 69f);
					}),
					new ParagonDetail("Having Tier 5 Towers", "Ui[UpgradeContainerTier5]", (InvestmentInfo info) => info.powerFromTier5Count, (ParagonDegreeDataModel model) => model.maxPowerFromTier5Count, delegate(ModHelperComponent image)
					{
						//IL_0007: Unknown result type (might be due to invalid IL or missing references)
						image.AddText(new Info("Text", (InfoPreset)0), "5", 69f);
					}),
					new ParagonDetail("Geraldo Totems", "44ec3db93dc5cb847aaf730cea6c6084", (InvestmentInfo info) => info.powerFromBonus)
				};
			}

			public ParagonDetail(string name, string icon, Func<InvestmentInfo, float> current, Func<ParagonDegreeDataModel, float>? max = null, Action<ModHelperComponent>? modifyIcon = null)
			{
				Name = name;
				Icon = icon;
				Current = current;
				Max = max;
				ModifyIcon = modifyIcon;
			}

			public void Update(ModHelperText text, InvestmentInfo investmentInfo)
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_0089: Unknown result type (might be due to invalid IL or missing references)
				//IL_0090: Unknown result type (might be due to invalid IL or missing references)
				current = Current(investmentInfo);
				max = Max?.Invoke(InGameExt.GetGameModel(InGame.instance).paragonDegreeDataModel) ?? (-1f);
				text.SetText($"{current:N0}");
				((Graphic)text.Text).color = ((max > 0f && current >= max) ? Color.green : Color.white);
			}

			public static IEnumerable<ModHelperText> CreateTexts(ModHelperPanel extraParagonInfo)
			{
				return AllDetails.Select((ParagonDetail detail) => detail.CreateInfoLine(extraParagonInfo));
			}

			private ModHelperText CreateInfoLine(ModHelperPanel parent)
			{
				//IL_0012: 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_0079: Unknown result type (might be due to invalid IL or missing references)
				ModHelperPanel val = ((ModHelperComponent)parent).AddPanel(new Info(Name, 500f, 100f), (string)null, (Axis?)(Axis)0, 25f);
				ModHelperButton obj = ((ModHelperComponent)val).AddButton(new Info("Icon", 100f), Icon, Action.op_Implicit((Action)delegate
				{
					string message = $"You are getting {current:N0} Paragon Power from {Name}.";
					if (max > 0f)
					{
						message += $" You are {current / max:P0} of the way to the maximum of {max:N0}.";
					}
					PopupScreenExt.SafelyQueue(PopupScreen.instance, (Action<PopupScreen>)delegate(PopupScreen screen)
					{
						screen.ShowOkPopup(message, (ReturnCallback)null);
					});
				}));
				ModifyIcon?.Invoke((ModHelperComponent)(object)obj);
				ModHelperText val2 = ((ModHelperComponent)val).AddText(new Info("Amount", 350f, 100f), "", 69f);
				((TMP_Text)val2.Text).alignment = (TextAlignmentOptions)4097;
				return val2;
			}
		}

		public static class Utils
		{
			public static void DefaultTemple(UpgradeModel upgradeModel)
			{
				upgradeModel.confirmation = ((SacrificeHelperMod.AutoSacrificeMode == AutoSacrificeMode.Off) ? "Sun Temple" : "");
				int cost = Game.instance.model.GetUpgrade(((Model)upgradeModel).name).cost;
				int num = CostHelper.CostForDifficulty(cost, InGame.instance);
				AutoSacrificeMode autoSacrificeMode = SacrificeHelperMod.AutoSacrificeMode;
				if (1 == 0)
				{
				}
				int num2 = autoSacrificeMode switch
				{
					AutoSacrificeMode.Off => 0, 
					AutoSacrificeMode.Sacrifice2222 => 200000, 
					_ => 150000, 
				};
				if (1 == 0)
				{
				}
				upgradeModel.cost = num + num2;
			}

			public static void ModifyTemple(UpgradeModel upgradeModel)
			{
				upgradeModel.confirmation = "";
				int cost = Game.instance.model.GetUpgrade(((Model)upgradeModel).name).cost;
				ModSettingDouble templeAlternateCostMod = SacrificeHelperMod.TempleAlternateCostMod;
				upgradeModel.cost = CostHelper.CostForDifficulty((int)((float)cost * ModSettingDouble.op_Implicit(templeAlternateCostMod)), InGame.instance);
			}

			public static void DefaultGod(UpgradeModel upgradeModel)
			{
				upgradeModel.confirmation = ((SacrificeHelperMod.AutoSacrificeMode == AutoSacrificeMode.Off) ? "True Sun God" : "");
				int cost = Game.instance.model.GetUpgrade(((Model)upgradeModel).name).cost;
				int num = CostHelper.CostForDifficulty(cost, InGame.instance);
				AutoSacrificeMode autoSacrificeMode = SacrificeHelperMod.AutoSacrificeMode;
				if (1 == 0)
				{
				}
				int num2 = ((autoSacrificeMode != AutoSacrificeMode.Off) ? 200000 : 0);
				if (1 == 0)
				{
				}
				upgradeModel.cost = num + num2;
			}

			public static void ModifyGod(UpgradeModel upgradeModel)
			{
				upgradeModel.confirmation = "";
				int cost = Game.instance.model.GetUpgrade(((Model)upgradeModel).name).cost;
				ModSettingDouble godAlternateCostMod = SacrificeHelperMod.GodAlternateCostMod;
				upgradeModel.cost = CostHelper.CostForDifficulty((int)((float)cost * ModSettingDouble.op_Implicit(godAlternateCostMod)), InGame.instance);
			}

			public static Dictionary<string, Color> GetColors(Dictionary<string, float> worths, bool god)
			{
				//IL_0112: 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_0129: Unknown result type (might be due to invalid IL or missing references)
				//IL_012e: 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_017c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0171: Unknown result type (might be due to invalid IL or missing references)
				//IL_0176: Unknown result type (might be due to invalid IL or missing references)
				//IL_0156: Unknown result type (might be due to invalid IL or missing references)
				//IL_015b: Unknown result type (might be due to invalid IL or missing references)
				Dictionary<string, Color> dictionary = new Dictionary<string, Color>();
				if (!god)
				{
					string key = "";
					float min = float.MaxValue;
					foreach (string item in worths.Keys.Where((string key2) => worths[key2] < min))
					{
						key = item;
						min = worths[item];
					}
					dictionary[key] = Color.red;
				}
				foreach (string key2 in worths.Keys)
				{
					if (dictionary.ContainsKey(key2))
					{
						continue;
					}
					float num = worths[key2];
					Color value = Color.red;
					if (num > 50000f)
					{
						value = Color.green;
					}
					else if (key2 == "Magic")
					{
						if (num > 1000f)
						{
							value = Color.white;
						}
					}
					else if (num > 300f)
					{
						value = Color.white;
					}
					dictionary[key2] = value;
				}
				return dictionary;
			}

			public static bool IsValidTower(Tower tower)
			{
				return !tower.towerModel.isPowerTower && !tower.towerModel.isGeraldoItem && !tower.towerModel.IsBeastHandlerPet && !tower.towerModel.isParagon && ((EntityModel)tower.towerModel).baseId != "TempleBase-TempleBase";
			}

			public unsafe static Dictionary<string, float> GetTowerWorths(Tower tower)
			{
				return ((TowerSet)15).Enumerate().ToDictionary((TowerSet s) => ((object)(*(TowerSet*)(&s))/*cast due to .constrained prefix*/).ToString(), (TowerSet s) => GetTowerSetWorth(s, tower));
			}

			private static float GetTowerSetWorth(TowerSet towerSet, Tower tower)
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				return (from t in Il2CppGenericIEnumerableExt.ToList<Tower>(InGameExt.GetTowerManager(InGame.instance).GetTowersInRange(((CommonBehaviorProxy<ITowerBehavior>)(object)tower).Position, tower.towerModel.range))
					where t.towerModel.towerSet == towerSet && ((RootObject)t).Id != ((RootObject)tower).Id && IsValidTower(t)
					select t).Sum((Tower t) => t.worth);
			}

			private static ParagonTower FakeParagonTower(Tower tower)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_002c: 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_003c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0045: Expected O, but got Unknown
				return new ParagonTower
				{
					Sim = ((RootObject)tower).Sim,
					entity = ((RootBehavior)tower).entity,
					model = ((RootBehavior)tower).model,
					tower = tower,
					isActive = true,
					activeAt = -1
				};
			}

			public static UpgradeModel GetParagonUpgrade(Tower tower)
			{
				GameModel val = (((Object)(object)InGame.instance != (Object)null) ? InGame.Bridge.Model : Game.instance.model);
				BloonsMod val2 = default(BloonsMod);
				return (((Mutable)tower).IsMutatedBy("HonoraryParagon") && ModHelper.HasMod("HonoraryParagons", ref val2)) ? val2.Call<UpgradeModel>("GetParagonUpgrade", new object[2] { val, tower.towerModel }) : val.GetParagonUpgradeForTowerId(((EntityModel)tower.towerModel).baseId);
			}

			public static long GetParagonDegree(TowerToSimulation tower, out InvestmentInfo investmentInfo, float bonus = 0f)
			{
				//IL_007a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0089: Unknown result type (might be due to invalid IL or missing references)
				//IL_008b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0182: Unknown result type (might be due to invalid IL or missing references)
				//IL_019b: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c0: 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_00dc: Unknown result type (might be due to invalid IL or missing references)
				//IL_00de: Unknown result type (might be due to invalid IL or missing references)
				GameModel model = tower.sim.Model;
				ParagonDegreeDataModel paragonDegreeDataModel = model.paragonDegreeDataModel;
				float num = (tower.IsParagon ? ((float)GetParagonUpgrade(tower.tower).cost) : tower.GetUpgradeCost(0, 6, -1f, true));
				float num2 = bonus * paragonDegreeDataModel.moneySpentOverX / ((1f + paragonDegreeDataModel.paidContributionPenalty) * num);
				InvestmentInfo seed = new InvestmentInfo
				{
					powerFromMoneySpent = num2
				};
				ParagonTower paragonTower = default(ParagonTower);
				if (Il2CppSystemObjectExt.Is<ParagonTower>(((RootBehavior)tower.tower).entity.GetBehavior<ParagonTower>(), ref paragonTower))
				{
					InvestmentInfo investmentInfo2 = paragonTower.investmentInfo;
					investmentInfo2.totalInvestment = paragonTower.investmentInfo.totalInvestment + num2;
					investmentInfo = investmentInfo2;
				}
				else
				{
					paragonTower = FakeParagonTower(tower.tower);
					paragonTower.upgradeCost = num;
					int index = 0;
					investmentInfo = (from tts in InGameExt.GetAllTowerToSim(InGame.instance, (string)null)
						where !tts.IsParagon && !((Mutable)tts.tower).IsMutatedBy("DoorGunnerMutator") && (((EntityModel)tts.Def).baseId == ((EntityModel)tower.Def).baseId || ((Model)tts.Def).GetChild<ParagonSacrificeBonusModel>() != null)
						orderby paragonTower.GetTowerInvestment(tts.tower, 3).totalInvestment
						select paragonTower.GetTowerInvestment(tts.tower, (tts.Def.tier >= 5) ? index++ : 3)).Aggregate(seed, (Func<InvestmentInfo, InvestmentInfo, InvestmentInfo>)paragonTower.CombineInvestments);
				}
				long num3 = 0L;
				BloonsMod val = default(BloonsMod);
				if (ModHelper.HasMod("Paragonomics", ref val))
				{
					num3 = (int)val.Call("GetDegree", new object[1] { investmentInfo.totalInvestment });
				}
				else
				{
					while (investmentInfo.totalInvestment >= (float)((Il2CppArrayBase<int>)(object)paragonDegreeDataModel.powerDegreeRequirements)[(int)num3])
					{
						num3++;
						if (num3 == ((Il2CppArrayBase<int>)(object)paragonDegreeDataModel.powerDegreeRequirements).Length)
						{
							break;
						}
					}
				}
				return num3;
			}
		}

		[HarmonyPatch(typeof(ParagonConfirmationPopup), "UpdateCurrentInvestment")]
		internal static class ParagonConfirmationPopup_UpdateCurrentInvestment
		{
			[HarmonyPostfix]
			private static void Postfix(ParagonConfirmationPopup __instance, float current)
			{
				//IL_007d: 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)
				TowerToSimulation selectedTower = TowerSelectionMenuExt.instance.selectedTower;
				float num = current;
				int cost = Utils.GetParagonUpgrade(selectedTower.tower).cost;
				if (__instance.upgradeCost != 0 && InGame.Bridge.GetCash(-1) < (double)cost)
				{
					num += (float)__instance.upgradeCost;
					num -= (float)cost;
				}
				InvestmentInfo investmentInfo;
				long paragonDegree = Utils.GetParagonDegree(selectedTower, out investmentInfo, num);
				NK_TextMeshProUGUI componentFromChildrenByName = ComponentExt.GetComponentFromChildrenByName<NK_TextMeshProUGUI>((Component)(object)((Component)__instance).transform, "DegreeText");
				componentFromChildrenByName.SetText(paragonDegree.ToString());
				((Graphic)componentFromChildrenByName).color = Color.white;
				if (paragonDegree >= 100)
				{
					BloonsMod mod = ModHelper.GetMod("Paragonomics");
					if ((bool?)((mod != null) ? mod.ModSettings["NoDegreeLimit"].GetValue() : null) != true)
					{
						((Graphic)componentFromChildrenByName).color = Color.green;
					}
				}
			}
		}

		[HarmonyPatch(typeof(ParagonConfirmationPopup), "Init", new Type[]
		{
			typeof(Action<double>),
			typeof(Action),
			typeof(int),
			typeof(int),
			typeof(int),
			typeof(BackGround),
			typeof(TransitionAnim)
		})]
		internal static class ParagonConfirmationPopup_Init
		{
			[HarmonyPostfix]
			private static void Postfix(ParagonConfirmationPopup __instance)
			{
				//IL_007f: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
				TowerToSimulation selectedTower = TowerSelectionMenuExt.instance.selectedTower;
				int num = 0;
				int cost = Utils.GetParagonUpgrade(selectedTower.tower).cost;
				if (__instance.upgradeCost != 0 && InGame.Bridge.GetCash(-1) < (double)cost)
				{
					num += __instance.upgradeCost;
					num -= cost;
				}
				InvestmentInfo investmentInfo;
				long paragonDegree = Utils.GetParagonDegree(selectedTower, out investmentInfo, num);
				GameObject gameObject = ((Component)((Popup)__instance).animator).gameObject;
				ModHelperImage val = ModHelperImage.Create(new Info("DegreeIndicator", 0f, -450f, 250f, 250f), "Ui[UpgradeContainerParagon]");
				GameObjectExt.AddModHelperComponent<ModHelperImage>(gameObject, val);
				((ModHelperComponent)val).AddText(new Info("DegreeText", (InfoPreset)0), paragonDegree.ToString(), 100f);
			}
		}

		private static readonly ModSettingBool TempleSacrificeInfo = new ModSettingBool(true)
		{
			description = "Shows indicators for Sun Temple and True Sun God sacrifices for how much of each tower category is in range.",
			icon = "4798e98bc64924a999a410acde0ac904"
		};

		private static readonly ModSettingBool ParagonSacrificeInfo = new ModSettingBool(true)
		{
			description = "Shows indicators for Paragon sacrifices for how what degree the paragon will be, and also how much power is coming from each source.",
			icon = "1757f8ef9167a3842b6d977f379d8548"
		};

		public static void UpdateUpgradeCosts(GameModel? gameModel = null)
		{
			if (gameModel == null)
			{
				gameModel = InGameExt.GetGameModel(InGame.instance);
			}
			UpgradeModel upgrade = gameModel.GetUpgrade("Sun Temple");
			UpgradeModel upgrade2 = gameModel.GetUpgrade("True Sun God");
			if (SacrificeHelperMod.templeSacrificesOff)
			{
				Utils.ModifyTemple(upgrade);
				Utils.ModifyGod(upgrade2);
			}
			else
			{
				Utils.DefaultTemple(upgrade);
				Utils.DefaultGod(upgrade2);
			}
			foreach (MonkeyTempleModel item in from tower in ((IEnumerable<TowerModel>)MonoLinqHelper.ToArray<TowerModel>(gameModel.GetTowersWithBaseId(TowerType.SuperMonkey, false))).Where(delegate(TowerModel tower)
				{
					Il2CppStringArray appliedUpgrades = tower.appliedUpgrades;
					return appliedUpgrades != null && ((Il2CppArrayBase<string>)(object)appliedUpgrades).Contains("Sun Temple") && !((Il2CppArrayBase<string>)(object)tower.appliedUpgrades).Contains("True Sun God");
				})
				select TowerModelBehaviorExt.GetBehavior<MonkeyTempleModel>(tower))
			{
				item.towerGroupCount = (ModSettingBool.op_Implicit(SacrificeHelperMod.FourCategorySunTemples) ? 4 : 3);
			}
		}
	}
	internal static class TowerSetExt
	{
		[SpecialName]
		public sealed class <G>$0BDFE946FF9530C0E65A0F67758E2703
		{
			[SpecialName]
			public static class <M>$6938555CF6C5DEAE31E69F666B5131BF
			{
			}

			[ExtensionMarker("<M>$6938555CF6C5DEAE31E69F666B5131BF")]
			public IEnumerable<TowerSet> Enumerate()
			{
				throw new NotSupportedException();
			}
		}

		public static IEnumerable<TowerSet> Enumerate(this TowerSet towerSet)
		{
			//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)
			TowerSet[] values = Enum.GetValues<TowerSet>();
			int i = 1;
			while (values.Contains((TowerSet)i))
			{
				if (((Enum)towerSet).HasFlag((Enum)(object)(TowerSet)i))
				{
					yield return (TowerSet)i;
				}
				i *= 2;
			}
		}
	}
}