Decompiled source of TacticalTweaks v1.2.2

TacticalTweaks.dll

Decompiled 13 hours ago
using System;
using System.Collections;
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.ModOptions;
using BTD_Mod_Helper.Api.Towers;
using BTD_Mod_Helper.Extensions;
using HarmonyLib;
using Il2Cpp;
using Il2CppAssets.Scripts;
using Il2CppAssets.Scripts.Models;
using Il2CppAssets.Scripts.Models.Bloons;
using Il2CppAssets.Scripts.Models.Bloons.Behaviors;
using Il2CppAssets.Scripts.Models.Entities;
using Il2CppAssets.Scripts.Models.GenericBehaviors;
using Il2CppAssets.Scripts.Models.Profile;
using Il2CppAssets.Scripts.Models.SimulationBehaviors;
using Il2CppAssets.Scripts.Models.TowerSets;
using Il2CppAssets.Scripts.Models.Towers;
using Il2CppAssets.Scripts.Models.Towers.Behaviors;
using Il2CppAssets.Scripts.Models.Towers.Behaviors.Abilities;
using Il2CppAssets.Scripts.Models.Towers.Behaviors.Abilities.Behaviors;
using Il2CppAssets.Scripts.Models.Towers.Behaviors.Attack;
using Il2CppAssets.Scripts.Models.Towers.Behaviors.Attack.Behaviors;
using Il2CppAssets.Scripts.Models.Towers.Projectiles.Behaviors;
using Il2CppAssets.Scripts.Models.Towers.TowerFilters;
using Il2CppAssets.Scripts.Models.Towers.Weapons;
using Il2CppAssets.Scripts.Models.Towers.Weapons.Behaviors;
using Il2CppAssets.Scripts.Simulation;
using Il2CppAssets.Scripts.Simulation.Behaviors;
using Il2CppAssets.Scripts.Simulation.Bloons;
using Il2CppAssets.Scripts.Simulation.Objects;
using Il2CppAssets.Scripts.Simulation.SMath;
using Il2CppAssets.Scripts.Simulation.SimulationBehaviors;
using Il2CppAssets.Scripts.Simulation.Towers;
using Il2CppAssets.Scripts.Simulation.Towers.Behaviors;
using Il2CppAssets.Scripts.Simulation.Towers.Behaviors.Abilities;
using Il2CppAssets.Scripts.Simulation.Towers.Behaviors.Abilities.Behaviors;
using Il2CppAssets.Scripts.Simulation.Towers.Behaviors.Attack;
using Il2CppAssets.Scripts.Simulation.Towers.Behaviors.Attack.Behaviors;
using Il2CppAssets.Scripts.Simulation.Towers.TowerFilters;
using Il2CppAssets.Scripts.Simulation.Towers.Weapons;
using Il2CppAssets.Scripts.Simulation.Track;
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 Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppNinjaKiwi.Common.ResourceUtils;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.IO;
using Il2CppSystem.Linq;
using MelonLoader;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using TacticalTweaks;
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(TacticalTweaksMod), "Tactical Tweaks", "1.2.2", "doombubbles", null)]
[assembly: MelonGame("Ninja Kiwi", "BloonsTD6")]
[assembly: MelonGame("Ninja Kiwi", "BloonsTD6-Epic")]
[assembly: HarmonyDontPatchAll]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("TacticalTweaks")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+ba6e6d2aef38cecefb394242dfbd4478c24a70de")]
[assembly: AssemblyProduct("TacticalTweaks")]
[assembly: AssemblyTitle("TacticalTweaks")]
[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;
		}
	}
}
namespace TacticalTweaks
{
	public static class ModHelperData
	{
		public const string WorksOnVersion = "55.3";

		public const string Version = "1.2.2";

		public const string Name = "Tactical Tweaks";

		public const string Description = "Adds an assortment of minor gameplay altering tweaks to BTD6, including **Buffable Paragons**!. See the Main Readme for full details.\r\n\r\nNew: Beast Handler Lone T5s, Brickell Mermonkeys, Elite Defender Target Switch, Etienne Targeting, Sticky Bomb Attack Speed, Better Laser Blasts, Better Trojan, Better Monkey City, Better Central Market, Auto Collect/Deposit Banks, Obyn Price Tweak, More Overclock Interactions, More Unfreezable Towers\r\nFormerly Useful Utilities: Dartling/Mortary/Sentry Targeting, Auto Trap Refresh\r\nOld Mods: Better Armor Piercing, Better Ezili Totem";

		public const string RepoOwner = "doombubbles";

		public const string PrevRepoName = "tactical-tweaks";

		public const string RepoName = "TacticalTweaks";
	}
	public abstract class TacticalTweak : NamedModContent, IModSettings, IModContent
	{
		protected virtual bool CreateCategory => false;

		protected virtual string Icon => ((ModContent)this).TextureExists(((ModContent)this).Name) ? ((ModContent)this).GetTextureGUID(((ModContent)this).Name) : null;

		protected virtual string DisableIfModPresent => ((ModContent)this).Name;

		protected static Instance MelonLogger => ((MelonBase)ModContent.GetInstance<TacticalTweaksMod>()).LoggerInstance;

		public sealed override IEnumerable<ModContent> Load()
		{
			if (!ModHelper.HasMod(DisableIfModPresent))
			{
				Type[] nestedTypes = ((object)this).GetType().GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic);
				foreach (Type nestedType in nestedTypes)
				{
					((ModContent)this).mod.ApplyHarmonyPatches(nestedType);
				}
				OnLoad();
				yield return (ModContent)(object)this;
			}
		}

		public sealed override void Register()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			TacticalTweaksMod.TacticalTweaks[((ModContent)this).Name] = this;
			if (CreateCategory)
			{
				ModSettingCategory category = new ModSettingCategory(((NamedModContent)this).DisplayName)
				{
					icon = Icon,
					collapsed = true
				};
				foreach (ModSetting item in ((ModContent)this).mod.ModSettings.Values.Where((ModSetting setting) => (object)setting.source == this))
				{
					item.category = category;
				}
			}
			OnRegister();
		}

		public virtual void OnLoad()
		{
		}

		public virtual void OnRegister()
		{
		}

		public virtual void OnSaveSettings()
		{
		}

		public virtual void OnUpdate()
		{
		}

		public virtual void OnGameObjectsReset()
		{
		}

		public virtual void OnNewGameModel(GameModel gameModel)
		{
		}

		public virtual void OnTowerSaved(Tower tower, TowerSaveDataModel saveData)
		{
		}

		public virtual void OnTowerLoaded(Tower tower, TowerSaveDataModel saveData)
		{
		}
	}
	public class TacticalTweaksMod : BloonsTD6Mod
	{
		public static readonly Dictionary<string, TacticalTweak> TacticalTweaks = new Dictionary<string, TacticalTweak>();

		public static readonly ModSettingCategory Overclock = new ModSettingCategory("Overclock")
		{
			icon = "c101127fbd522584dbcce02cdb22afdb",
			order = 1
		};

		public static readonly ModSettingCategory Targeting = new ModSettingCategory("Targeting")
		{
			icon = "IngameUi[CamoTargetIconCross]",
			order = 2
		};

		public static readonly ModSettingBool DefaultToNewTargeting = new ModSettingBool(true)
		{
			description = "Whether to default to the new targeting options, aka setting these towers to be First by default",
			category = Targeting
		};

		public static MelonPreferences_Category Preferences { get; private set; } = null;

		public override void OnApplicationStart()
		{
			Preferences = MelonPreferences.CreateCategory("TacticalTweaksPreferences");
			CollectionExtensions.Do<Type>(from type in AccessTools.GetTypesFromAssembly(((MelonBase)this).MelonAssembly.Assembly)
				where !type.IsNested
				select type, (Action<Type>)((BloonsMod)this).ApplyHarmonyPatches);
		}

		public static void AddAllTargets(AttackModel attackModel)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0027: 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_0039: Expected O, but got Unknown
			//IL_0040: 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_0052: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			List<TargetSupplierModel> list = AttackModelBehaviorExt.GetBehaviors<TargetSupplierModel>(attackModel).ToList();
			AttackModelBehaviorExt.AddBehavior<TargetFirstModel>(attackModel, CreateTargetFirstModelExt.Create(new Args
			{
				isSelectable = true
			}));
			AttackModelBehaviorExt.AddBehavior<TargetLastModel>(attackModel, CreateTargetLastModelExt.Create(new Args
			{
				isSelectable = true
			}));
			AttackModelBehaviorExt.AddBehavior<TargetCloseModel>(attackModel, CreateTargetCloseModelExt.Create(new Args
			{
				isSelectable = true
			}));
			AttackModelBehaviorExt.AddBehavior<TargetStrongModel>(attackModel, CreateTargetStrongModelExt.Create(new Args
			{
				isSelectable = true
			}));
			if (!ModSettingBool.op_Implicit(DefaultToNewTargeting))
			{
				return;
			}
			foreach (TargetSupplierModel item in list)
			{
				AttackModelBehaviorExt.RemoveBehavior<TargetSupplierModel>(attackModel, item);
				AttackModelBehaviorExt.AddBehavior<TargetSupplierModel>(attackModel, item);
			}
		}

		public static void UpdatePointer(AttackModel attackModel, bool? rotateTower = null)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			RotateToPointerModel behavior = AttackModelBehaviorExt.GetBehavior<RotateToPointerModel>(attackModel);
			AttackModelBehaviorExt.AddBehavior<RotateToTargetModel>(attackModel, CreateRotateToTargetModelExt.Create(new Args
			{
				rotateOnlyOnThrow = behavior.rotateOnlyOnEmit,
				rotateTower = (rotateTower ?? behavior.rotateTower)
			}));
			LineEffectModel val = default(LineEffectModel);
			if (ModelExt.HasDescendant<LineEffectModel>((Model)(object)attackModel, ref val))
			{
				val.useRotateToPointer = false;
			}
		}

		public override void OnSaveSettings(JObject settings)
		{
			foreach (TacticalTweak value in TacticalTweaks.Values)
			{
				value.OnSaveSettings();
			}
		}

		public override void OnUpdate()
		{
			foreach (TacticalTweak value in TacticalTweaks.Values)
			{
				value.OnUpdate();
			}
		}

		public override void OnGameObjectsReset()
		{
			foreach (TacticalTweak value in TacticalTweaks.Values)
			{
				value.OnGameObjectsReset();
			}
		}

		public override void OnNewGameModel(GameModel gameModel)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			foreach (TacticalTweak value in TacticalTweaks.Values)
			{
				value.OnNewGameModel(gameModel);
			}
			TowerModel heroWithNameAndLevel = gameModel.GetHeroWithNameAndLevel(TowerType.StrikerJones, 20, false);
			if (heroWithNameAndLevel != null)
			{
				TowerModelBehaviorExt.AddBehavior<SupportRemoveFilterOutTagModel>(heroWithNameAndLevel, CreateSupportRemoveFilterOutTagModelExt.Create(new Args
				{
					mutatorId = "Striker:DdtDamageModifier",
					removeScriptWithSupportMutatorId = "Striker:Level9BlackBuff",
					isGlobal = true
				}));
			}
		}

		public override void OnTowerSaved(Tower tower, TowerSaveDataModel saveData)
		{
			foreach (TacticalTweak value in TacticalTweaks.Values)
			{
				value.OnTowerSaved(tower, saveData);
			}
		}

		public override void OnTowerLoaded(Tower tower, TowerSaveDataModel saveData)
		{
			foreach (TacticalTweak value in TacticalTweaks.Values)
			{
				value.OnTowerLoaded(tower, saveData);
			}
		}
	}
	public abstract class ToggleableTweak : TacticalTweak
	{
		private ModSettingBool setting = null;

		protected abstract bool DefaultEnabled { get; }

		public bool Enabled => ModSettingBool.op_Implicit(setting);

		public abstract override string Description { get; }

		protected virtual ModSettingCategory Category => null;

		public override void OnLoad()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_005c: Expected O, but got Unknown
			Dictionary<string, ModSetting> modSettings = ((ModContent)this).mod.ModSettings;
			string name = ((ModContent)this).Name;
			ModSettingBool val = new ModSettingBool(DefaultEnabled)
			{
				displayName = ((NamedModContent)this).DisplayName,
				icon = Icon,
				category = Category,
				description = ((NamedModContent)this).Description,
				source = (IModSettings)(object)this
			};
			ModSettingBool value = val;
			setting = val;
			modSettings[name] = (ModSetting)(object)value;
		}
	}
}
namespace TacticalTweaks.Tweaks
{
	public class AutoBloonTrapRetarget : TacticalTweak
	{
		private enum TrapRetargetSetting
		{
			Off,
			StartOfRound,
			Constantly
		}

		[HarmonyPatch(typeof(Simulation), "RoundStart")]
		internal static class Simulation_RoundStart
		{
			[HarmonyPostfix]
			internal static void Postfix(Simulation __instance)
			{
				if (ModSettingEnum<TrapRetargetSetting>.op_Implicit(AutoTrapRetarget) != TrapRetargetSetting.StartOfRound)
				{
					return;
				}
				Il2CppGenericIEnumerable.ForEach<TargetSelectedPoint>(__instance.factory.GetUncast<TargetSelectedPoint>(), (Action<TargetSelectedPoint>)delegate(TargetSelectedPoint point)
				{
					//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_0035: Unknown result type (might be due to invalid IL or missing references)
					if (((RootBehavior)((AttackBehavior)point).attack).model.name.Contains("BloonTrap") && point.HasValidPoint)
					{
						Vector3 targetPoint = point.targetPoint;
						((TargetSupplier)point).ApplyTargetTypeData(((Vector3)(ref targetPoint)).ToVector2());
					}
				});
			}
		}

		[HarmonyPatch(typeof(Weapon), "Process")]
		internal static class Weapon_Process
		{
			[HarmonyPostfix]
			internal static void Postfix(Weapon __instance)
			{
				//IL_0060: Unknown result type (might be due to invalid IL or missing references)
				//IL_0065: 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)
				TargetSelectedPoint val = default(TargetSelectedPoint);
				if (ModSettingEnum<TrapRetargetSetting>.op_Implicit(AutoTrapRetarget) == TrapRetargetSetting.Constantly && ((RootBehavior)((AttackBehavior)__instance).attack).model.name.Contains("BloonTrap") && Il2CppSystemObjectExt.Is<TargetSelectedPoint>((Il2CppObjectBase)(object)((AttackBehavior)__instance).attack.activeTargetSupplier, ref val) && __instance.IsReloadReady && val.HasValidPoint)
				{
					TargetSelectedPoint obj = val;
					Vector3 targetPoint = val.targetPoint;
					((TargetSupplier)obj).ApplyTargetTypeData(((Vector3)(ref targetPoint)).ToVector2());
				}
			}
		}

		private static readonly ModSettingEnum<TrapRetargetSetting> AutoTrapRetarget = new ModSettingEnum<TrapRetargetSetting>(TrapRetargetSetting.Off)
		{
			icon = "dc5d21f63f63bff40a8798a2b666a5aa",
			description = "For Engineers with with Bloon Trap and Larger Service Area, traps will now be automatically retargeted on the same spot to refresh them."
		};
	}
	public class AutoCollectBanks : ToggleableTweak
	{
		protected override bool DefaultEnabled => false;

		public override string Description => "All Banks will auto collect when full like the XX2 Banks do.";

		protected override string Icon => "01a32a1a35c684d6a8d137b62d3a7f1b";

		public override void OnNewGameModel(GameModel gameModel)
		{
			BankModel val = default(BankModel);
			foreach (TowerModel item in Il2CppGenericIEnumerable.AsIEnumerable<TowerModel>(gameModel.GetTowersWithBaseId(TowerType.BananaFarm, false)))
			{
				if (TowerModelBehaviorExt.HasBehavior<BankModel>(item, ref val))
				{
					val.autoCollect = true;
				}
			}
		}
	}
	public class AutoDepositBanks : ToggleableTweak
	{
		[HarmonyPatch(typeof(Bank), "Collect")]
		internal static class Bank_Collect
		{
			[HarmonyPrefix]
			internal static void Prefix(Bank __instance, ref float __state)
			{
				__state = __instance.cash;
			}

			[HarmonyPostfix]
			internal static void Postfix(Bank __instance, float __state)
			{
				if (ModContent.GetInstance<AutoDepositBanks>().Enabled && TowerModelBehaviorExt.HasBehavior<BankDepositsModel>(((TowerBehavior)__instance).tower.towerModel) && !(__state < __instance.bankModel.capacity))
				{
					((RootObject)__instance).Sim.RemoveCash((double)(__state / 2f), (CashType)2, InGame.Bridge.MyPlayerNumber, (CashSource)6);
					__instance.DepositCash(__state / 2f);
				}
			}
		}

		protected override bool DefaultEnabled => false;

		public override string Description => "When making a full collection from a Monkey Bank that has Deposits enabled, half of the amount collected will be automatically deposited back.";

		protected override string Icon => "1728a8a7ee4434f589617ff0d2672b9c";
	}
	public class BeastHandlerLoneT5s : ToggleableTweak
	{
		[HarmonyPatch(typeof(ContributionMutator), "Mutate")]
		internal static class ContributionMutator_Mutate
		{
			[HarmonyPostfix]
			internal static void Postfix(ContributionMutator __instance, Model model)
			{
				TowerModel val = default(TowerModel);
				if (ModContent.GetInstance<BeastHandlerLoneT5s>().Enabled && __instance.towerBaseId == TowerType.Piranha && Il2CppSystemObjectExt.Is<TowerModel>((Il2CppObjectBase)(object)model, ref val) && val.tier >= 5 && __instance.power < 84)
				{
					((Model)model.GetDescendant<TowerModel>()).GetDescendant<CreateGreatWhiteEffectModel>().maxGrabBloonName = "Zomg";
				}
			}
		}

		private class T5Description : ModTextOverride
		{
			private string Upgrade { get; init; } = null;

			public override string Name => Upgrade;

			public override string LocalizationKey => Upgrade + " Description";

			public override bool Active => ModContent.GetInstance<BeastHandlerLoneT5s>().Enabled;

			public override string TextValue => StringExt.RegexReplace(((ModTextOverride)this).OriginalText, " Requires.*$", "");

			public override IEnumerable<ModContent> Load()
			{
				yield return (ModContent)(object)new T5Description
				{
					Upgrade = "Megalodon"
				};
				yield return (ModContent)(object)new T5Description
				{
					Upgrade = "Giganotosaurus"
				};
				yield return (ModContent)(object)new T5Description
				{
					Upgrade = "Pouakai"
				};
			}
		}

		public override string DisplayName => "Beast Handler Lone T5s";

		protected override bool DefaultEnabled => false;

		public override string Description => "Allows Tier 5 Beast Handlers to be purchased even without any other Beast Handlers contributing to them.\r\nMegalodon still requires 84 Beast Power to insta kill BAD Bloons.";

		protected override string Icon => "MonkeyIcons[BeastHandlerIcon]";

		public override void OnNewGameModel(GameModel gameModel)
		{
			if (!base.Enabled)
			{
				return;
			}
			foreach (BeastHandlerPetModel item in ((IEnumerable<TowerModel>)MonoLinqHelper.ToArray<TowerModel>(gameModel.GetTowersWithBaseId(TowerType.BeastHandler, false))).SelectMany((TowerModel model) => (IEnumerable<TowerModel>)MonoLinqHelper.ToArray<TowerModel>(((Model)model).GetDescendants<TowerModel>())).SelectMany((TowerModel model) => (IEnumerable<BeastHandlerPetModel>)MonoLinqHelper.ToArray<BeastHandlerPetModel>(((Model)model).GetDescendants<BeastHandlerPetModel>())))
			{
				item.requiredCount = 0;
			}
		}
	}
	public class BetterArmorPiercingDarts : ToggleableTweak
	{
		protected override bool DefaultEnabled => false;

		public override string Description => "Makes Monkey Subs with the Armor Piercing Darts upgrade to be able to pop Lead Bloons";

		protected override string Icon => "89a459fa46fc4c6419f64888fb30cfa7";

		public override void OnNewGameModel(GameModel gameModel)
		{
			//IL_005a: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			foreach (TowerModel item in from model in Il2CppGenericIEnumerable.AsIEnumerable<TowerModel>(gameModel.GetTowersWithBaseId(TowerType.MonkeySub, false))
				where ((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("Armor Piercing Darts")
				select model)
			{
				DamageModel damageModel = ProjectileModelExt.GetDamageModel(TowerModelExt.GetWeapon(item).projectile);
				damageModel.immuneBloonProperties = (BloonProperties)(damageModel.immuneBloonProperties & -2);
				damageModel.immuneBloonPropertiesOriginal = (BloonProperties)(damageModel.immuneBloonPropertiesOriginal & -2);
			}
		}
	}
	public class BetterCentralMarket : ToggleableTweak
	{
		[HarmonyPatch(typeof(CentralMarketBuff), "TestTower")]
		internal static class CentralMarketBuff_TestTower
		{
			[HarmonyPrefix]
			internal static bool Prefix(CentralMarketBuff __instance, Tower testTower)
			{
				if (!ModContent.GetInstance<BetterCentralMarket>().Enabled)
				{
					return true;
				}
				TowerModel val = default(TowerModel);
				if (testTower == ((TowerBehavior)__instance).tower || !Il2CppSystemObjectExt.Is<TowerModel>(testTower.towerModel, ref val) || val.CheckSet((TowerSet)8, false))
				{
					return false;
				}
				testTower.RemoveMutatorIncludeSubTowers((BehaviorMutator)(object)__instance.mutator);
				testTower.AddMutatorIncludeSubTowers((BehaviorMutator)(object)__instance.mutator, -1, true, true, false, true, -1);
				return false;
			}
		}

		[HarmonyPatch(typeof(CentralMarketBuff), "Attatched")]
		internal static class CentralMarketBuff_Attatched
		{
			[HarmonyPrefix]
			internal static void Prefix(CentralMarketBuff __instance)
			{
				if (ModContent.GetInstance<BetterCentralMarket>().Enabled)
				{
					Enumerator<Tower> enumerator = ((RootObject)__instance).Sim.factory.GetRaw<Tower>().list.GetEnumerator();
					while (enumerator.MoveNext())
					{
						Tower current = enumerator.Current;
						__instance.TestTower(current, ((TowerBehavior)__instance).tower.towerModel, 0f, 0);
					}
				}
			}
		}

		[HarmonyPatch(typeof(CentralMarketMutator), "Mutate")]
		internal static class CentralMarketMutator_CentralMarketMutator
		{
			public class CentralMarketDescription : ModTextOverride
			{
				public override string LocalizationKey => "Central Market Description";

				public override bool Active => ModContent.GetInstance<BetterCentralMarket>().Enabled;

				public override string TextValue => "Earns heaps of money each round and increases income generated by all non-Support towers by 10%.";
			}

			[HarmonyPostfix]
			internal static void Postfix(CentralMarketBuff __instance, Model model, ref bool __result)
			{
				if (!ModContent.GetInstance<BetterCentralMarket>().Enabled)
				{
					return;
				}
				float multiplier = __instance.centralMarketBuffModel.multiplier;
				float num = multiplier - 1f;
				foreach (CashModel item in Il2CppGenericIEnumerable.AsIEnumerable<CashModel>(model.GetDescendants<CashModel>()))
				{
					item.bonusMultiplier += num;
					__result = true;
				}
				foreach (CashPerTowerInRangeModel item2 in Il2CppGenericIEnumerable.AsIEnumerable<CashPerTowerInRangeModel>(model.GetDescendants<CashPerTowerInRangeModel>()))
				{
					item2.baseCash *= multiplier;
					for (int i = 0; i < ((Il2CppArrayBase<float>)(object)item2.extraCashPerTier).Count; i++)
					{
						Il2CppStructArray<float> extraCashPerTier = item2.extraCashPerTier;
						int num2 = i;
						((Il2CppArrayBase<float>)(object)extraCashPerTier)[num2] = ((Il2CppArrayBase<float>)(object)extraCashPerTier)[num2] * multiplier;
					}
					__result = true;
				}
				foreach (IncreaseBloonWorthModel item3 in Il2CppGenericIEnumerable.AsIEnumerable<IncreaseBloonWorthModel>(model.GetDescendants<IncreaseBloonWorthModel>()))
				{
					if (item3.cash > 0f)
					{
						item3.cash *= multiplier;
					}
					else
					{
						item3.cashMultiplier *= multiplier;
					}
					__result = true;
				}
				foreach (MoabTakedownModel item4 in Il2CppGenericIEnumerable.AsIEnumerable<MoabTakedownModel>(model.GetDescendants<MoabTakedownModel>()))
				{
					item4.multiplier *= multiplier;
					__result = true;
				}
				foreach (EatBloonModel item5 in Il2CppGenericIEnumerable.AsIEnumerable<EatBloonModel>(model.GetDescendants<EatBloonModel>()))
				{
					item5.rbeCashMultiplier *= multiplier;
					__result = true;
				}
				foreach (WallOfTreesModel item6 in Il2CppGenericIEnumerable.AsIEnumerable<WallOfTreesModel>(model.GetDescendants<WallOfTreesModel>()))
				{
					item6.rbeCashMultiplier *= multiplier;
					__result = true;
				}
			}
		}

		protected override bool DefaultEnabled => false;

		public override string Description => "Makes the Central Market buff affect all non-Support towers' income generation not just Merchantmen.";

		protected override string Icon => "6b345ca20df5d40308baf66c662f6e33";
	}
	public class BetterEziliTotem : ToggleableTweak
	{
		protected override bool DefaultEnabled => false;

		public override string Description => "Makes Ezili's Sacrificial Totem not cost any lives";

		protected override string Icon => "6316d713002ae4bfab93838017b598ee";

		public override void OnNewGameModel(GameModel gameModel)
		{
			if (!base.Enabled)
			{
				return;
			}
			for (int i = 7; i <= 20; i++)
			{
				TowerModel heroWithNameAndLevel = gameModel.GetHeroWithNameAndLevel(TowerType.Ezili, i, false);
				AbilityModel val = ((IEnumerable<AbilityModel>)TowerModelExt.GetAbilities(heroWithNameAndLevel)).FirstOrDefault((Func<AbilityModel, bool>)((AbilityModel b) => ((Model)b).name.Contains("Totem")));
				if (val != null)
				{
					val.livesCost = 0;
				}
			}
		}
	}
	public class BetterLaserBlasts : ToggleableTweak
	{
		protected override bool DefaultEnabled => false;

		public override string Description => "Makes the Laser Blasts upgrade give a minor Attack Speed buff for Super Monkeys. Plasma Blasts unaffected.\r\nRates for 0/0/0, 1/0/0, 2/0/0: .045, 0.45, .03 -> .045, .04, .03";

		protected override string Icon => "1e6e95d36ce3cc54ba1920cfa5378360";

		public override void OnNewGameModel(GameModel gameModel)
		{
			if (!base.Enabled)
			{
				return;
			}
			foreach (TowerModel item in ((IEnumerable<TowerModel>)Enumerable.ToArray<TowerModel>(gameModel.GetTowersWithBaseId(TowerType.SuperMonkey, false))).Where((TowerModel model) => ((Il2CppArrayBase<int>)(object)model.tiers)[0] == 1))
			{
				TowerModel tower = gameModel.GetTower(TowerType.SuperMonkey, 0, ((Il2CppArrayBase<int>)(object)item.tiers)[1], ((Il2CppArrayBase<int>)(object)item.tiers)[2]);
				TowerModel tower2 = gameModel.GetTower(TowerType.SuperMonkey, 2, ((Il2CppArrayBase<int>)(object)item.tiers)[1], ((Il2CppArrayBase<int>)(object)item.tiers)[2]);
				float rate = ((Il2CppArrayBase<WeaponModel>)(object)TowerModelExt.GetAttackModel(tower).weapons)[0].Rate;
				float rate2 = ((Il2CppArrayBase<WeaponModel>)(object)TowerModelExt.GetAttackModel(tower2).weapons)[0].Rate;
				((Il2CppArrayBase<WeaponModel>)(object)TowerModelExt.GetAttackModel(item).weapons)[0].Rate = (rate * 2f + rate2) / 3f;
			}
		}
	}
	public class BetterMonkeyCity : ToggleableTweak
	{
		[HarmonyPatch(typeof(MutatorTower), "Mutate")]
		internal static class MonkeyCityIncomeSupport_Mutate
		{
			[HarmonyPostfix]
			internal static void Postfix(MutatorTower __instance, Model model, ref bool __result)
			{
				if (!ModContent.GetInstance<BetterMonkeyCity>().Enabled)
				{
					return;
				}
				foreach (IncreaseBloonWorthModel item in Il2CppGenericIEnumerable.AsIEnumerable<IncreaseBloonWorthModel>(model.GetDescendants<IncreaseBloonWorthModel>()))
				{
					if (item.cash > 0f)
					{
						item.cash *= __instance.multiplier;
					}
					else
					{
						item.cashMultiplier *= __instance.multiplier;
					}
					__result = true;
				}
				foreach (ImfLoanModel item2 in Il2CppGenericIEnumerable.AsIEnumerable<ImfLoanModel>(model.GetDescendants<ImfLoanModel>()))
				{
					item2.amount *= __instance.multiplier;
					item2.imfLoanCollection.amount = item2.amount;
					__result = true;
				}
				foreach (MoabTakedownModel item3 in Il2CppGenericIEnumerable.AsIEnumerable<MoabTakedownModel>(model.GetDescendants<MoabTakedownModel>()))
				{
					item3.multiplier *= __instance.multiplier;
					__result = true;
				}
			}
		}

		protected override bool DefaultEnabled => false;

		public override string Description => "Makes the Monkey City income buff affect more things, including Lead to Gold, IMF Loan, Monkey-Nomics, Monkey Pirates, and similar effects.";

		protected override string Icon => "92d1f357799f3407b99ac503dbf8b36f";
	}
	public class BetterTrojan : ToggleableTweak
	{
		[HarmonyPatch(typeof(BloonWorthMutator), "Mutate")]
		internal static class IncreaseBloonWorthWithTierModel_BloonWorthMutator_Mutate
		{
			[HarmonyPrefix]
			internal static void Prefix(Model model, Model baseModel, ref int __state)
			{
				BloonModel val = default(BloonModel);
				BloonModel val2 = default(BloonModel);
				if (ModContent.GetInstance<BetterTrojan>().Enabled && Il2CppSystemObjectExt.Is<BloonModel>((Il2CppObjectBase)(object)model, ref val) && Il2CppSystemObjectExt.Is<BloonModel>((Il2CppObjectBase)(object)baseModel, ref val2))
				{
					__state = val.layerNumber;
					val.layerNumber = (int)val2.GetTotalLayers(InGame.Bridge.Model);
				}
			}

			[HarmonyPostfix]
			internal static void Postfix(Model model, ref int __state)
			{
				BloonModel val = default(BloonModel);
				if (ModContent.GetInstance<BetterTrojan>().Enabled && Il2CppSystemObjectExt.Is<BloonModel>((Il2CppObjectBase)(object)model, ref val))
				{
					val.layerNumber = __state;
				}
			}
		}

		protected override bool DefaultEnabled => false;

		public override string Description => "Makes Benjamin's Bloon Trojan use the real internal layer count for Bloons so that it no longer loses money.";

		protected override string Icon => "3f5b06699342a46498a873362b0aa85a";
	}
	public class BrickellMermonkeys : ToggleableTweak
	{
		protected override bool DefaultEnabled => true;

		public override string Description => "Makes Brickell's effects apply to non-exclusively water based towers again.";

		protected override string Icon => "dc1d82f5e96b24e4bab87e09a9f47866";

		public override void OnNewGameModel(GameModel gameModel)
		{
			if (!base.Enabled)
			{
				return;
			}
			FilterTowerByPlaceableAreaModel val = default(FilterTowerByPlaceableAreaModel);
			foreach (TowerModel item in (Il2CppArrayBase<TowerModel>)(object)gameModel.towers)
			{
				if (((EntityModel)item).baseId != TowerType.AdmiralBrickell)
				{
					continue;
				}
				List<TowerFilterModel> filters = new List<TowerFilterModel>();
				Il2CppGenericIEnumerable.ForEach<Model>(((Model)item).GetDescendants<Model>(), (Action<Model>)delegate(Model model)
				{
					ActivateRateSupportZoneModel val2 = default(ActivateRateSupportZoneModel);
					if (Il2CppSystemObjectExt.Is<ActivateRateSupportZoneModel>((Il2CppObjectBase)(object)model, ref val2))
					{
						filters.AddRange((IEnumerable<TowerFilterModel>)val2.filters);
					}
					ActivatePierceSupportZoneModel val3 = default(ActivatePierceSupportZoneModel);
					if (Il2CppSystemObjectExt.Is<ActivatePierceSupportZoneModel>((Il2CppObjectBase)(object)model, ref val3))
					{
						filters.AddRange((IEnumerable<TowerFilterModel>)val3.filters);
					}
					ActivateTowerDamageSupportZoneModel val4 = default(ActivateTowerDamageSupportZoneModel);
					if (Il2CppSystemObjectExt.Is<ActivateTowerDamageSupportZoneModel>((Il2CppObjectBase)(object)model, ref val4))
					{
						filters.AddRange((IEnumerable<TowerFilterModel>)val4.filters);
					}
					ActivateVisibilitySupportZoneModel val5 = default(ActivateVisibilitySupportZoneModel);
					if (Il2CppSystemObjectExt.Is<ActivateVisibilitySupportZoneModel>((Il2CppObjectBase)(object)model, ref val5))
					{
						filters.AddRange((IEnumerable<TowerFilterModel>)val5.filters);
					}
					PierceSupportModel val6 = default(PierceSupportModel);
					if (Il2CppSystemObjectExt.Is<PierceSupportModel>((Il2CppObjectBase)(object)model, ref val6))
					{
						filters.AddRange((IEnumerable<TowerFilterModel>)((SupportModel)val6).filters);
					}
				});
				foreach (TowerFilterModel item2 in filters)
				{
					if (Il2CppSystemObjectExt.Is<FilterTowerByPlaceableAreaModel>((Il2CppObjectBase)(object)item2, ref val))
					{
						val.exclusive = false;
					}
				}
			}
		}
	}
	public class BuffableParagons : ToggleableTweak
	{
		[HarmonyPatch(typeof(Tower), "IsParagonBased")]
		internal static class Tower_IsParagonBased
		{
			[HarmonyPrefix]
			internal static bool Prefix(ref bool __result)
			{
				if (!ModContent.GetInstance<BuffableParagons>().Enabled)
				{
					return true;
				}
				__result = false;
				return false;
			}
		}

		[HarmonyPatch(typeof(ParagonTower), "Finish")]
		internal static class ParagonTower_Finish
		{
			[HarmonyPostfix]
			internal static void Postfix(ParagonTower __instance)
			{
				if (!ModContent.GetInstance<BuffableParagons>().Enabled)
				{
					return;
				}
				foreach (Tower item in MonoLinqHelper.ToArray<Tower>(((RootObject)__instance).Sim.towerManager.GetTowers()))
				{
					Action onSuspendedChanged = ((CommonBehaviorProxy<ITowerBehavior>)(object)item).onSuspendedChanged;
					if (onSuspendedChanged != null)
					{
						onSuspendedChanged.Invoke();
					}
				}
			}
		}

		[HarmonyPatch(typeof(TapTowerAbilityBehavior), "IsBanned")]
		internal static class TapTowerAbilityBehavior_IsBanned
		{
			[HarmonyPrefix]
			internal static void Prefix(Tower tower, ref bool __state)
			{
				if (ModContent.GetInstance<BuffableParagons>().Enabled)
				{
					__state = tower.towerModel.isParagon;
					tower.towerModel.isParagon = false;
				}
			}

			[HarmonyPostfix]
			internal static void Postfix(Tower tower, ref bool __state)
			{
				if (ModContent.GetInstance<BuffableParagons>().Enabled)
				{
					tower.towerModel.isParagon = __state;
				}
			}
		}

		[HarmonyPatch(typeof(BrewTargetting), "FilterTower")]
		internal static class BrewTargetting_FilterTower
		{
			[HarmonyPrefix]
			internal static void Prefix(Tower tower, ref bool __state)
			{
				if (ModContent.GetInstance<BuffableParagons>().Enabled)
				{
					__state = tower.towerModel.isParagon;
					tower.towerModel.isParagon = false;
				}
			}

			[HarmonyPostfix]
			internal static void Postfix(Tower tower, ref bool __state)
			{
				if (ModContent.GetInstance<BuffableParagons>().Enabled)
				{
					tower.towerModel.isParagon = __state;
				}
			}
		}

		[HarmonyPatch]
		internal static class TargetFriendly_GetTargets
		{
			private static IEnumerable<MethodBase> TargetMethods()
			{
				yield return MoreAccessTools.SafeGetNestedClassMethod(typeof(TargetFriendly), "GetTargets", "MoveNext", 0);
			}

			[HarmonyPrefix]
			internal static void Prefix(ref Tower[] __state)
			{
				if (ModContent.GetInstance<BuffableParagons>().Enabled)
				{
					__state = ((IEnumerable<Tower>)MonoLinqHelper.ToArray<Tower>(InGame.Bridge.Simulation.factory.GetUncast<Tower>())).Where((Tower tower) => tower.towerModel.isParagon).ToArray();
					Tower[] array = __state;
					foreach (Tower val in array)
					{
						val.towerModel.isParagon = false;
					}
				}
			}

			[HarmonyPostfix]
			internal static void Postfix(ref Tower[] __state)
			{
				if (ModContent.GetInstance<BuffableParagons>().Enabled)
				{
					Tower[] array = __state;
					foreach (Tower val in array)
					{
						val.towerModel.isParagon = true;
					}
				}
			}
		}

		[HarmonyPatch(typeof(Tower), "AddParagonMutator")]
		internal static class Tower_AddParagonMutator
		{
			[HarmonyPrefix]
			internal static bool Prefix(Tower __instance, BehaviorMutator mutator, int time, bool updateDuration, bool applyMutation, bool onlyTimeoutWhenActive, bool useRoundTime, int roundsRemaining)
			{
				if (!ModContent.GetInstance<BuffableParagons>().Enabled || !__instance.towerModel.isParagon)
				{
					return true;
				}
				((Mutable)__instance).AddMutator(mutator, time, updateDuration, applyMutation, onlyTimeoutWhenActive, useRoundTime, false, false, false, roundsRemaining, false, false);
				return false;
			}
		}

		[HarmonyPatch(typeof(Tower), "AddParagonMutatorFromParent")]
		internal static class Tower_AddParagonMutatorFromParent
		{
			[HarmonyPrefix]
			internal static bool Prefix(Tower __instance, BehaviorMutator mutator, int time, bool updateDuration, bool applyMutation, bool onlyTimeoutWhenActive, bool useRoundTime, int roundsRemaining)
			{
				if (!ModContent.GetInstance<BuffableParagons>().Enabled || !__instance.towerModel.isParagon)
				{
					return true;
				}
				__instance.AddMutatorFromParent(mutator, time, updateDuration, applyMutation, onlyTimeoutWhenActive, useRoundTime, roundsRemaining);
				return false;
			}
		}

		[HarmonyPatch(typeof(Tower), "AddParagonMutatorIncludeSubTowers")]
		internal static class Tower_AddParagonMutatorIncludeSubTowers
		{
			[HarmonyPrefix]
			internal static bool Prefix(Tower __instance, BehaviorMutator mutator, int time, bool updateDuration, bool applyMutation, bool onlyTimeoutWhenActive, bool useRoundTime, int roundsRemaining)
			{
				if (!ModContent.GetInstance<BuffableParagons>().Enabled || !__instance.towerModel.isParagon)
				{
					return true;
				}
				__instance.AddMutatorIncludeSubTowers(mutator, time, updateDuration, applyMutation, onlyTimeoutWhenActive, useRoundTime, roundsRemaining);
				return false;
			}
		}

		protected override float RegistrationPriority => -1f;

		protected override bool DefaultEnabled => false;

		public override string Description => "Makes Paragons able to receive buffs like normal towers.";

		protected override string Icon => "Ui[ParagonPip]";

		public override void OnNewGameModel(GameModel gameModel)
		{
			if (base.Enabled)
			{
				Il2CppGenericIEnumerable.ForEach<SupportModel>(((Model)gameModel.GetParagonTower(TowerType.BoomerangMonkey)).GetDescendants<SupportModel>(), (Action<SupportModel>)delegate(SupportModel model)
				{
					model.onlyAffectParagon = false;
				});
			}
		}
	}
	public class DartlingGunnerTargeting : ToggleableTweak
	{
		[HarmonyPatch(typeof(RotateToPointer), "SetRotation")]
		internal static class RotateToPointer_SetRotation
		{
			[HarmonyPrefix]
			internal static bool Prefix(RotateToPointer __instance)
			{
				Attack attack = ((AttackBehavior)__instance).attack;
				TargetSupplier val = default(TargetSupplier);
				if (!ModContent.GetInstance<DartlingGunnerTargeting>().Enabled || !Il2CppSystemObjectExt.Is<TargetSupplier>(attack.activeTargetSupplier, ref val))
				{
					return true;
				}
				bool flag = false;
				bool flag2 = false;
				Enumerator<AttackBehavior> enumerator = attack.attackBehaviors.GetEnumerator();
				while (enumerator.MoveNext())
				{
					AttackBehavior current = enumerator.Current;
					flag |= Il2CppSystemObjectExt.Is<RotateToPointer>((Il2CppObjectBase)(object)current);
					flag2 |= Il2CppSystemObjectExt.Is<RotateToTarget>((Il2CppObjectBase)(object)current);
				}
				if (!flag || !flag2)
				{
					return true;
				}
				bool flag3 = Il2CppSystemObjectExt.Is<TargetFirst>((Il2CppObjectBase)(object)val) || Il2CppSystemObjectExt.Is<TargetLast>((Il2CppObjectBase)(object)val) || Il2CppSystemObjectExt.Is<TargetClose>((Il2CppObjectBase)(object)val) || Il2CppSystemObjectExt.Is<TargetStrong>((Il2CppObjectBase)(object)val) || Il2CppSystemObjectExt.Is<TargetCamo>((Il2CppObjectBase)(object)val);
				return !flag3;
			}
		}

		[HarmonyPatch(typeof(RotateToTarget), "ApplyRotation")]
		internal static class RotateToTarget_ApplyRotation
		{
			[HarmonyPrefix]
			internal static bool Prefix(RotateToTarget __instance)
			{
				Attack attack = ((AttackBehavior)__instance).attack;
				TargetSupplier val = default(TargetSupplier);
				if (!ModContent.GetInstance<DartlingGunnerTargeting>().Enabled || !Il2CppSystemObjectExt.Is<TargetSupplier>(attack.activeTargetSupplier, ref val))
				{
					return true;
				}
				bool flag = false;
				bool flag2 = false;
				Enumerator<AttackBehavior> enumerator = attack.attackBehaviors.GetEnumerator();
				while (enumerator.MoveNext())
				{
					AttackBehavior current = enumerator.Current;
					flag |= Il2CppSystemObjectExt.Is<RotateToPointer>((Il2CppObjectBase)(object)current);
					flag2 |= Il2CppSystemObjectExt.Is<RotateToTarget>((Il2CppObjectBase)(object)current);
				}
				if (!flag || !flag2)
				{
					return true;
				}
				return Il2CppSystemObjectExt.Is<TargetFirst>((Il2CppObjectBase)(object)val) || Il2CppSystemObjectExt.Is<TargetLast>((Il2CppObjectBase)(object)val) || Il2CppSystemObjectExt.Is<TargetClose>((Il2CppObjectBase)(object)val) || Il2CppSystemObjectExt.Is<TargetStrong>((Il2CppObjectBase)(object)val) || Il2CppSystemObjectExt.Is<TargetCamo>((Il2CppObjectBase)(object)val);
			}
		}

		protected override bool DefaultEnabled => true;

		public override string Description => "Gives all Dartling Gunners First/Last/Close/Strong targeting";

		protected override ModSettingCategory Category => TacticalTweaksMod.Targeting;

		protected override string Icon => "MonkeyIcons[DartlingGunnerIcon]";

		protected override string DisableIfModPresent => "MegaKnowledge";

		public override void OnNewGameModel(GameModel gameModel)
		{
			if (!base.Enabled)
			{
				return;
			}
			foreach (TowerModel item in ((IEnumerable<TowerModel>)gameModel.towers).Where((TowerModel model) => ((EntityModel)model).baseId == TowerType.DartlingGunner && !((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("Bloon Area Denial System")))
			{
				AttackModel attackModel = TowerModelExt.GetAttackModel(item);
				bool value = !((Il2CppArrayBase<string>)(object)item.appliedUpgrades).Contains("Ray of Doom") && !((Il2CppArrayBase<string>)(object)item.appliedUpgrades).Contains("Buckshot");
				TacticalTweaksMod.UpdatePointer(attackModel, value);
				TacticalTweaksMod.AddAllTargets(attackModel);
				item.UpdateTargetProviders();
			}
		}
	}
	public class EliteDefenderTargetSwitch : ToggleableTweak
	{
		[HarmonyPatch(typeof(Ability), "Activate")]
		internal static class Ability_Activate
		{
			[HarmonyPostfix]
			internal static void Postfix(Ability __instance)
			{
				if (ModContent.GetInstance<EliteDefenderTargetSwitch>().Enabled)
				{
					AbilityModel abilityModel = __instance.abilityModel;
					if (((abilityModel != null) ? abilityModel.displayName : null) == "Retaliation")
					{
						((TowerBehavior)__instance).tower.SetTargetType(TargetType.first);
					}
				}
			}
		}

		protected override bool DefaultEnabled => false;

		public override string Description => "An Elite Defender will switch to First targeting after a Bloon leak activates its ability.";

		protected override string Icon => "c9cb42be6c73344b0bd7757d4201de65";

		protected override ModSettingCategory Category => TacticalTweaksMod.Targeting;
	}
	public class EtienneTargeting : ToggleableTweak
	{
		protected override bool DefaultEnabled => false;

		public override string Description => "Replaces Etienne's targeting options with the standard Fist, Last, Close Strong.";

		protected override string Icon => "MonkeyIcons[EtienneIcon]";

		protected override ModSettingCategory Category => TacticalTweaksMod.Targeting;

		public override void OnNewGameModel(GameModel gameModel)
		{
			//IL_004b: 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_005d: Expected O, but got Unknown
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			if (!base.Enabled)
			{
				return;
			}
			foreach (TowerModel item in Il2CppGenericIEnumerable.AsIEnumerable<TowerModel>(gameModel.GetTowersWithBaseId(TowerType.Etienne, false)))
			{
				AttackModel attackModel = TowerModelExt.GetAttackModel(item);
				AttackModelBehaviorExt.RemoveBehaviors<TargetDivideAndConquerModel>(attackModel);
				AttackModelBehaviorExt.RemoveBehaviors<TargetZoneDefenceModel>(attackModel);
				AttackModelBehaviorExt.AddBehavior<TargetLastModel>(attackModel, CreateTargetLastModelExt.Create(new Args
				{
					isSelectable = true
				}));
				AttackModelBehaviorExt.AddBehavior<TargetCloseModel>(attackModel, CreateTargetCloseModelExt.Create(new Args
				{
					isSelectable = true
				}));
				AttackModelBehaviorExt.AddBehavior<TargetStrongModel>(attackModel, CreateTargetStrongModelExt.Create(new Args
				{
					isSelectable = true
				}));
				item.UpdateTargetProviders();
			}
		}
	}
	public class FixIceMonkeyParagon : TacticalTweak
	{
		public override void OnNewGameModel(GameModel gameModel)
		{
			TowerModel paragonTower = gameModel.GetParagonTower(TowerType.IceMonkey);
			AbilityModel ability = TowerModelExt.GetAbility(paragonTower);
			if (ability != null)
			{
				AgeModel descendant = ((Model)ability).GetDescendant<AgeModel>();
				if (descendant != null)
				{
					descendant.rounds = 999999;
				}
			}
		}
	}
	public class HeroBoostDebt : ToggleableTweak
	{
		[HarmonyPatch(typeof(TowerSelectionMenu), "UpdateHeroBooster")]
		internal static class TowerSelectionMenu_UpdateHeroBooster
		{
			[HarmonyPostfix]
			internal static void Postfix(TowerSelectionMenu __instance)
			{
				if (ModContent.GetInstance<HeroBoostDebt>().Enabled)
				{
					__instance.heroBoosterButtonText.SetText("▼$");
					if (IEnumerableExt.OfIl2CppType<ImfLoanCollection>((IEnumerable)__instance.Bridge.simulation.GetBehaviors().ToArray()).Any())
					{
						((Selectable)__instance.heroBoosterButton).interactable = false;
					}
				}
			}
		}

		[HarmonyPatch(typeof(TowerSelectionMenu), "OnHeroBoosterButtonClicked")]
		internal static class TowerSelectionMenu_OnHeroBoosterButtonClicked
		{
			[HarmonyPrefix]
			internal static bool Prefix(TowerSelectionMenu __instance)
			{
				if (!ModContent.GetInstance<HeroBoostDebt>().Enabled)
				{
					return true;
				}
				TowerToSimulation tower = __instance.selectedTower;
				PopupScreen.instance.ShowPopup((Placement)0, "Hero Boost Debt", $"Do you want to boost to level {tower.hero.level + 1}?\nYou will gain a debt of ${tower.hero.costToLevelUp:N0}", ReturnCallback.op_Implicit((Action)delegate
				{
					//IL_0012: 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_0068: Unknown result type (might be due to invalid IL or missing references)
					//IL_0073: Expected O, but got Unknown
					//IL_0074: Unknown result type (might be due to invalid IL or missing references)
					//IL_0080: Unknown result type (might be due to invalid IL or missing references)
					//IL_009c: Expected O, but got Unknown
					__instance.Bridge.UpgradeHeroToLevel(tower.Id, Action<bool>.op_Implicit((Action<bool>)delegate
					{
					}), tower.hero.level + 1);
					Simulation simulation = __instance.Bridge.Simulation;
					Args val = new Args();
					((ModelArgs<ImfLoanCollectionModel>)val).name = "HeroBoostDebt";
					val.collectionRate = 0.5f;
					val.amount = tower.hero.costToLevelUp;
					simulation.AddBehavior<ImfLoanCollection>((SimulationBehaviorModel)(object)CreateImfLoanCollectionModelExt.Create(val));
					__instance.UpdateHeroBooster(tower);
				}), "Yes", ReturnCallback.op_Implicit((Action)delegate
				{
					__instance.UpdateHeroBooster(tower);
				}), "No", (TransitionAnim)1, (BackGround)0, false, false);
				return false;
			}
		}

		protected override bool DefaultEnabled => true;

		public override string Description => "Replaces the Monkey Money Hero Boost with a button that lets you purchase the next level up of the hero by going into debt.";

		protected override string Icon => "9419ea792c2a1344c8e538f00d4537a5";
	}
	public class MoreUnfreezableTowers : ToggleableTweak
	{
		[HarmonyPatch(typeof(ApplyTowerFreeze), "FreezeTower")]
		internal static class ApplyTowerFreeze_FreezeTower
		{
			[HarmonyPrefix]
			internal static bool Prefix(ApplyTowerFreeze __instance, ObjectId towerID)
			{
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				if (!ModContent.GetInstance<MoreUnfreezableTowers>().Enabled)
				{
					return true;
				}
				Tower towerById = ((RootObject)__instance).Sim.towerManager.GetTowerById(towerID);
				TowerModel towerModel = towerById.towerModel;
				Il2CppStringArray appliedUpgrades = towerModel.appliedUpgrades;
				int result;
				if (appliedUpgrades == null || !((Il2CppArrayBase<string>)(object)appliedUpgrades).Contains("Ring of Fire"))
				{
					Il2CppStringArray appliedUpgrades2 = towerModel.appliedUpgrades;
					if (appliedUpgrades2 == null || !((Il2CppArrayBase<string>)(object)appliedUpgrades2).Contains("Signal Flare"))
					{
						Il2CppStringArray appliedUpgrades3 = towerModel.appliedUpgrades;
						if (appliedUpgrades3 == null || !((Il2CppArrayBase<string>)(object)appliedUpgrades3).Contains("Dragon's Breath"))
						{
							Il2CppStringArray appliedUpgrades4 = towerModel.appliedUpgrades;
							if (appliedUpgrades4 == null || !((Il2CppArrayBase<string>)(object)appliedUpgrades4).Contains("Tidal Chill"))
							{
								Il2CppStringArray appliedUpgrades5 = towerModel.appliedUpgrades;
								if ((appliedUpgrades5 == null || !((Il2CppArrayBase<string>)(object)appliedUpgrades5).Contains("The Blazing Sun")) && ((EntityModel)towerModel).baseId != TowerType.Gwendolin)
								{
									result = ((towerById.towerSkinName != "Fusty the Snowman") ? 1 : 0);
									goto IL_00e6;
								}
							}
						}
					}
				}
				result = 0;
				goto IL_00e6;
				IL_00e6:
				return (byte)result != 0;
			}
		}

		[HarmonyPatch(typeof(PyrotechnicsSupportFilter), "FilterTowerModel")]
		internal static class PyrotechnicsSupportFilter_FilterTowerModel
		{
			[HarmonyPostfix]
			internal static void Postfix(TowerModel towerModel, ref bool __result)
			{
				__result |= ((EntityModel)towerModel).baseId == TowerType.Desperado && (((Il2CppArrayBase<string>)(object)towerModel.appliedUpgrades)?.Contains("The Blazing Sun") ?? false);
			}
		}

		protected override bool DefaultEnabled => true;

		public override string Description => "Fire Towers and certain other Ice Towers also no longer get frozen on Glacial Trail.\r\nThis includes: Gwen (Any Skin), Fusty the Snowman, Ring of Fire Tack Shooters, Dragon's Breath Wizards, Signal Flare Mortar Monkeys, Tidal Chill Mermonkeys, The Blazing Sun.";

		protected override string Icon => "MapImages[MapSelectGlacialTrailButton]";
	}
	public class MortarMonkeyTargeting : ToggleableTweak
	{
		protected override bool DefaultEnabled => true;

		public override string Description => "Gives all Mortar Monkeys First/Last/Close/Strong targeting";

		protected override ModSettingCategory Category => TacticalTweaksMod.Targeting;

		protected override string Icon => "MonkeyIcons[MortarMonkeyIcon]";

		protected override string DisableIfModPresent => "MegaKnowledge";

		public override void OnNewGameModel(GameModel gameModel)
		{
			if (!base.Enabled)
			{
				return;
			}
			foreach (TowerModel item in ((IEnumerable<TowerModel>)gameModel.towers).Where((TowerModel model) => ((EntityModel)model).baseId == TowerType.MortarMonkey))
			{
				AttackModel attackModel = TowerModelExt.GetAttackModel(item);
				TacticalTweaksMod.AddAllTargets(attackModel);
				item.towerSelectionMenuThemeId = "ActionButton";
				item.UpdateTargetProviders();
			}
		}
	}
	public class ObynBuffsGlobal : ToggleableTweak
	{
		protected override bool DefaultEnabled => false;

		public override string Description => "Makes Obyn's buff apply to all Druids, not just ones within range.";

		protected override string Icon => "UiBuffIcons[BuffIconObynLevel11]";

		public override void OnNewGameModel(GameModel gameModel)
		{
			foreach (TowerModel item in Il2CppGenericIEnumerable.AsIEnumerable<TowerModel>(gameModel.GetTowersWithBaseId(TowerType.ObynGreenfoot, false)))
			{
				foreach (SupportModel behavior in TowerModelBehaviorExt.GetBehaviors<SupportModel>(item))
				{
					behavior.isGlobal = true;
				}
			}
		}
	}
	public class ObynPriceTweak : ToggleableTweak
	{
		protected override bool DefaultEnabled => false;

		public override string Description => "Changes Obyn's base price so that he's able to be used as a CHIMPs start like he used to be.";

		protected override string Icon => "MonkeyIcons[ObynGreenFootIcon]";

		public override void OnNewGameModel(GameModel gameModel)
		{
			TowerModel towerWithName = gameModel.GetTowerWithName(TowerType.Sauda);
			foreach (TowerModel item in Il2CppGenericIEnumerable.AsIEnumerable<TowerModel>(gameModel.GetTowersWithBaseId(TowerType.ObynGreenfoot, false)))
			{
				item.cost = towerWithName.cost;
			}
		}
	}
	public class OverclockBanks : ToggleableTweak
	{
		[HarmonyPatch(typeof(OverclockMutator), "Mutate")]
		internal static class OverclockMutator_Mutate
		{
			[HarmonyPostfix]
			internal static void Postfix(OverclockMutator __instance, Model model)
			{
				TowerModel towerModel = default(TowerModel);
				if (ModContent.GetInstance<OverclockBanks>().Enabled && Il2CppSystemObjectExt.Is<TowerModel>((Il2CppObjectBase)(object)model, ref towerModel))
				{
					Apply(towerModel, __instance.overclockModel.rateModifier);
				}
			}
		}

		[HarmonyPatch(typeof(OverclockPermanentMutator), "Mutate")]
		internal static class OverclockPermanentModel_Mutate
		{
			[HarmonyPostfix]
			internal static void Postfix(OverclockPermanentMutator __instance, Model model)
			{
				TowerModel towerModel = default(TowerModel);
				if (ModContent.GetInstance<OverclockMonkeyopolis>().Enabled && Il2CppSystemObjectExt.Is<TowerModel>((Il2CppObjectBase)(object)model, ref towerModel))
				{
					float rateModifier = 1f - (float)__instance.stacks * (1f - __instance.overclockPermanentModel.rateModifier);
					Apply(towerModel, rateModifier);
				}
			}
		}

		protected override bool DefaultEnabled => true;

		public override string Description => "Makes the Overclock buff affect the interest rates of Monkey Banks.";

		protected override string Icon => "01a32a1a35c684d6a8d137b62d3a7f1b";

		protected override ModSettingCategory Category => TacticalTweaksMod.Overclock;

		public static void Apply(TowerModel towerModel, float rateModifier)
		{
			foreach (BankModel item in Il2CppGenericIEnumerable.AsIEnumerable<BankModel>(((Model)towerModel).GetDescendants<BankModel>()))
			{
				item.interest /= rateModifier;
			}
		}
	}
	public class OverclockMonkeyopolis : ToggleableTweak
	{
		[HarmonyPatch(typeof(OverclockMutator), "Mutate")]
		internal static class OverclockMutator_Mutate
		{
			[HarmonyPostfix]
			internal static void Postfix(OverclockMutator __instance, Model model)
			{
				TowerModel towerModel = default(TowerModel);
				if (ModContent.GetInstance<OverclockMonkeyopolis>().Enabled && Il2CppSystemObjectExt.Is<TowerModel>((Il2CppObjectBase)(object)model, ref towerModel) && !(((EntityModel)towerModel).baseId == TowerType.BananaFarm))
				{
					Il2CppGenericIEnumerable.ForEach<EmissionsPerRoundFilterModel>(model.GetDescendants<EmissionsPerRoundFilterModel>(), (Action<EmissionsPerRoundFilterModel>)delegate(EmissionsPerRoundFilterModel filter)
					{
						MonkeyopolisModel val = default(MonkeyopolisModel);
						int num = (TowerModelBehaviorExt.HasBehavior<MonkeyopolisModel>(towerModel, ref val) ? val.cratesPerRound : filter.count);
						filter.count = Math.CeilToInt((float)num / __instance.overclockModel.rateModifier);
					});
				}
			}
		}

		[HarmonyPatch(typeof(OverclockPermanentMutator), "Mutate")]
		internal static class OverclockPermanentModel_Mutate
		{
			[HarmonyPostfix]
			internal static void Postfix(OverclockPermanentMutator __instance, Model model)
			{
				TowerModel towerModel = default(TowerModel);
				if (ModContent.GetInstance<OverclockMonkeyopolis>().Enabled && Il2CppSystemObjectExt.Is<TowerModel>((Il2CppObjectBase)(object)model, ref towerModel) && !(((EntityModel)towerModel).baseId == TowerType.BananaFarm))
				{
					float rateModifier = 1f - (float)__instance.stacks * (1f - __instance.overclockPermanentModel.rateModifier);
					Il2CppGenericIEnumerable.ForEach<EmissionsPerRoundFilterModel>(model.GetDescendants<EmissionsPerRoundFilterModel>(), (Action<EmissionsPerRoundFilterModel>)delegate(EmissionsPerRoundFilterModel filter)
					{
						MonkeyopolisModel val = default(MonkeyopolisModel);
						int num = (TowerModelBehaviorExt.HasBehavior<MonkeyopolisModel>(towerModel, ref val) ? val.cratesPerRound : filter.count);
						filter.count = Math.CeilToInt((float)num / rateModifier);
					});
				}
			}
		}

		[HarmonyPatch(typeof(EmissionMutator), "Mutate")]
		internal static class EmissionMutator_Mutate
		{
			[HarmonyPrefix]
			internal static void Prefix(EmissionMutator __instance, Model model, ref List<int> __state)
			{
				__state = ((IEnumerable<EmissionsPerRoundFilterModel>)Enumerable.ToArray<EmissionsPerRoundFilterModel>(model.GetDescendants<EmissionsPerRoundFilterModel>())).Select((EmissionsPerRoundFilterModel filter) => filter.count).ToList();
			}

			[HarmonyPostfix]
			internal static void Postfix(EmissionMutator __instance, Model model, ref List<int> __state)
			{
				foreach (var (val, num) in ((IEnumerable<EmissionsPerRoundFilterModel>)Enumerable.ToArray<EmissionsPerRoundFilterModel>(model.GetDescendants<EmissionsPerRoundFilterModel>())).Zip(__state))
				{
					val.count = Math.Max(num, val.count);
				}
			}
		}

		protected override bool DefaultEnabled => true;

		public override string Description => "Makes the Overclock buff affect Monkeyopolis income in the same way it affects Banana Farms.";

		protected override string Icon => "6bcf8dc34ff294fe5bdf6f358a6eb62f";

		protected override ModSettingCategory Category => TacticalTweaksMod.Overclock;
	}
	public class OverclockPeriodicAbilities : ToggleableTweak
	{
		[HarmonyPatch(typeof(OverclockMutator), "Mutate")]
		internal static class OverclockMutator_Mutate
		{
			[HarmonyPostfix]
			internal static void Postfix(OverclockMutator __instance, Model model)
			{
				if (!ModContent.GetInstance<OverclockPeriodicAbilities>().Enabled)
				{
					return;
				}
				float rateModifier = __instance.overclockModel.rateModifier;
				Il2CppGenericIEnumerable.ForEach<ActivateAbilityAfterIntervalModel>(model.GetDescendants<ActivateAbilityAfterIntervalModel>(), (Action<ActivateAbilityAfterIntervalModel>)delegate(ActivateAbilityAfterIntervalModel i)
				{
					if (!((Model)i).name.Contains("TechBotify"))
					{
						i.interval *= rateModifier;
						i.intervalFrames = Math.CeilToInt((float)i.intervalFrames * rateModifier);
					}
				});
			}
		}

		[HarmonyPatch(typeof(OverclockPermanentMutator), "Mutate")]
		internal static class OverclockPermanentModel_Mutate
		{
			[HarmonyPostfix]
			internal static void Postfix(OverclockPermanentMutator __instance, Model model)
			{
				if (!ModContent.GetInstance<OverclockPeriodicAbilities>().Enabled)
				{
					return;
				}
				float rateModifier = 1f - (float)__instance.stacks * (1f - __instance.overclockPermanentModel.rateModifier);
				Il2CppGenericIEnumerable.ForEach<ActivateAbilityAfterIntervalModel>(model.GetDescendants<ActivateAbilityAfterIntervalModel>(), (Action<ActivateAbilityAfterIntervalModel>)delegate(ActivateAbilityAfterIntervalModel i)
				{
					if (!((Model)i).name.Contains("TechBotify"))
					{
						i.interval *= rateModifier;
						i.intervalFrames = Math.CeilToInt((float)i.intervalFrames * rateModifier);
					}
				});
			}
		}

		protected override bool DefaultEnabled => true;

		public override string Description => "Makes the Overclock buff affect the frequency of periodic ability activations like Carpet of Spikes.";

		protected override string Icon => "beca93cfa6584443081618415fec9cb0";

		protected override ModSettingCategory Category => TacticalTweaksMod.Overclock;
	}
	public class OverlockCash : ToggleableTweak
	{
		[HarmonyPatch(typeof(OverclockMutator), "Mutate")]
		internal static class OverclockMutator_Mutate
		{
			[HarmonyPostfix]
			internal static void Postfix(OverclockMutator __instance, Model model)
			{
				TowerModel towerModel = default(TowerModel);
				if (ModContent.GetInstance<OverlockCash>().Enabled && Il2CppSystemObjectExt.Is<TowerModel>((Il2CppObjectBase)(object)model, ref towerModel))
				{
					float rateModifier = __instance.overclockModel.rateModifier;
					Apply(towerModel, rateModifier);
				}
			}
		}

		[HarmonyPatch(typeof(OverclockPermanentMutator), "Mutate")]
		internal static class OverclockPermanentModel_Mutate
		{
			[HarmonyPostfix]
			internal static void Postfix(OverclockPermanentMutator __instance, Model model)
			{
				TowerModel towerModel = default(TowerModel);
				if (ModContent.GetInstance<OverlockCash>().Enabled && Il2CppSystemObjectExt.Is<TowerModel>((Il2CppObjectBase)(object)model, ref towerModel))
				{
					float rateModifier = 1f - (float)__instance.stacks * (1f - __instance.overclockPermanentModel.rateModifier);
					Apply(towerModel, rateModifier);
				}
			}
		}

		protected override bool DefaultEnabled => true;

		public override string Description => "Makes the Overclock buff increase other forms of cash generation for towers such as from end of round or from abilities.";

		protected override string Icon => "a5a03704d4accd542a39454eba688fb5";

		protected override ModSettingCategory Category => TacticalTweaksMod.Overclock;

		public static void Apply(TowerModel towerModel, float rateModifier)
		{
			foreach (PerRoundCashBonusTowerModel item in Il2CppGenericIEnumerable.AsIEnumerable<PerRoundCashBonusTowerModel>(((Model)towerModel).GetDescendants<PerRoundCashBonusTowerModel>()))
			{
				item.cashPerRound /= rateModifier;
				item.cashRoundBonusMultiplier /= rateModifier;
			}
			foreach (ImfLoanModel item2 in Il2CppGenericIEnumerable.AsIEnumerable<ImfLoanModel>(((Model)towerModel).GetDescendants<ImfLoanModel>()))
			{
				item2.amount /= rateModifier;
			}
			foreach (CashPerTowerInRangeModel item3 in Il2CppGenericIEnumerable.AsIEnumerable<CashPerTowerInRangeModel>(((Model)towerModel).GetDescendants<CashPerTowerInRangeModel>()))
			{
				item3.baseCash /= rateModifier;
				for (int i = 0; i < ((Il2CppArrayBase<float>)(object)item3.extraCashPerTier).Count; i++)
				{
					Il2CppStructArray<float> extraCashPerTier = item3.extraCashPerTier;
					int num = i;
					((Il2CppArrayBase<float>)(object)extraCashPerTier)[num] = ((Il2CppArrayBase<float>)(object)extraCashPerTier)[num] / rateModifier;
				}
			}
			if (!(((EntityModel)towerModel).baseId != TowerType.BananaFarm) || !(((EntityModel)towerModel).baseId != TowerType.MonkeyVillage))
			{
				return;
			}
			foreach (CashModel item4 in Il2CppGenericIEnumerable.AsIEnumerable<CashModel>(((Model)towerModel).GetDescendants<CashModel>()))
			{
				item4.bonusMultiplier += 1f / rateModifier - 1f;
			}
		}
	}
	public class ParagonSentryTargeting : ToggleableTweak
	{
		protected override bool DefaultEnabled => true;

		public override string Description => "Gives the Master Builder's Green Sentry First/Last/Close/Strong/Locked targeting.";

		protected override ModSettingCategory Category => TacticalTweaksMod.Targeting;

		protected override string Icon => "b22553f1b304d274d9ea350eece10cce";

		public override void OnNewGameModel(GameModel gameModel)
		{
			if (base.Enabled)
			{
				TowerModel paragonTower = gameModel.GetParagonTower(TowerType.EngineerMonkey);
				TowerModel val = ModelExt.FindDescendant<TowerModel>((Model)(object)paragonTower, TowerType.SentryParagonGreen);
				AttackModel attackModel = TowerModelExt.GetAttackModel(val);
				TacticalTweaksMod.UpdatePointer(attackModel, false);
				TacticalTweaksMod.AddAllTargets(attackModel);
				val.UpdateTargetProviders();
			}
		}
	}
	public class PeriodicCooldownReduction : ToggleableTweak
	{
		[HarmonyPatch(typeof(MutatorTower), "BuffTowerModel")]
		internal static class AbilityCooldownScaleSupport_BuffTowerModel
		{
			[HarmonyPostfix]
			internal static void Postfix(MutatorTower __instance, TowerModel towerModel)
			{
				if (ModContent.GetInstance<PeriodicCooldownReduction>().Enabled)
				{
					Il2CppGenericIEnumerable.ForEach<ActivateAbilityAfterIntervalModel>(((Model)towerModel).GetDescendants<ActivateAbilityAfterIntervalModel>(), (Action<ActivateAbilityAfterIntervalModel>)delegate(ActivateAbilityAfterIntervalModel i)
					{
						i.interval /= __instance.abilityCooldownSpeedScale;
						i.intervalFrames = Math.CeilToInt((float)i.intervalFrames / __instance.abilityCooldownSpeedScale);
					});
				}
			}
		}

		protected override bool DefaultEnabled => true;

		public override string Description => "Makes ability cooldown reduction effects also apply to periodically activated abilities like Carpet of Spikes.";

		protected override string Icon => "beca93cfa6584443081618415fec9cb0";
	}
	public class PursuitPathPrioritization : ToggleableTweak
	{
		[HarmonyPatch(typeof(PursuitSetting), "GetPursuitTarget")]
		internal static class PursuitSetting_GetPursuitTarget
		{
			[HarmonyPrefix]
			internal static bool Prefix(PursuitSetting __instance, ref Target? __result)
			{
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ea: Expected O, but got Unknown
				HeliMovement heliMovement = __instance.heliMovement;
				if (((heliMovement != null) ? ((TowerBehavior)heliMovement).tower : null) == null || !PathSelections.TryGetValue(((RootObject)((TowerBehavior)__instance.heliMovement).tower).Id, out List<string> value))
				{
					return true;
				}
				Path[] currentPaths = (from p in value
					select ((RootObject)__instance).Sim.Map.pathManager.GetPath(p) into p
					where p.hasBloons || p.hasOfftrackBloons
					select p).ToArray();
				if (!ArrayExt.Any<Path>(currentPaths))
				{
					return true;
				}
				__result = ((IEnumerable<Target>)MonoLinqHelper.ToArray<Target>(((Il2CppObjectBase)((PathSupplierHeli)__instance).Targets(99999f)).Cast<IEnumerable<Target>>())).FirstOrDefault((Func<Target, bool>)delegate(Target target)
				{
					PathSegment pathSegment = target.pathSegment;
					object obj = ((pathSegment != null) ? pathSegment.path : null);
					if (obj == null)
					{
						Bloon bloon = target.bloon;
						obj = ((bloon != null) ? bloon.path : null);
					}
					Path val = (Path)obj;
					return val != null && (currentPaths.Contains(val) || val.def.pathId.Contains("Boss"));
				});
				if (__result == null)
				{
					__result = new Target();
				}
				return false;
			}
		}

		public class PursuitTsmTheme : ModTsmTheme
		{
			private TSMButton button = null;

			private static readonly Dictionary<Entity, string> Dots = new Dictionary<Entity, string>();

			public override string BaseTheme => "HeliPilot";

			public override void SetupTheme(BaseTSMTheme theme)
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_004f: Unknown result type (might be due to invalid IL or missing references)
				button = GameObjectExt.AddTSMButton(((Component)theme).gameObject, new Info("PursuitButton", 372f, -428f, 180f), "Ui[GreenBtnSquare]", "PursuitButton", ModContent.GetId<PursuitCustomInput>());
				GameObjectExt.AddImage(((Component)button).gameObject, new Info("Icon", 128f), "3d08be8876462204d9702b4259d9828e");
			}

			public override void TowerChanged(BaseTSMTheme theme, TowerToSimulation tower)
			{
				PursuitSetting behaviorInDependants = ((RootBehavior)tower.tower).Entity.GetBehaviorInDependants<PursuitSetting>();
				if (behaviorInDependants == null)
				{
					((Component)button).gameObject.SetActive(false);
					return;
				}
				((Component)button).gameObject.SetActive(true);
				if (!Dots.Any())
				{
					StartDrawing();
				}
			}

			public override void OnDisable(BaseTSMTheme theme)
			{
				StopDrawing();
			}

			private static void StartDrawing()
			{
				//IL_0080: Unknown result type (might be due to invalid IL or missing references)
				//IL_0085: 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_0094: 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_00b5: Expected O, but got Unknown
				//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
				Simulation current = SimulationExt.Current;
				Enumerator<Path> enumerator = current.Map.pathManager.paths.GetEnumerator();
				while (enumerator.MoveNext())
				{
					Path current2 = enumerator.Current;
					if (!current2.isActive || current2.def.pathId.Contains("Boss"))
					{
						continue;
					}
					foreach (PathSegment item in (Il2CppArrayBase<PathSegment>)(object)current2.segments)
					{
						Entity val = current.factory.Create<Entity>();
						val.AddBehaviorFromModel((Model)(object)CreateTransformModelExt.Create(new Args
						{
							position = new Vector3(item.point.x, item.point.y, item.pointHeight)
						}), false);
						DisplayBehavior val2 = ((Il2CppObjectBase)val.AddBehaviorFromModel((Model)(object)CreateDisplayModelExt.Create(), false)).Cast<DisplayBehavior>();
						val2.SetScaleOffset(Vector3.zero);
						Dots[val] = current2.def.pathId;
					}
				}
			}

			private static void StopDrawing()
			{
				foreach (Entity key in Dots.Keys)
				{
					((RootObject)key).Destroy();
				}
				Dots.Clear();
			}

			public override void Update(BaseTSMTheme theme)
			{
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				//IL_008c: Unknown result type (might be due to invalid IL or missing references)
				//IL_00df: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
				//IL_0189: Unknown result type (might be due to invalid IL or missing references)
				//IL_0193: Expected O, but got Unknown
				if (!Dots.Any())
				{
					return;
				}
				InputManager val = InGameExt[InGame.instance];
				bool flag = ModCustomInput.ActiveInput is PursuitCustomInput;
				object obj;
				if (!flag)
				{
					obj = TowerSelectionMenuExt.instance.selectedTower;
				}
				else
				{
					CustomInput customInput = val.customInput;
					obj = ((customInput != null) ? customInput.tower : null);
				}
				TowerToSimulation val2 = (TowerToSimulation)obj;
				object obj2;
				if (!flag)
				{
					obj2 = null;
				}
				else
				{
					PathSegment? path = PursuitCustomInput.GetPath(val.CursorPositionWorld);
					if (path == null)
					{
						obj2 = null;
					}
					else
					{
						Path path2 = path.path;
						obj2 = ((path2 != null) ? path2.def.pathId : null);
					}
				}
				string text = (string)obj2;
				List<string> list = ((val2 == null) ? new List<string>() : PathSelections.GetValueOrDefault(val2.Id, new List<string>()));
				foreach (KeyValuePair<Entity, string> dot in Dots)
				{
					dot.Deconstruct(out var key, out var value);
					Entity val3 = key;
					string text2 = value;
					DisplayBehavior displayBehavior = val3.GetDisplayBehavior();
					displayBehavior.SetScaleOffset(Vector3.one * (float)((val2 != null && (list.Contains(text2) || flag)) ? 1 : 0));
					PrefabReference display = displayBehavior.displayModel.display;
					string text3 = ((display != null) ? display.AssetGUID : null);
					string text4 = "f6e4526492bc9164baac0dd1058077f2";
					if (flag)
					{
						bool flag2 = text == text2;
						bool flag3 = list.Contains(text2);
						if (flag2 && flag3)
						{
							text4 = "15a96ce311133ec46b824e88f291a255";
						}
						else if (!flag2 && !flag3)
						{
							text4 = "505654c2ff7054e49900a08b16f67bde";
						}
					}
					if (text3 != text4)
					{
						displayBehavior.displayModel.display = new PrefabReference(text4);
						((RootBehavior)displayBehavior).UpdatedModel((Model)(object)displayBehavior.displayModel);
					}
				}
			}
		}

		public class PursuitCustomInput : ModCustomInput
		{
			public override string GetHelperMessage(CustomInput customInput)
			{
				return "Prioritize pursuing specific path(s)";
			}

			public static PathSegment? GetPath(Vector2 cursorPosWorld)
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				return SimulationExt.Current.map.pathManager.FirstPathSegmentInRangeOrDefault(new Vector2(cursorPosWorld), 10f, false, false, false);
			}

			public override bool IsPositionValid(CustomInput customInput, Vector2 cursorPosWorld, bool isCursorInWorld)
			{
				//IL_0004: Unknown result type (might be due to invalid IL or missing references)
				return isCursorInWorld && GetPath(cursorPosWorld) != null;
			}

			public override void OnValidPositionCursorUp(CustomInput customInput, Vector2 cursorPosWorld, bool isCursorInWorld)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				//IL_0047: Unknown result type (might be due to invalid IL or missing references)
				//IL_0077: Unknown result type (might be due to invalid IL or missing references)
				string pathId = GetPath(cursorPosWorld).path.def.pathId;
				if (!PathSelections.TryGetValue(customInput.tower.Id, out List<string> value))
				{
					value = new List<string>();
					PathSelections.Add(customInput.tower.Id, value);
				}
				if (value.Contains(pathId))
				{
					value.Remove(pathId);
				}
				else
				{
					value.Add(pathId);
				}
				((ModCustomInput)this).OnValidPositionCursorUp(customInput, cursorPosWorld, isCursorInWorld);
			}

			public override void Update(CustomInput customInput, Vector3 cursorPosUnityWorld, Vector2 cursorPosWorld, bool isCursorActive)
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				if (isCursorActive)
				{
					PathSegment? path = GetPath(cursorPosWorld);
					string text = ((path != null) ? path.path.def.pathId : null);
					string text2 = ((ModCustomInput)this).GetHelperMessage(customInput);
					List<string> valueOrDefault = PathSelections.GetValueOrDefault(customInput.tower.Id, new List<string>());
					if (text != null)
					{
						text2 = (valueOrDefault.Contains(text) ? ("Stop prioritizing " + text) : ("Start prioritizing " + text));
					}
					customInput.inputManager.SetHelperMessage(text2, -1f);
				}
			}
		}

		public static readonly Dictionary<ObjectId, List<string>> PathSelections = new Dictionary<ObjectId, List<string>>();

		protected override bool DefaultEnabled => true;

		protected override string Icon => "3d08be8876462204d9702b4259d9828e";

		public override string Description => "Allows Heli Pilots to choose to prioritize Bloons on specific paths.";

		public override void OnNewGameModel(GameModel gameModel)
		{
			if (!base.Enabled)
			{
				return;
			}
			foreach (TowerModel item in ((IEnumerable<TowerModel>)MonoLinqHelper.ToArray<TowerModel>(gameModel.GetTowersWithBaseId(TowerType.HeliPilot, false))).Where((TowerModel model) => ((Il2CppArrayBase<string>)(object)model.appliedUpgrades)?.Contains("Pursuit") ?? false))
			{
				item.towerSelectionMenuThemeId = ModContent.GetId<PursuitTsmTheme>();
			}
		}

		public override void OnTowerSaved(Tower tower, TowerSaveDataModel saveData)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			if (PathSelections.TryGetValue(((RootObject)tower).Id, out List<string> value))
			{
				saveData.metaData[((ModContent)this).Id] = JsonConvert.SerializeObject((object)value);
			}
		}

		public override void OnTowerLoaded(Tower tower, TowerSaveDataModel saveData)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			string text = default(string);
			if (saveData.metaData.TryGetValue(((ModContent)this).Id, ref text))
			{
				PathSelections[((RootObject)tower).Id] = JsonConvert.DeserializeObject<List<string>>(text) ?? new List<string>();
			}
		}

		public override void OnGameObjectsReset()
		{
			PathSelections.Clear();
		}
	}
	public class StickyBombAttackSpeed : ToggleableTweak
	{
		[HarmonyPatch(typeof(Tower), "OnUpgraded")]
		internal static class Tower_OnUpgraded
		{
			[HarmonyPostfix]
			internal static void Postfix(Tower __instance)
			{
				Apply(__instance);
			}
		}

		[HarmonyPatch(typeof(Tower), "OnPlace")]
		internal static class Tower_OnPlace
		{
			[HarmonyPostfix]
			internal static void Postfix(Tower __instance)
			{
				Apply(__instance);
			}
		}

		[HarmonyPatch(typeof(RateSupportMutator), "Mutate")]
		internal static class RateSupportMutator_Mutate
		{
			[HarmonyPrefix]
			internal static bool Prefix(RateSupportMutator __instance, Model baseModel, Model model, ref bool __result)
			{
				TowerModel val = default(TowerModel);
				TowerModel val2 = default(TowerModel);
				if (((BehaviorMutator)__instance).id != "StickyBombAttackSpeed" || !Il2CppSystemObjectExt.Is<TowerModel>((Il2CppObjectBase)(object)baseModel, ref val) || !Il2CppSystemObjectExt.Is<TowerModel>((Il2CppObjectBase)(object)model, ref val2) || !ModContent.GetInstance<StickyBombAttackSpeed>().Enabled)
				{
					return true;
				}
				IEnumerable<AddBehaviorToBloonModel> enumerable = Il2CppGenericIEnumerable.AsIEnumerable<AddBehaviorToBloonModel>(((Model)val2).GetDescendants<AddBehaviorToBloonModel>()).Where(delegate(AddBehaviorToBloonModel m)
				{
					switch (m.mutationId)
					{
					case "StickyBomb":
					case "MasterSticky":
					case "StickyBombSplash":
						return true;
					default:
						return false;
					}
				});
				float rate = ((Il2CppArrayBase<WeaponModel>)(object)TowerModelExt.GetAttackModel(val).weapons)[0].Rate;
				float rate2 = ((Il2CppArrayBase<WeaponModel>)(object)TowerModelExt.GetAttackModel(val2).weapons)[0].Rate;
				float num = rate2 / rate;
				foreach (AddBehaviorToBloonModel item in enumerable)
				{
					item.lifespan *= num;
					if (item.lifespan < 0.05f)
					{
						item.lifespan = 0.05f;
					}
					item.lifespanFrames = (int)(item.lifespan * 60f);
					foreach (DamageOverTimeModel behavior in AddBehaviorToBloonModelBehaviorExt.GetBehaviors<DamageOverTimeModel>(item))
					{
						behavior.Interval = item.lifespan - 0.02f;
					}
					foreach (ProjectileOverTimeModel behavior2 in AddBehaviorToBloonModelBehaviorExt.GetBehaviors<ProjectileOverTimeModel>(item))
					{
						behavior2.Interval = item.lifespan - 0.02f;
					}
				}
				__result = true;
				return false;
			}
		}

		protected override bool DefaultEnabled => false;

		public override string Description => "Makes attack speed buffs cause Sticky Bombs to blow up quicker. (Also affects Master Bomber)";

		protected override string Icon => "a61263630220b41b4a578114cc55cfe9";

		public static void Apply(Tower? tower)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			if (((tower != null) ? tower.towerModel : null) != null && ModContent.GetInstance<StickyBombAttackSpeed>().Enabled)
			{
				Il2CppStringArray appliedUpgrades = tower.towerModel.appliedUpgrades;
				if (appliedUpgrades != null && ((Il2CppArrayBase<string>)(object)appliedUpgrades).Contains("Sticky Bomb") && !((Mutable)tower).IsMutatedBy("StickyBombAttackSpeed"))
				{
					((Mutable)tower).AddMutator((BehaviorMutator)new RateSupportMutator(true, "StickyBombAttackSpeed", 1f, -100, (BuffIndicatorModel)null, false, (DisplayModel)null)
					{
						cantBeAbsorbed = true
					}, -1, true, true, false, true, false, false, false, -1, false, false);
				}
			}
		}
	}
}