Decompiled source of BuffsInShop v1.1.4

BuffsInShop.dll

Decompiled 9 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.Data;
using BTD_Mod_Helper.Api.Display;
using BTD_Mod_Helper.Api.Helpers;
using BTD_Mod_Helper.Api.ModOptions;
using BTD_Mod_Helper.Api.Towers;
using BTD_Mod_Helper.Extensions;
using BuffsInShop;
using BuffsInShop.Buff;
using HarmonyLib;
using Il2CppAssets.Scripts;
using Il2CppAssets.Scripts.Data;
using Il2CppAssets.Scripts.Models;
using Il2CppAssets.Scripts.Models.Audio;
using Il2CppAssets.Scripts.Models.Effects;
using Il2CppAssets.Scripts.Models.Entities;
using Il2CppAssets.Scripts.Models.GenericBehaviors;
using Il2CppAssets.Scripts.Models.GeraldoItems;
using Il2CppAssets.Scripts.Models.Map;
using Il2CppAssets.Scripts.Models.Powers.Effects;
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.Mods;
using Il2CppAssets.Scripts.Models.Towers.Mutators;
using Il2CppAssets.Scripts.Models.Towers.Projectiles;
using Il2CppAssets.Scripts.Models.Towers.Projectiles.Behaviors;
using Il2CppAssets.Scripts.Models.Towers.TowerFilters;
using Il2CppAssets.Scripts.Models.Towers.Upgrades;
using Il2CppAssets.Scripts.Models.Towers.Weapons.Behaviors;
using Il2CppAssets.Scripts.Simulation;
using Il2CppAssets.Scripts.Simulation.Input;
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.Behaviors;
using Il2CppAssets.Scripts.Simulation.Towers.TowerFilters;
using Il2CppAssets.Scripts.Simulation.Towers.Weapons.Behaviors;
using Il2CppAssets.Scripts.Simulation.Track;
using Il2CppAssets.Scripts.Unity;
using Il2CppAssets.Scripts.Unity.UI_New.InGame;
using Il2CppAssets.Scripts.Unity.UI_New.InGame.RightMenu;
using Il2CppAssets.Scripts.Unity.UI_New.InGame.StoreMenu;
using Il2CppAssets.Scripts.Utils;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppNinjaKiwi.Common;
using Il2CppNinjaKiwi.Common.ResourceUtils;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Linq;
using MelonLoader;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json.Linq;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(BuffsInShopMod), "Buffs in Shop", "1.1.4", "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("BuffsInShop")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+84720981ac4dda2a64ed364546af3a7e1f1d9eb5")]
[assembly: AssemblyProduct("BuffsInShop")]
[assembly: AssemblyTitle("BuffsInShop")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
[CompilerGenerated]
internal sealed class <>z__ReadOnlyArray<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T>
{
	int ICollection.Count => _items.Length;

	bool ICollection.IsSynchronized => false;

	object ICollection.SyncRoot => this;

	object? IList.this[int index]
	{
		get
		{
			return _items[index];
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	bool IList.IsFixedSize => true;

	bool IList.IsReadOnly => true;

	int IReadOnlyCollection<T>.Count => _items.Length;

	T IReadOnlyList<T>.this[int index] => _items[index];

	int ICollection<T>.Count => _items.Length;

	bool ICollection<T>.IsReadOnly => true;

	T IList<T>.this[int index]
	{
		get
		{
			return _items[index];
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	public <>z__ReadOnlyArray(T[] items)
	{
		_items = items;
	}

	IEnumerator IEnumerable.GetEnumerator()
	{
		return ((IEnumerable)_items).GetEnumerator();
	}

	void ICollection.CopyTo(Array array, int index)
	{
		((ICollection)_items).CopyTo(array, index);
	}

	int IList.Add(object? value)
	{
		throw new NotSupportedException();
	}

	void IList.Clear()
	{
		throw new NotSupportedException();
	}

	bool IList.Contains(object? value)
	{
		return ((IList)_items).Contains(value);
	}

	int IList.IndexOf(object? value)
	{
		return ((IList)_items).IndexOf(value);
	}

	void IList.Insert(int index, object? value)
	{
		throw new NotSupportedException();
	}

	void IList.Remove(object? value)
	{
		throw new NotSupportedException();
	}

	void IList.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}

	IEnumerator<T> IEnumerable<T>.GetEnumerator()
	{
		return ((IEnumerable<T>)_items).GetEnumerator();
	}

	void ICollection<T>.Add(T item)
	{
		throw new NotSupportedException();
	}

	void ICollection<T>.Clear()
	{
		throw new NotSupportedException();
	}

	bool ICollection<T>.Contains(T item)
	{
		return ((ICollection<T>)_items).Contains(item);
	}

	void ICollection<T>.CopyTo(T[] array, int arrayIndex)
	{
		((ICollection<T>)_items).CopyTo(array, arrayIndex);
	}

	bool ICollection<T>.Remove(T item)
	{
		throw new NotSupportedException();
	}

	int IList<T>.IndexOf(T item)
	{
		return ((IList<T>)_items).IndexOf(item);
	}

	void IList<T>.Insert(int index, T item)
	{
		throw new NotSupportedException();
	}

	void IList<T>.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}
}
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 BuffsInShop
{
	public class BuffInShopMutator(ModBuffInShop modBuffInShop) : ModMutator<BuffInShopMutator.Data>()
	{
		public record struct Data(float Cost, int Stacks);

		public override string Name => ((ModContent)modBuffInShop).Name;

		public override bool CantBeAbsorbed => true;

		public override bool Saved => false;

		public override bool Mutate(Model baseModel, Model model, Data data)
		{
			return modBuffInShop.ExtraMutation(((Il2CppObjectBase)model).Cast<TowerModel>());
		}
	}
	public class Buffs : ModTowerSet
	{
		public override bool AllowInRestrictedModes => true;

		protected override int Order => 100;
	}
	public class BuffsInShopMod : BloonsTD6Mod
	{
		public static readonly ModSettingBool RequireBuffOriginUsable = new ModSettingBool(true)
		{
			description = "Requires the original source of a buff to be usable in a match for it to show up in the shop",
			icon = "MonkeyIcons[MonkeyVillageIcon]"
		};

		public static readonly ModSettingBool BypassTowerRestrictions = new ModSettingBool(false)
		{
			description = "Makes it so buffs in shop can be placed on any towers, not just ones they'd naturally apply to",
			icon = "ecba4e8d656984819b66fd9d821d0bea"
		};

		public static readonly ModSettingBool AlwaysAffectSubTowers = new ModSettingBool(false)
		{
			description = "Makes the buffs that don't normally affect sub-towers like Alchemists' and Overclock now affect sub-towers.",
			icon = "51eeafda3cb950c448d89640e15be086"
		};

		private static readonly Dictionary<ModBuffInShop, (float cost, int stacks)> Clipboard = new Dictionary<ModBuffInShop, (float, int)>();

		public override void OnTitleScreen()
		{
			//IL_0075: 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_008c: Expected O, but got Unknown
			ModModel val = ((IEnumerable<ModModel>)GameData.Instance.mods).FirstOrDefault((Func<ModModel, bool>)((ModModel model) => ((Model)model).name == "Clicks"));
			if (val == null)
			{
				return;
			}
			foreach (ModBuffInShop item in from buff in ModContent.GetContent<ModBuffInShop>()
				where !buff.AllowInChimps
				select buff)
			{
				ModModelExt.AddMutator(val, (MutatorModModel)(object)CreateLockTowerModModelExt.Create(new Args
				{
					towerToLock = ((ModContent)item).Id
				}));
			}
		}

		public override void OnSaveSettings(JObject settings)
		{
			foreach (ModBuffInShop item in ModContent.GetContent<ModBuffInShop>())
			{
				Game.instance.model.GetTower(((ModContent)item).Id, 0, 0, 0).cost = ((ModTower)item).Cost;
				((ModTower)item).AddOrRemoveFromShop();
			}
		}

		public override void OnTowerDestroyed(Tower tower)
		{
			int num = default(int);
			foreach (ModBuffInShop item in from buff in ModContent.GetContent<ModBuffInShop>()
				where buff.HasBuff(tower)
				select buff)
			{
				TowerInventory towerInventory = InGame.Bridge.Simulation.GetTowerInventory(tower.owner);
				if (towerInventory.towerMaxes.TryGetValue(((ModContent)item).Id, ref num) && num > -1)
				{
					Dictionary<string, int> towerMaxes = towerInventory.towerMaxes;
					string id = ((ModContent)item).Id;
					int num2 = towerMaxes[id];
					towerMaxes[id] = num2 + 1;
				}
			}
		}

		public override void OnTowerSaved(Tower tower, TowerSaveDataModel saveData)
		{
			foreach (TimedMutator item in ((ListLite<TimedMutator>)(object)((Mutable)tower).mutators).ToArray())
			{
				if (ModBuffInShop.Cache.TryGetValue(item.mutator.id, out ModBuffInShop value))
				{
					BuffInShopMutator.Data data = ((ModMutator<BuffInShopMutator.Data>)value.Mutator).GetData(item.mutator);
					saveData.metaData[((ModContent)value).Id] = $"{data.Cost}";
					if (data.Stacks > 1)
					{
						saveData.metaData[((ModContent)value).Id + "Count"] = data.Stacks.ToString();
					}
					value.OnSaved(tower, saveData);
				}
			}
		}

		public static void OnLateTowerLoaded(Tower tower, TowerSaveDataModel saveData)
		{
			string s = default(string);
			string s2 = default(string);
			foreach (var (text2, modBuffInShop2) in ModBuffInShop.Cache)
			{
				if (!saveData.metaData.TryGetValue(text2, ref s) || !float.TryParse(s, out var result))
				{
					continue;
				}
				modBuffInShop2.Apply(tower, result);
				if (saveData.metaData.TryGetValue(text2 + "Count", ref s2) && int.TryParse(s2, out var result2))
				{
					for (int i = 1; i < result2; i++)
					{
						modBuffInShop2.Apply(tower, 0f);
					}
				}
			}
			foreach (TimedMutator item in ((ListLite<TimedMutator>)(object)((Mutable)tower).mutators).ToArray())
			{
				if (ModBuffInShop.Cache.TryGetValue(item.mutator.id, out ModBuffInShop value))
				{
					value.OnLoaded(tower, saveData);
				}
			}
		}

		public override object? Call(string operation, params object[] parameters)
		{
			switch (operation)
			{
			case "OnTowerCopied":
			{
				Tower tower = default(Tower);
				if (!ArrayExt.CheckTypes<Tower>(parameters, ref tower))
				{
					break;
				}
				Clipboard.Clear();
				foreach (ModBuffInShop item in ModContent.GetContent<ModBuffInShop>())
				{
					if (item.HasBuff(tower, out var towerCost))
					{
						Clipboard[item] = (towerCost, item.GetStackCount(tower));
					}
				}
				break;
			}
			case "OnTowerPasted":
			{
				Tower tower2 = default(Tower);
				if (!ArrayExt.CheckTypes<Tower>(parameters, ref tower2))
				{
					break;
				}
				foreach (KeyValuePair<ModBuffInShop, (float, int)> item2 in Clipboard)
				{
					item2.Deconstruct(out var key, out var value);
					(float, int) tuple = value;
					ModBuffInShop modBuffInShop = key;
					var (purchaseCost, num) = tuple;
					modBuffInShop.Apply(tower2, purchaseCost, sideEffects: true);
					for (int num2 = 1; num2 < num; num2++)
					{
						modBuffInShop.Apply(tower2, 0f, sideEffects: true);
					}
				}
				break;
			}
			case "OnClipboardCleared":
				Clipboard.Clear();
				break;
			case "ModifyClipboardCost":
			{
				Tower val = default(Tower);
				if (!ArrayExt.CheckTypes<Tower>(parameters, ref val))
				{
					break;
				}
				return (from buff in ModContent.GetContent<ModBuffInShop>()
					where buff.HasBuff(val)
					select buff).Sum((ModBuffInShop buff) => InGame.Bridge.Simulation.towerManager.GetTowerCost(InGame.Bridge.Model.GetTowerWithName(((ModContent)buff).Id), Vector3Boxed.op_Implicit(((CommonBehaviorProxy<ITowerBehavior>)(object)val).Position), InGame.Bridge.Simulation.GetTowerInventory(val.owner), val.owner));
			}
			}
			return null;
		}
	}
	public static class Extensions
	{
		public static RateSupportMutator CreateMutator(this RateSupportModel rateSupport)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			return new RateSupportMutator(rateSupport.isUnique, rateSupport.mutatorId, rateSupport.multiplier, rateSupport.priority, ((SupportModel)rateSupport).GetBuffIndicatorModel(), false, rateSupport.buffDisplayModel);
		}

		public static MutatorTower CreateMutator(this PierceSupportModel pierceSupport)
		{
			//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: Expected O, but got Unknown
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			return new MutatorTower(new PierceSupport
			{
				pierceSupportModel = pierceSupport
			});
		}

		public static ProjectileSpeedSupportMutator CreateMutator(this ProjectileSpeedSupportModel projSpeedSupport)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			return new ProjectileSpeedSupportMutator(projSpeedSupport.multiplier, projSpeedSupport.isUnique, projSpeedSupport.mutatorId, 0, ((SupportModel)projSpeedSupport).GetBuffIndicatorModel(), false);
		}

		public static MutatorTower CreateMutator(this RangeSupportModel rangeSupport)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			return new MutatorTower(rangeSupport.isUnique, rangeSupport.mutatorId, rangeSupport.additive, rangeSupport.multiplier, ((SupportModel)rangeSupport).GetBuffIndicatorModel());
		}

		public static MutatorTower CreateMutator(this AbilityCooldownScaleSupportModel abilityCooldownScaleSupport)
		{
			//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_001e: Expected O, but got Unknown
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			return new MutatorTower(new AbilityCooldownScaleSupport
			{
				abilityCooldownScaleSupportModel = abilityCooldownScaleSupport
			}, abilityCooldownScaleSupport.abilityCooldownSpeedScale, ((Model)abilityCooldownScaleSupport).name);
		}

		public static MutatorTower CreateMutator(this VisibilitySupportModel visibilitySupport)
		{
			//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: Expected O, but got Unknown
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			return new MutatorTower(new VisibilitySupport
			{
				visibilitySupportModel = visibilitySupport
			});
		}

		public static MutatorTower CreateMutator(this AddBehaviorToTowerSupportModel addBehaviorToTowerSupport)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			return new MutatorTower(addBehaviorToTowerSupport.behaviors, addBehaviorToTowerSupport.mutationId, ((SupportModel)addBehaviorToTowerSupport).GetBuffIndicatorModel());
		}

		public static MutatorTower CreateMutator(this MonkeyCityIncomeSupportModel monkeyCityIncomeSupport)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			return new MutatorTower(((SupportModel)monkeyCityIncomeSupport).GetBuffIndicatorModel(), monkeyCityIncomeSupport.incomeModifier, monkeyCityIncomeSupport.uniqueMutatorId);
		}

		public static MutatorTower CreateMutator(this TargetSupplierSupportModel targetSupplierSupport)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			return new MutatorTower(targetSupplierSupport);
		}

		public static Mutator CreateMutator(this FlagshipAttackSpeedIncreaseModel flagshipAttackSpeedIncreaseModel)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			return new Mutator(flagshipAttackSpeedIncreaseModel);
		}

		public static MutatorTower CreateMutator(this SubCommanderSupportModel subCommanderSupport)
		{
			//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: Expected O, but got Unknown
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			return new MutatorTower(new SubCommanderSupport
			{
				subCommandSupportModel = subCommanderSupport
			});
		}

		public static Mutator CreateMutator(this BonusCashZoneModel bonusCashZone)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			return new Mutator(true, bonusCashZone.stackName, bonusCashZone.multiplier);
		}

		public static MutatorTower CreateMutator(this DamageSupportModel damageSupport)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			return new MutatorTower(damageSupport.increase, damageSupport.isUnique, damageSupport.mutatorId, ((SupportModel)damageSupport).GetBuffIndicatorModel());
		}

		public static MutatorTower CreateMutator(this PiercePercentageSupportModel piercePercentageSupport)
		{
			//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: Expected O, but got Unknown
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			return new MutatorTower(new PiercePercentageSupport
			{
				piercePercentageSupportModel = piercePercentageSupport
			});
		}

		public static RateSupportMutator CreateMutator(this ActivateRateSupportZoneModel activateRateSupportZoneModel)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			return new RateSupportMutator(activateRateSupportZoneModel.isUnique, activateRateSupportZoneModel.mutatorId, activateRateSupportZoneModel.rateModifier, 0, ((AbilityBehaviorBuffModel)activateRateSupportZoneModel).GetBuffIndicatorModel(), false, (DisplayModel)null);
		}

		public static MutatorTower CreateMutator(this ActivatePierceSupportZoneModel activatePierceSupportZoneModel)
		{
			//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_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			//IL_007c: Expected O, but got Unknown
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			return new MutatorTower(new PierceSupport
			{
				pierceSupportModel = CreatePierceSupportModelExt.Create(new Args
				{
					isUnique = activatePierceSupportZoneModel.isUnique,
					pierce = activatePierceSupportZoneModel.pierceIncrease,
					mutatorId = activatePierceSupportZoneModel.mutatorId,
					filters = Il2CppArrayBase<TowerFilterModel>.op_Implicit((Il2CppArrayBase<TowerFilterModel>)(object)activatePierceSupportZoneModel.filters),
					isGlobal = ((AbilityBehaviorBuffModel)activatePierceSupportZoneModel).isGlobal,
					buffLocsName = ((AbilityBehaviorBuffModel)activatePierceSupportZoneModel).buffLocsName,
					buffIconName = ((AbilityBehaviorBuffModel)activatePierceSupportZoneModel).buffIconName
				})
			});
		}

		public static MutatorTower CreateMutator(this ActivateTowerDamageSupportZoneModel activateTowerDamageSupportZoneModel)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			return new MutatorTower(activateTowerDamageSupportZoneModel.damageIncrease, activateTowerDamageSupportZoneModel.isUnique, activateTowerDamageSupportZoneModel.mutatorId, ((AbilityBehaviorBuffModel)activateTowerDamageSupportZoneModel).GetBuffIndicatorModel());
		}

		public static MutatorTower CreateMutator(this ActivateVisibilitySupportZoneModel activateVisibilitySupportZoneModel)
		{
			//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_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_006e: Expected O, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			return new MutatorTower(new VisibilitySupport
			{
				visibilitySupportModel = CreateVisibilitySupportModelExt.Create(new Args
				{
					isUnique = activateVisibilitySupportZoneModel.isUnique,
					mutatorId = activateVisibilitySupportZoneModel.mutatorId,
					isGlobal = ((AbilityBehaviorBuffModel)activateVisibilitySupportZoneModel).isGlobal,
					filters = Il2CppArrayBase<TowerFilterModel>.op_Implicit((Il2CppArrayBase<TowerFilterModel>)(object)activateVisibilitySupportZoneModel.filters),
					buffLocsName = ((AbilityBehaviorBuffModel)activateVisibilitySupportZoneModel).buffLocsName,
					buffIconName = ((AbilityBehaviorBuffModel)activateVisibilitySupportZoneModel).buffIconName
				})
			});
		}

		public static MutatorTower CreateMutator(this DamageTypeSupportModel damageTypeSupportModel)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			return new MutatorTower(damageTypeSupportModel.mutatorId, damageTypeSupportModel.isUnique, ((SupportModel)damageTypeSupportModel).GetBuffIndicatorModel(), damageTypeSupportModel.immuneBloonProperties);
		}

		public static PierceUpMutator CreateMutator(this PierceUpTowersModel pierceUpTowersModel)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			return new PierceUpMutator(pierceUpTowersModel.increase, pierceUpTowersModel.mutatorId, pierceUpTowersModel.priority, pierceUpTowersModel);
		}

		public static DamageUpMutator CreateMutator(this DamageUpTowersModel damageUpTowersModel)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			return new DamageUpMutator(damageUpTowersModel.increase, damageUpTowersModel.mutatorId, damageUpTowersModel.priority);
		}

		public static DamageUpTagMutator CreateMutator(this DamageUpTagTowersModel damageUpTagTowersModel)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			return new DamageUpTagMutator(damageUpTagTowersModel);
		}

		public static HeatItUpDamageMutator CreateMutator(this HeatItUpDamageBuffModel heatItUpDamageBuffModel)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			return new HeatItUpDamageMutator(heatItUpDamageBuffModel.mutatorId, heatItUpDamageBuffModel.GetBuffIndicatorModel());
		}

		public static MutatorTower CreateMutator(this RateSupportBombExpertModel rateSupportBombExpertModel)
		{
			//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: Expected O, but got Unknown
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			return new MutatorTower(new RateSupportBombExpert
			{
				rateSupportBombExpertModel = rateSupportBombExpertModel
			});
		}

		public static MutatorTower CreateMutator(this RateSupportExplosiveModel rateSupportExplosiveModel)
		{
			//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: Expected O, but got Unknown
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			return new MutatorTower(new RateSupportExplosive
			{
				rateSupportExplosiveModel = rateSupportExplosiveModel
			});
		}

		public static MutatorTower CreateMutator(this ProjectileRadiusSupportModel rateSupportBombExpertModel)
		{
			//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: Expected O, but got Unknown
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			return new MutatorTower(new ProjectileRadiusSupport
			{
				projectileRadiusSupportModel = rateSupportBombExpertModel
			});
		}

		public static MutatorTower CreateMutator(this FreezeDurationSupportModel freezeDurationSupportModel)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			return new MutatorTower(freezeDurationSupportModel.isUnique, freezeDurationSupportModel.mutatorId, freezeDurationSupportModel.additive, freezeDurationSupportModel.multiplier, ((SupportModel)freezeDurationSupportModel).GetBuffIndicatorModel());
		}

		public static MutatorTower CreateMutator(this BananaCashIncreaseSupportModel bananaCashIncreaseSupportModel)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			return new MutatorTower(bananaCashIncreaseSupportModel);
		}

		public static int Compare<T, TBase>(this (T, TBase) elements, Func<IEnumerable<T>, IEnumerable<T>> orderBy, Func<TBase, int>? fallback = null) where T : TBase
		{
			var (val, val2) = elements;
			if (val2 is T val3 && !object.Equals(val, val2))
			{
				T val4 = orderBy(new <>z__ReadOnlyArray<T>(new T[2] { val, val3 })).First();
				T val5 = orderBy(new <>z__ReadOnlyArray<T>(new T[2] { val3, val })).First();
				if (object.Equals(val, val4) && object.Equals(val, val5))
				{
					return -1;
				}
				if (object.Equals(val2, val4) && object.Equals(val2, val5))
				{
					return 1;
				}
			}
			return fallback?.Invoke(val2) ?? 0;
		}

		public static int Compare<T, TBase>(this T self, TBase unknown, Func<IEnumerable<T>, IEnumerable<T>> orderBy, Func<TBase, int>? fallback = null) where T : IComparable<TBase>, TBase
		{
			return (self, unknown).Compare<T, TBase>(orderBy, fallback);
		}

		public static int Compare<T, TBase>(this T self, TBase unknown, Func<TBase, int>? fallback, Func<IEnumerable<T>, IEnumerable<T>> orderBy) where T : IComparable<TBase>, TBase
		{
			return (self, unknown).Compare<T, TBase>(orderBy, fallback);
		}

		public static BehaviorMutator ApplyBuffIcon<T>(this BehaviorMutator mutator) where T : ModBuffIcon
		{
			mutator.buffIndicator = ((ModBuffIcon)ModContent.GetInstance<T>()).CreateBuffIndicatorModel();
			return mutator;
		}
	}
	public abstract class ModBuffInShop : ModFakeTower<Buffs>, IModSettings, IModContent
	{
		private static readonly JObject BaseCosts = AssemblyExt.GetEmbeddedJson(typeof(ModBuffInShop).Assembly, "costs.json");

		public static readonly Dictionary<string, ModBuffInShop> Cache = new Dictionary<string, ModBuffInShop>();

		public static readonly ModSettingCategory Costs = new ModSettingCategory("Costs");

		public static readonly ModSettingCategory Hotkeys = new ModSettingCategory("Hotkeys");

		public static readonly ModSettingCategory Always = new ModSettingCategory("Always Usable");

		public static readonly ModSettingCategory GodBoosting = new ModSettingCategory("God Boost")
		{
			icon = ModContent.GetTextureGUID<BuffsInShopMod>("GodBoost")
		};

		protected BehaviorMutator[] defaultMutators = null;

		private ModSettingInt cost = null;

		private ModSettingHotkey hotkey = null;

		private ModSettingBool includeInGodBoost = null;

		private ModSettingBool? alwaysUsable;

		private TowerModel? originTowerModel;

		[CompilerGenerated]
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private BuffInShopMutator <Mutator>k__BackingField;

		public bool AlwaysUsable => alwaysUsable != null && ModSettingBool.op_Implicit(alwaysUsable);

		public static GameModel GameModel => GameModelExt.Current;

		public abstract string? OriginTower { get; }

		public abstract string BaseDescription { get; }

		public float UpgradeCost
		{
			get
			{
				int num;
				if (OriginTower != null)
				{
					UpgradeModel? originUpgradeModel = OriginUpgradeModel;
					num = ((originUpgradeModel != null) ? originUpgradeModel.cost : 0);
				}
				else
				{
					num = 0;
				}
				return num;
			}
		}

		public float TowerCost
		{
			get
			{
				TowerModel obj = OriginTowerModel;
				return (obj != null) ? obj.cost : 0f;
			}
		}

		public virtual float BaseCost => UpgradeCost / 2f;

		public virtual KeyCode KeyCode => (KeyCode)0;

		public virtual bool SubsequentDiscount => false;

		public virtual int PriorityBoost => 1;

		public virtual bool AllowInChimps => true;

		public virtual int OriginTopPath => 0;

		public virtual int OriginMidPath => 0;

		public virtual int OriginBotPath => 0;

		public virtual int[] OriginTiers => new int[3] { OriginTopPath, OriginMidPath, OriginBotPath };

		public virtual bool DefaultGodBoost => ((ModContent)this).mod is BuffsInShopMod;

		public virtual bool Hero => false;

		public virtual int MaxStacks => 1;

		public virtual bool ParagonAllowed => false;

		public virtual TowerModel OriginTowerModel
		{
			get
			{
				object obj;
				TowerModel obj2;
				if (OriginTower != null)
				{
					obj = originTowerModel;
					if (obj == null)
					{
						if ((Object)(object)InGame.instance != (Object)null)
						{
							TowerModel tower = GameModel.GetTower(OriginTower, OriginTopPath, OriginMidPath, OriginBotPath);
							TowerModel val = default(TowerModel);
							if (tower != null && Il2CppSystemObjectExt.Is<TowerModel>(tower, ref val) && IsValidOrigin(val))
							{
								obj2 = val;
								goto IL_0088;
							}
						}
						obj2 = Game.instance.model.GetTower(OriginTower, OriginTopPath, OriginMidPath, OriginBotPath);
						goto IL_0088;
					}
				}
				else
				{
					obj = null;
				}
				goto IL_0093;
				IL_0093:
				return (TowerModel)obj;
				IL_0088:
				TowerModel val2 = obj2;
				originTowerModel = obj2;
				obj = val2;
				goto IL_0093;
			}
		}

		public virtual UpgradeModel? OriginUpgradeModel
		{
			get
			{
				object result;
				if (!ArrayExt.Any<int>(OriginTiers, (Func<int, bool>)((int i) => i > 0)))
				{
					result = null;
				}
				else
				{
					GameModel gameModel = GameModel;
					TowerModel obj = OriginTowerModel;
					result = gameModel.GetUpgrade((obj != null) ? ((IEnumerable<string>)obj.appliedUpgrades).Last() : null);
				}
				return (UpgradeModel?)result;
			}
		}

		public override AudioClipReference? PlacementSound => new AudioClipReference("4e14271436fb5b445afff1240816d6b9");

		public override EffectModel? PlacementEffect => new EffectModel("", new PrefabReference("cc4e51ecd049ee249a5bd51db3612483"), 1f, 1f);

		public IEnumerable<string> MutatorIds => defaultMutators.Select((BehaviorMutator mutator) => mutator.id);

		public override string? Icon
		{
			get
			{
				SpriteReference spriteReferenceOrNull = ((ModContent)this).GetSpriteReferenceOrNull(((ModContent)this).Name);
				return (spriteReferenceOrNull != null) ? spriteReferenceOrNull.AssetGUID : null;
			}
		}

		public override SpriteReference IconReference
		{
			get
			{
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Expected O, but got Unknown
				object result;
				if (((ModTower)this).Icon != null)
				{
					result = (object)new SpriteReference(((ModTower)this).Icon);
				}
				else
				{
					UpgradeModel? originUpgradeModel = OriginUpgradeModel;
					result = ((originUpgradeModel != null) ? originUpgradeModel.icon : null) ?? OriginTowerModel.icon;
				}
				return (SpriteReference)result;
			}
		}

		public override ModSettingHotkey Hotkey => hotkey;

		public override int Cost => (!SavedBaseCost.HasValue) ? ((int)BaseCost) : ModSettingInt.op_Implicit(cost);

		public override bool DontAddToShop => ((ModTower)this).Cost < 0;

		private int? SavedBaseCost => ((JToken)BaseCosts).Value<int?>((object)((ModContent)this).Name);

		public bool IncludeInGodBoost => !(this is GodBoost) && ModSettingBool.op_Implicit(includeInGodBoost);

		public override bool HighlightTowers => true;

		public virtual bool AffectsSubTowers => true;

		public sealed override string Description => BaseDescription + (SubsequentDiscount ? "\nSubsequent purchases are less expensive." : "");

		internal BuffInShopMutator Mutator => <Mutator>k__BackingField ?? (<Mutator>k__BackingField = new BuffInShopMutator(this));

		public virtual bool IsValidOrigin(TowerModel current)
		{
			return true;
		}

		public override void Register()
		{
			((ModTower)this).Register();
			defaultMutators = GetMutators(null).ToArray();
			BehaviorMutator[] array = defaultMutators;
			foreach (BehaviorMutator val in array)
			{
				val.priority += PriorityBoost;
			}
			originTowerModel = null;
			Cache[((ModContent)this).Id] = this;
		}

		public override IEnumerable<ModContent> Load()
		{
			int? baseCost = SavedBaseCost;
			if (!baseCost.HasValue)
			{
				try
				{
					baseCost = (int)BaseCost;
				}
				catch (Exception)
				{
					baseCost = 0;
				}
			}
			Dictionary<string, ModSetting> modSettings = ((ModContent)this).mod.ModSettings;
			string key = ((ModContent)this).Name + "Cost";
			ModBuffInShop modBuffInShop = this;
			ModSettingInt val = new ModSettingInt(baseCost.Value)
			{
				category = Costs,
				icon = ((ModTower)this).Icon,
				displayName = ((NamedModContent)this).DisplayName,
				description = "In Game Cost for " + ((NamedModContent)this).DisplayName + ". Set to a negative number to disable the buff."
			};
			ModSettingInt value = val;
			modBuffInShop.cost = val;
			modSettings[key] = (ModSetting)(object)value;
			Dictionary<string, ModSetting> modSettings2 = ((ModContent)this).mod.ModSettings;
			string key2 = ((ModContent)this).Name + "HotKey";
			ModBuffInShop modBuffInShop2 = this;
			ModSettingHotkey val2 = new ModSettingHotkey(KeyCode, (HotkeyModifier)(((int)KeyCode != 0) ? 2 : 0))
			{
				category = Hotkeys,
				icon = ((ModTower)this).Icon,
				displayName = ((NamedModContent)this).DisplayName,
				description = "Hot Key for " + ((NamedModContent)this).DisplayName
			};
			ModSettingHotkey value2 = val2;
			modBuffInShop2.hotkey = val2;
			modSettings2[key2] = (ModSetting)(object)value2;
			if (!(this is GodBoost))
			{
				Dictionary<string, ModSetting> modSettings3 = ((ModContent)this).mod.ModSettings;
				string key3 = ((ModContent)this).Name + "Always";
				ModBuffInShop modBuffInShop3 = this;
				ModSettingBool val3 = new ModSettingBool(false)
				{
					category = Always,
					icon = ((ModTower)this).Icon,
					displayName = ((NamedModContent)this).DisplayName,
					description = "Makes " + ((NamedModContent)this).DisplayName + " always show up in the shop regardless of the Require Buff Origin Usable setting"
				};
				ModSettingBool value3 = val3;
				modBuffInShop3.alwaysUsable = val3;
				modSettings3[key3] = (ModSetting)(object)value3;
				Dictionary<string, ModSetting> modSettings4 = ((ModContent)this).mod.ModSettings;
				string key4 = ((ModContent)this).Name + "GodBoosting";
				ModBuffInShop modBuffInShop4 = this;
				ModSettingBool val4 = new ModSettingBool(DefaultGodBoost)
				{
					category = GodBoosting,
					icon = ((ModTower)this).Icon,
					displayName = ((NamedModContent)this).DisplayName,
					description = "Whether " + ((NamedModContent)this).DisplayName + " should be included within the God Boost buff. Reminder: Still follows the Bypass Tower Restrictions setting."
				};
				value3 = val4;
				modBuffInShop4.includeInGodBoost = val4;
				modSettings4[key4] = (ModSetting)(object)value3;
			}
			yield return (ModContent)(object)this;
			yield return (ModContent)(object)Mutator;
		}

		public override void ModifyBaseTowerModel(TowerModel towerModel)
		{
			((ModFakeTower)this).ModifyBaseTowerModel(towerModel);
			if (((EntityModel)towerModel).behaviors == null)
			{
				Il2CppReferenceArray<Model> val = (((EntityModel)towerModel).behaviors = new Il2CppReferenceArray<Model>(0L));
			}
		}

		public override void ModifyTowerModelForMatch(TowerModel towerModel, GameModel gameModel)
		{
			originTowerModel = null;
		}

		public override int CompareTo(ModContent other)
		{
			return this.Compare<ModBuffInShop, ModContent>(other, (Func<ModContent, int>?)((ModContent)this).CompareTo, (Func<IEnumerable<ModBuffInShop>, IEnumerable<ModBuffInShop>>)((IEnumerable<ModBuffInShop> buffs) => from buff in buffs
				orderby ((ModContent)buff).Order, buff.Hero, buff.ParagonAllowed, buff.OriginTower == TowerType.Alchemist descending, buff.OriginTower == TowerType.Desperado descending, buff.OriginTower == TowerType.EngineerMonkey descending, buff.OriginTower == TowerType.MonkeyVillage descending, buff.OriginTower != TowerType.SuperMonkey descending, (buff.OriginTower != null) ? ((Il2CppArrayBase<string>)(object)TowerType.towers).IndexOf(buff.OriginTower) : 999, (OriginBotPath: buff.OriginBotPath, OriginMidPath: buff.OriginMidPath, OriginTopPath: buff.OriginTopPath)
				select buff));
		}

		public override bool CanPlaceAt(Vector2 at, Tower? tower, ref string helperMessage)
		{
			if (tower == null)
			{
				helperMessage = "Must be placed on a tower.";
				return false;
			}
			if (!tower.IsSelectable)
			{
				helperMessage = "Can't select that tower";
				return false;
			}
			if (TowerModelBehaviorExt.HasBehavior<IgnoreAllMutatorsTowerModel>(tower.towerModel))
			{
				helperMessage = "That tower can't be mutated.";
				return false;
			}
			return CanApplyTo(tower, ref helperMessage);
		}

		public override void OnPlace(Vector2 at, TowerModel towerModelFake, Tower? hoveredTower, float towerCost)
		{
			if (hoveredTower != null)
			{
				hoveredTower.worth += towerCost;
				Apply(hoveredTower, towerCost, sideEffects: true);
				UpdateDiscounts();
			}
		}

		public int GetStackCount(Tower? tower)
		{
			BuffInShopMutator.Data data = default(BuffInShopMutator.Data);
			return (tower != null && ((ModMutator<BuffInShopMutator.Data>)Mutator).Get((Mutable)(object)tower, ref data) != null) ? data.Stacks : 0;
		}

		public bool HasBuff(Tower tower)
		{
			return ((ModMutator)Mutator).Get((Mutable)(object)tower) != null;
		}

		public bool HasBuff(Tower tower, out float towerCost)
		{
			BuffInShopMutator.Data data = default(BuffInShopMutator.Data);
			bool flag = ((ModMutator<BuffInShopMutator.Data>)Mutator).Get((Mutable)(object)tower, ref data) != null;
			towerCost = (flag ? data.Cost : 0f);
			return flag;
		}

		public virtual BehaviorMutator GetMutator(Tower? tower)
		{
			return null;
		}

		public virtual IEnumerable<BehaviorMutator> GetMutators(Tower? tower)
		{
			yield return GetMutator(tower);
		}

		public virtual bool CanApplyTo(Tower tower, ref string helperMessage)
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			TimedMutator val = default(TimedMutator);
			if (GetStackCount(tower) >= MaxStacks || (MaxStacks == 1 && defaultMutators.Length != 0 && defaultMutators.All((BehaviorMutator defaultMutator) => Il2CppSystemObjectExt.Is<TimedMutator>(((Mutable)tower).GetMutatorById(defaultMutator.id), ref val) && val.mutator.priority >= defaultMutator.priority)))
			{
				helperMessage = "Tower already buffed.";
				return false;
			}
			if (tower.IsParagonBased() && !ParagonAllowed)
			{
				helperMessage = "Can't buff Paragons.";
				return false;
			}
			ObjectId parentId = ((CommonBehaviorProxy<ITowerBehavior>)(object)tower).ParentId;
			if (((ObjectId)(ref parentId)).IsValid)
			{
				helperMessage = "Can't apply directly to sub towers";
				return false;
			}
			return true;
		}

		public virtual void Apply(Tower tower, float purchaseCost = -1f, bool sideEffects = false)
		{
			BehaviorMutator[] array = GetMutators(tower).ToArray();
			BehaviorMutator[] array2 = array;
			foreach (BehaviorMutator val in array2)
			{
				val.priority += PriorityBoost;
				val.cantBeAbsorbed = true;
			}
			bool flag = ModSettingBool.op_Implicit(BuffsInShopMod.AlwaysAffectSubTowers) || AffectsSubTowers;
			if (purchaseCost > -1f)
			{
				int stackCount = GetStackCount(tower);
				((Mutable)tower).RemoveMutatorsById(((ModMutator)Mutator).MutatorId);
				BehaviorMutator val2 = ((ModMutator<BuffInShopMutator.Data>)Mutator).Create(new BuffInShopMutator.Data
				{
					Cost = purchaseCost,
					Stacks = stackCount + 1
				});
				if (tower.IsParagonBased())
				{
					tower.AddParagonMutator(val2, -1, true, true, false, true, -1);
				}
				else
				{
					((Mutable)tower).AddMutator(val2, -1, true, true, false, true, false, false, false, -1, false, false);
				}
			}
			foreach (string mutatorId in MutatorIds)
			{
				if (flag)
				{
					tower.RemoveMutatorsIncludeSubTowersById(mutatorId);
				}
				else
				{
					((Mutable)tower).RemoveMutatorsById(mutatorId);
				}
			}
			BehaviorMutator[] array3 = array;
			foreach (BehaviorMutator val3 in array3)
			{
				if (flag)
				{
					if (ParagonAllowed && tower.IsParagonBased())
					{
						tower.AddParagonMutatorIncludeSubTowers(val3, -1, true, true, false, true, -1);
					}
					else
					{
						tower.AddMutatorIncludeSubTowers(val3, -1, true, true, false, true, -1);
					}
				}
				else if (ParagonAllowed && tower.IsParagonBased())
				{
					tower.AddParagonMutator(val3, -1, true, true, false, true, -1);
				}
				else
				{
					((Mutable)tower).AddMutator(val3, -1, true, true, false, true, false, false, false, -1, false, false);
				}
			}
		}

		public virtual bool ExtraMutation(TowerModel towerModel)
		{
			return false;
		}

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

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

		public virtual bool IsBlocked(TowerInventory ti)
		{
			int num = default(int);
			return !AlwaysUsable && OriginTower != null && ((ti.towerMaxes.TryGetValue(OriginTower, ref num) && num == 0) || OriginTiers.Where((int tier, int path) => tier != 0 && ti.IsPathTierLocked(new Tower
			{
				towerModel = OriginTowerModel
			}, path, tier)).Any());
		}

		internal static void UpdateDiscounts()
		{
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Expected O, but got Unknown
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Expected O, but got Unknown
			if (SimulationExt.Current == null)
			{
				return;
			}
			List<TowerDiscount> towerDiscounts = SimulationExt.Current.GetTowerInventory(InGame.Bridge.MyPlayerNumber).towerDiscounts;
			Il2CppArrayBase<Tower> source = Enumerable.ToArray<Tower>(SimulationExt.Current.towerManager.GetTowers());
			ITowerPurchaseButton val3 = default(ITowerPurchaseButton);
			foreach (ModBuffInShop buff in from modBuffInShop in ModContent.GetContent<ModBuffInShop>()
				where modBuffInShop.SubsequentDiscount
				select modBuffInShop)
			{
				bool flag = ((IEnumerable<Tower>)source).Any(buff.HasBuff);
				int num = Il2CppGenerics.FindIndex<TowerDiscount>(towerDiscounts, (Func<TowerDiscount, bool>)((TowerDiscount d) => d.id == ((ModContent)buff).Id));
				if (flag != num >= 0)
				{
					if (flag)
					{
						TowerDiscount val = new TowerDiscount();
						val.id = ((ModContent)buff).Id;
						val.towers = new Il2CppStringArray(new string[1] { ((ModContent)buff).Id });
						val.charges = 99999999;
						val.multiplier = 0.5f;
						val.subtraction = 0f;
						towerDiscounts.Add(val);
					}
					else
					{
						towerDiscounts.RemoveAt(num);
					}
					ShopMenu instance = ShopMenuExt.instance;
					Transform val2 = ((instance != null) ? instance.GetTowerButtonFromBaseId(((ModContent)buff).Id) : null);
					if ((Object)(object)val2 != (Object)null && Il2CppSystemObjectExt.Is<ITowerPurchaseButton>(((Component)val2).GetComponentInChildren<ITowerPurchaseButton>(), ref val3))
					{
						val3.SetDirty();
					}
				}
			}
		}
	}
	public abstract class ModBuffInShop<T> : ModBuffInShop where T : ModBuffInShop
	{
		public override int PriorityBoost => ModContent.GetInstance<T>().PriorityBoost + 1;

		public override bool CanApplyTo(Tower tower, ref string helperMessage)
		{
			if (!base.CanApplyTo(tower, ref helperMessage))
			{
				return false;
			}
			T instance = ModContent.GetInstance<T>();
			if (!instance.HasBuff(tower))
			{
				helperMessage = "Must have the " + ((NamedModContent)instance).DisplayName + " buff";
				return false;
			}
			return true;
		}
	}
	public abstract class ModBuffInShopGeraldo : ModBuffInShop
	{
		public override string OriginTower => TowerType.Geraldo;

		public override bool Hero => true;

		public virtual string GeraldoItemId => ((ModContent)this).Name;

		public GeraldoItemModel GeraldoItem => ModBuffInShop.GameModel.GetGeraldoItemWithName(GeraldoItemId);

		public override AudioClipReference PlacementSound => ((Model)GeraldoItem).GetDescendant<CreateSoundOnGeraldoItemModel>().soundId;

		public override EffectModel PlacementEffect
		{
			get
			{
				//IL_000d: 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_0031: Expected O, but got Unknown
				CreateEffectOnGeraldoItemModel descendant = ((Model)GeraldoItem).GetDescendant<CreateEffectOnGeraldoItemModel>();
				return CreateEffectModelExt.Create(new Args
				{
					assetId = descendant.effectId,
					lifespan = descendant.lifespan
				});
			}
		}

		public abstract string ItemLocsId { get; }

		public override string DisplayName => "[" + ItemLocsId + " name]";

		public override string BaseDescription => "[" + ItemLocsId + " description]";

		public override float BaseCost => GeraldoItem.cost * 5;
	}
	public abstract class ModBuffInShopParagon : ModBuffInShop
	{
		public override int OriginTopPath => 5;

		public override int OriginMidPath => 5;

		public override int OriginBotPath => 5;

		public override UpgradeModel? OriginUpgradeModel => Game.instance.model.GetParagonUpgrade(OriginTower);

		public override TowerModel OriginTowerModel => Game.instance.model.GetParagonTower(OriginTower);
	}
	public static class ModHelperData
	{
		public const string WorksOnVersion = "55.0";

		public const string Version = "1.1.4";

		public const string Name = "Buffs in Shop";

		public const string Description = "Adds many tower buffs to the in game shop that can be directly purchased for towers.\nSee the home page Readme for full details.";

		public const string RepoOwner = "doombubbles";

		public const string PrevRepoName = "buffs-in-shop";

		public const string RepoName = "BuffsInShop";

		public const string Icon = "Buffs-Button.png";
	}
	[HarmonyPatch(typeof(MapSaveLoader), "LoadMapSaveData")]
	internal static class MapSaveLoader_LoadMapSaveData
	{
		[HarmonyPostfix]
		internal static void Postfix(Simulation sim, MapSaveDataModel mapData)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			if (mapData == null)
			{
				return;
			}
			Enumerator<TowerSaveDataModel> enumerator = mapData.placedTowers.GetEnumerator();
			while (enumerator.MoveNext())
			{
				TowerSaveDataModel current = enumerator.Current;
				if (current != null)
				{
					Tower towerById = sim.towerManager.GetTowerById(current.IdLastSave);
					BuffsInShopMod.OnLateTowerLoaded(towerById, current);
				}
			}
		}
	}
	[HarmonyPatch(typeof(TowerManager), "GetFreeUpgrade")]
	internal static class TowerManager_GetFreeUpgrade
	{
		[HarmonyPostfix]
		internal static void Postfix(Tower tower, int tier, ref bool __result)
		{
			__result |= TowerModelBehaviorExt.GetBehaviors<FreeUpgradeSupportModel>(tower.towerModel).Any((FreeUpgradeSupportModel model) => model.upgrade < 0 && tier <= -model.upgrade);
		}
	}
	[HarmonyPatch(typeof(TowerManager), "GetZoneDiscount")]
	internal static class TowerManager_GetZoneDiscount
	{
		[HarmonyPostfix]
		internal static void Postfix(TowerModel towerModel, Dictionary<string, List<DiscountZone>> __result)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			foreach (DiscountZoneModModel behavior in TowerModelBehaviorExt.GetBehaviors<DiscountZoneModModel>(towerModel))
			{
				DiscountZoneModel val = ModelSerializer.DeserializeModel<DiscountZoneModel>(behavior.specificScriptId);
				__result.TryAdd(val.stackName, new List<DiscountZone>());
				__result[val.stackName].Add(new DiscountZone
				{
					discountZoneModel = val
				});
			}
		}
	}
	[HarmonyPatch(typeof(Simulation), "StockStandardTowerInventory")]
	internal static class Simulation_StockStandardTowerInventory
	{
		[HarmonyPostfix]
		internal static void Postfix(TowerInventory ti)
		{
			if (!ModSettingBool.op_Implicit(BuffsInShopMod.RequireBuffOriginUsable))
			{
				return;
			}
			foreach (ModBuffInShop item in from buff in ModContent.GetContent<ModBuffInShop>()
				where buff.IsBlocked(ti)
				select buff)
			{
				ti.towerMaxes[((ModContent)item).Id] = 0;
			}
		}
	}
	[HarmonyPatch(typeof(TowerInventory))]
	internal static class TowerInventory_TowerChanged
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(TowerInventory), "DestroyedTower", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(TowerInventory), "CreatedTower", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(TowerInventory), "UpdatedTower", (Type[])null, (Type[])null);
		}

		[HarmonyPostfix]
		internal static void Postfix()
		{
			TaskScheduler.ScheduleTask((Action)ModBuffInShop.UpdateDiscounts, (Func<bool>)null);
		}
	}
	[HarmonyPatch(typeof(TowerModel), "GetPrimaryWeaponThrowMarkerHeight")]
	internal static class TowerModel_GetPrimaryWeaponThrowMarkerHeight
	{
		[HarmonyPrefix]
		internal static bool Prefix(TowerModel __instance, ref float __result)
		{
			if (!ModBuffInShop.Cache.ContainsKey(((EntityModel)__instance).baseId))
			{
				return true;
			}
			__result = 0f;
			return false;
		}
	}
	[HarmonyPatch(typeof(Simulation), "RoundEnd")]
	internal static class Simulation_RoundEnd
	{
		[HarmonyPostfix]
		internal static void Postfix(Simulation __instance)
		{
			ModContent.GetInstance<Ultraboost>().HandleBoosting(__instance);
		}
	}
}
namespace BuffsInShop.Buff
{
	public class AbsoluteZero : ModBuffInShop
	{
		public override string OriginTower => TowerType.IceMonkey;

		public override int OriginMidPath => 5;

		public override string BaseDescription => "Gives an Ice Monkey 50% increased attack speed.";

		public override bool SubsequentDiscount => true;

		public override KeyCode KeyCode => (KeyCode)48;

		public override AudioClipReference? PlacementSound => ((Model)OriginTowerModel).GetDescendant<CreateSoundOnAbilityModel>().sound.assetId;

		public override EffectModel? PlacementEffect => ((Model)OriginTowerModel).GetDescendant<CreateEffectOnAbilityModel>().effectModel;

		public override bool IsValidOrigin(TowerModel current)
		{
			return ModelExt.HasDescendant<ActivateRateSupportZoneModel>((Model)(object)current);
		}

		public override bool CanApplyTo(Tower tower, ref string helperMessage)
		{
			if (!ModSettingBool.op_Implicit(BuffsInShopMod.BypassTowerRestrictions) && ((EntityModel)tower.towerModel).baseId != TowerType.IceMonkey)
			{
				helperMessage = "Must be an Ice Monkey.";
				return false;
			}
			return base.CanApplyTo(tower, ref helperMessage);
		}

		public override BehaviorMutator GetMutator(Tower? tower)
		{
			return (BehaviorMutator)(object)((Model)OriginTowerModel).GetDescendant<ActivateRateSupportZoneModel>().CreateMutator();
		}
	}
	public class AbyssDwelling : ModBuffInShop
	{
		public override string OriginTower => TowerType.Mermonkey;

		public override int OriginTopPath => 3;

		public override string BaseDescription => "Gives a tower 10% increased pierce.";

		public override float BaseCost => 800f;

		public override bool SubsequentDiscount => true;

		public override KeyCode KeyCode => (KeyCode)91;

		public override BehaviorMutator GetMutator(Tower? tower)
		{
			return (BehaviorMutator)(object)TowerModelBehaviorExt.GetBehavior<PiercePercentageSupportModel>(OriginTowerModel).CreateMutator();
		}
	}
	public class AcidicMixtureDip : ModBuffInShop
	{
		private TowerModel AlchemistPerma => ModBuffInShop.GameModel.GetTower(OriginTower, 5, 0, 0);

		public override string OriginTower => TowerType.Alchemist;

		public override int OriginTopPath => 2;

		public override float BaseCost => base.UpgradeCost * 10f;

		public override string BaseDescription => "Makes a tower able to pop Lead Bloons and deal extra damage to Ceramic and MOAB-class Bloons.";

		public override KeyCode KeyCode => (KeyCode)97;

		public override bool SubsequentDiscount => true;

		public override bool AffectsSubTowers => false;

		public override EffectModel? PlacementEffect => ((Model)TowerModelExt.GetAttackModel(AlchemistPerma, 1)).GetDescendant<CreateEffectOnExhaustFractionModel>().effectModel;

		public override AudioClipReference? PlacementSound => Il2CppGenericIEnumerable.AsIEnumerable<SoundModel>(((Model)TowerModelExt.GetAttackModel(AlchemistPerma, 2)).GetDescendants<SoundModel>()).Skip(0).First()
			.assetId;

		public override bool CanApplyTo(Tower tower, ref string helperMessage)
		{
			if (!ModSettingBool.op_Implicit(BuffsInShopMod.BypassTowerRestrictions) && ((Model)AlchemistPerma).GetDescendant<AddAcidicMixtureToProjectileModel>().ignoreList.Contains(((EntityModel)tower.towerModel).baseId))
			{
				helperMessage = "Invalid tower for Alchemist buff.";
				return false;
			}
			return base.CanApplyTo(tower, ref helperMessage);
		}

		public override BehaviorMutator GetMutator(Tower? tower)
		{
			return (BehaviorMutator)(object)ModelExt.Duplicate<AddAcidicMixtureToProjectileModel>(((Model)AlchemistPerma).GetDescendant<AddAcidicMixtureToProjectileModel>()).Mutator;
		}
	}
	public class ArtilleryCommand : ModBuffInShop
	{
		public class ArtilleryCommandIcon : ModBuffIcon
		{
		}

		public override string OriginTower => TowerType.StrikerJones;

		public override int OriginTopPath => 19;

		public override bool Hero => true;

		public override string BaseDescription => "Gives a Bomb Shooter or Mortary Monkey double damage and pierce.";

		public override float BaseCost => 40000f;

		public override bool SubsequentDiscount => true;

		public override AudioClipReference? PlacementSound => AbilityModelBehaviorExt.GetBehavior<CreateSoundOnAbilityModel>(TowerModelBehaviorExt.GetBehavior<AbilityModel>(OriginTowerModel)).sound.assetId;

		public override EffectModel? PlacementEffect => ((Model)OriginTowerModel).GetDescendant<ArtilleryCommandModel>().otherTowerEffectModel;

		public override bool IsValidOrigin(TowerModel current)
		{
			return ModelExt.HasDescendant<ArtilleryCommandModel>((Model)(object)current);
		}

		public override bool CanApplyTo(Tower tower, ref string helperMessage)
		{
			if (!ModSettingBool.op_Implicit(BuffsInShopMod.BypassTowerRestrictions) && ((EntityModel)tower.towerModel).baseId != TowerType.BombShooter && ((EntityModel)tower.towerModel).baseId != TowerType.MortarMonkey)
			{
				helperMessage = "Must be a Bomb Shooter or Mortar Monkey.";
				return false;
			}
			return base.CanApplyTo(tower, ref helperMessage);
		}

		public override BehaviorMutator GetMutator(Tower? tower)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			return ((BehaviorMutator)new ArtilleryCommandDamageMutator()).ApplyBuffIcon<ArtilleryCommandIcon>();
		}
	}
	public class BankHack : ModBuffInShop
	{
		public override string OriginTower => TowerType.Benjamin;

		public override int OriginTopPath => 8;

		public override bool Hero => true;

		public override string BaseDescription => "Gives a Monkey Bank 12% increased income generation.";

		public override float BaseCost => 2500f;

		public override bool SubsequentDiscount => true;

		public override bool AllowInChimps => false;

		public override AudioClipReference PlacementSound => new AudioClipReference("1e8f6916f463550449a46307a385746e");

		public override EffectModel PlacementEffect => new EffectModel("", new PrefabReference("8a3a3ac08ba475e49a36389cea1356e4"), 1f, 1f);

		public override bool CanApplyTo(Tower tower, ref string helperMessage)
		{
			if (!ModSettingBool.op_Implicit(BuffsInShopMod.BypassTowerRestrictions) && !TowerModelBehaviorExt.HasBehavior<BankModel>(tower.towerModel))
			{
				helperMessage = "Must be a Monkey Bank.";
				return false;
			}
			return base.CanApplyTo(tower, ref helperMessage);
		}

		public override BehaviorMutator GetMutator(Tower? tower)
		{
			return (BehaviorMutator)(object)TowerModelBehaviorExt.GetBehavior<BananaCashIncreaseSupportModel>(OriginTowerModel).CreateMutator();
		}
	}
	public class BerserkerBrew : ModBuffInShop
	{
		private TowerModel AlchemistPerma => ModBuffInShop.GameModel.GetTower(OriginTower, 5, 0, 0);

		public override string OriginTower => TowerType.Alchemist;

		public override int OriginTopPath => 3;

		public override float BaseCost => base.UpgradeCost * 5f;

		public override string BaseDescription => "Gives a tower a brew that increases damage, pierce, range and attack speed.";

		public override KeyCode KeyCode => (KeyCode)98;

		public override bool SubsequentDiscount => true;

		public override bool AffectsSubTowers => false;

		public override EffectModel? PlacementEffect => ((Model)TowerModelExt.GetAttackModel(AlchemistPerma, 2)).GetDescendant<CreateEffectOnExhaustFractionModel>().effectModel;

		public override AudioClipReference? PlacementSound => Il2CppGenericIEnumerable.AsIEnumerable<SoundModel>(((Model)TowerModelExt.GetAttackModel(AlchemistPerma, 2)).GetDescendants<SoundModel>()).Skip(1).First()
			.assetId;

		public override bool CanApplyTo(Tower tower, ref string helperMessage)
		{
			if (!ModSettingBool.op_Implicit(BuffsInShopMod.BypassTowerRestrictions) && ((Model)AlchemistPerma).GetDescendant<AddBerserkerBrewToProjectileModel>().ignoreList.Contains(((EntityModel)tower.towerModel).baseId))
			{
				helperMessage = "Invalid tower for Alchemist buff.";
				return false;
			}
			return base.CanApplyTo(tower, ref helperMessage);
		}

		public override BehaviorMutator GetMutator(Tower? tower)
		{
			AddBerserkerBrewToProjectileModel val = ModelExt.Duplicate<AddBerserkerBrewToProjectileModel>(((Model)AlchemistPerma).GetDescendant<AddBerserkerBrewToProjectileModel>());
			AddBerserkerBrewToProjectileModel descendant = ((Model)OriginTowerModel).GetDescendant<AddBerserkerBrewToProjectileModel>();
			val.mutator = null;
			val.damageUp = descendant.damageUp;
			val.pierceUp = descendant.pierceUp;
			val.rangeUp = descendant.rangeUp;
			val.rateUp = descendant.rateUp;
			val.buffIconName = descendant.buffIconName;
			val.buffLocsName = descendant.buffLocsName;
			BeserkerBrewMutator mutator = val.Mutator;
			((BehaviorMutator)mutator).buffIndicator = descendant.GetBuffIndicatorModel();
			return (BehaviorMutator)(object)mutator;
		}
	}
	public class BloodSacrifice : ModBuffInShop
	{
		public override string OriginTower => TowerType.Adora;

		public override int OriginTopPath => 19;

		public override bool Hero => true;

		public override string BaseDescription => "Gives Adora or a Sun Avatar/Temple/God 10% increased range and 10% reduced reload time, but puts you $500 in debt. " + $"Can be purchased up to {MaxStacks} times per tower, doubling the debt each time.";

		public override float BaseCost => 1000f;

		public override AudioClipReference? PlacementSound => AbilityModelBehaviorExt.GetBehavior<CreateSoundOnAbilityModel>(TowerModelBehaviorExt.GetBehavior<AbilityModel>(OriginTowerModel, ((ModContent)this).Name)).sound.assetId;

		public override EffectModel? PlacementEffect => AbilityModelBehaviorExt.GetBehavior<BloodSacrificeModel>(TowerModelBehaviorExt.GetBehavior<AbilityModel>(OriginTowerModel, ((ModContent)this).Name)).effectAtSacrificeModel;

		public override int MaxStacks => 5;

		public override bool IsValidOrigin(TowerModel current)
		{
			AbilityModel val = default(AbilityModel);
			return TowerModelBehaviorExt.HasBehavior<AbilityModel>(current, ((ModContent)this).Name, ref val);
		}

		public override bool CanApplyTo(Tower tower, ref string helperMessage)
		{
			if (IEnumerableExt.OfIl2CppType<ImfLoanCollection>((IEnumerable)((RootObject)tower).Sim.GetBehaviors().ToArray()).Any((ImfLoanCollection loan) => ((Model)loan.imfLoanCollectionModel).name.Contains(((ModContent)this).Name + ((object)((RootObject)tower).Id/*cast due to .constrained prefix*/).ToString())))
			{
				helperMessage = "Still in debt from last purchase";
				return false;
			}
			if (!ModSettingBool.op_Implicit(BuffsInShopMod.BypassTowerRestrictions) && ((EntityModel)tower.towerModel).baseId != TowerType.Adora && (!(((EntityModel)tower.towerModel).baseId == TowerType.SuperMonkey) || ((Il2CppArrayBase<int>)(object)tower.towerModel.tiers)[0] < 3))
			{
				helperMessage = "Must be Adora or a Sun Avatar/Temple/God";
				return false;
			}
			TimedMutator mutatorById = ((Mutable)tower).GetMutatorById("BloodSacrificeBuff");
			if (mutatorById != null)
			{
				BehaviorMutator mutator = mutatorById.mutator;
				BloodSacrificeMutator val = default(BloodSacrificeMutator);
				if (((mutator != null) ? new bool?(Il2CppSystemObjectExt.Is<BloodSacrificeMutator>((Il2CppObjectBase)(object)mutator, ref val)) : ((bool?)null)) == true && val.bonusCount >= 40)
				{
					helperMessage = "Sacrifice Level is at maximum";
					return false;
				}
			}
			return base.CanApplyTo(tower, ref helperMessage);
		}

		public override BehaviorMutator GetMutator(Tower? tower)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			BloodSacrificeModel descendant = ((Model)OriginTowerModel).GetDescendant<BloodSacrificeModel>();
			int num = 0;
			if (tower != null)
			{
				TimedMutator mutatorById = ((Mutable)tower).GetMutatorById("BloodSacrificeBuff");
				bool? obj;
				BloodSacrificeMutator val = default(BloodSacrificeMutator);
				if (mutatorById == null)
				{
					obj = null;
				}
				else
				{
					BehaviorMutator mutator = mutatorById.mutator;
					obj = ((mutator != null) ? new bool?(Il2CppSystemObjectExt.Is<BloodSacrificeMutator>((Il2CppObjectBase)(object)mutator, ref val)) : ((bool?)null));
				}
				bool? flag = obj;
				if (flag == true)
				{
					num = val.bonusCount + 10;
				}
			}
			return (BehaviorMutator)new BloodSacrificeMutator(descendant, num, ((Model)OriginTowerModel).name);
		}

		public override void Apply(Tower tower, float purchaseCost = -1f, bool sideEffects = false)
		{
			base.Apply(tower, purchaseCost, sideEffects);
			if (sideEffects)
			{
				int stackCount = GetStackCount(tower);
				double debt = 250.0 * Math.Pow(2.0, stackCount);
				TaskScheduler.ScheduleTask((Action)delegate
				{
					//IL_0010: Unknown result type (might be due to invalid IL or missing references)
					//IL_0015: Unknown result type (might be due to invalid IL or missing references)
					//IL_0031: 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_004e: Expected O, but got Unknown
					//IL_004f: Unknown result type (might be due to invalid IL or missing references)
					//IL_005b: Unknown result type (might be due to invalid IL or missing references)
					//IL_006e: Expected O, but got Unknown
					Simulation sim = ((RootObject)tower).Sim;
					Args val = new Args();
					((ModelArgs<ImfLoanCollectionModel>)val).name = ((ModContent)this).Name + ((object)((RootObject)tower).Id/*cast due to .constrained prefix*/).ToString();
					val.collectionRate = 0.5f;
					val.amount = (float)debt;
					sim.AddBehavior<ImfLoanCollection>((SimulationBehaviorModel)(object)CreateImfLoanCollectionModelExt.Create(val));
				}, (Func<bool>)null);
			}
		}
	}
	public class BombExpert : ModBuffInShop
	{
		public override string OriginTower => TowerType.StrikerJones;

		public override int OriginTopPath => 17;

		public override bool Hero => true;

		public override string BaseDescription => "Gives a tower +5% range and 25% pierce. A Bomb Shooter gets 24% increased attack speed, and a Mortar Monkey gets that as well as 10% increased blast radius.";

		public override float BaseCost => 2000f;

		public override bool SubsequentDiscount => true;

		public override IEnumerable<BehaviorMutator> GetMutators(Tower? tower)
		{
			RateSupportExplosiveModel mainBuff = TowerModelBehaviorExt.GetBehavior<RateSupportExplosiveModel>(OriginTowerModel);
			RateSupportBombExpertModel bombExport = ModelExt.Duplicate<RateSupportBombExpertModel>(TowerModelBehaviorExt.GetBehavior<RateSupportBombExpertModel>(OriginTowerModel));
			((SupportModel)bombExport).buffLocsName = ((SupportModel)mainBuff).buffLocsName;
			((SupportModel)bombExport).buffIconName = ((SupportModel)mainBuff).buffIconName;
			((Model)bombExport).AddChildDependant<BuffIndicatorModel>(CreateBuffIndicatorModelExt.Create(new Args
			{
				buffName = ((SupportModel)bombExport).buffLocsName,
				iconName = ((SupportModel)bombExport).buffIconName
			}));
			yield return (BehaviorMutator)(object)bombExport.CreateMutator();
			int num;
			if (!(((tower != null) ? ((EntityModel)tower.towerModel).baseId : null) == TowerType.BombShooter))
			{
				num = ((((tower != null) ? ((EntityModel)tower.towerModel).baseId : null) == TowerType.MortarMonkey) ? 1 : 0);
			}
			else
			{
				num = 1;
			}
			if (num != 0)
			{
				yield return (BehaviorMutator)(object)mainBuff.CreateMutator();
			}
			if (((tower != null) ? ((EntityModel)tower.towerModel).baseId : null) == TowerType.MortarMonkey)
			{
				yield return (BehaviorMutator)(object)TowerModelBehaviorExt.GetBehavior<ProjectileRadiusSupportModel>(OriginTowerModel).CreateMutator();
			}
		}
	}
	public class BottleHotSauce : ModBuffInShopGeraldo
	{
		public override string ItemLocsId => "Gerrys fire hot sauce";

		public override EffectModel PlacementEffect
		{
			get
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: 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_0030: Expected O, but got Unknown
				PrefabReference effectAtTowerId = ((Model)base.GeraldoItem).GetDescendant<BottleHotSauceBehaviorModel>().effectAtTowerId;
				return CreateEffectModelExt.Create(new Args
				{
					assetId = effectAtTowerId,
					lifespan = 1f
				});
			}
		}

		public override bool AffectsSubTowers => false;

		public override bool CanApplyTo(Tower tower, ref string helperMessage)
		{
			if (!((Model)base.GeraldoItem).GetDescendant<BottleHotSauceBehaviorModel>().IsTowerModelValid(tower.towerModel))
			{
				helperMessage = "Invalid tower";
				return false;
			}
			return base.CanApplyTo(tower, ref helperMessage);
		}

		public override BehaviorMutator GetMutator(Tower? tower)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			return (BehaviorMutator)new BottleHotSauceMutator(((Model)base.GeraldoItem).GetDescendant<BottleHotSauceBehaviorModel>());
		}

		public override void Apply(Tower tower, float purchaseCost = -1f, bool sideEffects = false)
		{
			//IL_0037: 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_004e: Unknown result type (might be due to invalid IL or missing references)
			base.Apply(tower, purchaseCost, sideEffects);
			if (sideEffects)
			{
				Tower val = ((RootObject)tower).Sim.towerManager.CreateTower(((RootObject)tower).Sim.model.GetTowerWithName("HotSauceCreatureTowerV2"), Vector3Boxed.op_Implicit(((CommonBehaviorProxy<ITowerBehavior>)(object)tower).Position), tower.owner, ((RootObject)tower.GetAreaTowerIsPlacedOn()).Id, ((RootObject)tower).Id, (TowerSaveDataModel)null, false, true, 0f, true, -1, -1);
				val.SetTargetType(((CommonBehaviorProxy<ITowerBehavior>)(object)tower).TargetType);
			}
		}
	}
	public class CallToArms : ModBuffInShop
	{
		public override string OriginTower => TowerType.MonkeyVillage;

		public override int OriginMidPath => 4;

		public override float BaseCost => base.UpgradeCost;

		public override string BaseDescription => "Gives a tower +50% attack speed and pops.";

		public override KeyCode KeyCode => (KeyCode)99;

		public override bool SubsequentDiscount => true;

		public override AudioClipReference? PlacementSound => ((Model)OriginTowerModel).GetDescendant<CreateSoundOnAbilityModel>().sound.assetId;

		public override EffectModel? PlacementEffect => ((Model)OriginTowerModel).GetDescendant<CreateEffectOnAbilityModel>().effectModel;

		public override bool IsValidOrigin(TowerModel current)
		{
			return ModelExt.HasDescendant<CallToArmsModel>((Model)(object)current);
		}

		public override BehaviorMutator GetMutator(Tower? tower)
		{
			CallToArmsModel val = ModelExt.Duplicate<CallToArmsModel>(((Model)OriginTowerModel).GetDescendant<CallToArmsModel>());
			BuffIndicatorModel buffIndicator = ((BehaviorMutator)val.Mutator).buffIndicator;
			val._mutator = null;
			CallToArmsMutator mutator = val.Mutator;
			((BehaviorMutator)mutator).buffIndicator = buffIndicator;
			return (BehaviorMutator)(object)mutator;
		}
	}
	public class Echosense : ModBuffInShop
	{
		public override string OriginTower => TowerType.Mermonkey;

		public override int OriginBotPath => 2;

		public override float BaseCost => base.UpgradeCost;

		public override string BaseDescription => $"Gives a Mermonkey 6% increased range. Stackable up to {MaxStacks} times.";

		public override int MaxStacks => 10;

		public override bool CanApplyTo(Tower tower, ref string helperMessage)
		{
			if (!ModSettingBool.op_Implicit(BuffsInShopMod.BypassTowerRestrictions) && ((EntityModel)tower.towerModel).baseId != TowerType.Mermonkey)
			{
				helperMessage = "Must be a Mermonkey";
				return false;
			}
			return base.CanApplyTo(tower, ref helperMessage);
		}

		public override BehaviorMutator GetMutator(Tower? tower)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			int num = ((tower == null) ? (-1) : GetStackCount(tower));
			SupportStackingRangeModel behavior = TowerModelBehaviorExt.GetBehavior<SupportStackingRangeModel>(OriginTowerModel);
			return (BehaviorMutator)new MutatorTower(new SupportStackingRange
			{
				supportStackingRangeModel = behavior
			}, ((SelfStackingSupportCompoundingModel)behavior).mutatorId + (num + 1));
		}
	}
	public class EliteSniping : ModBuffInShop
	{
		public override string OriginTower => TowerType.SniperMonkey;

		public override int OriginMidPath => 5;

		public override float BaseCost => 2000f;

		public override string BaseDescription => "Gives a Sniper Monkey Elite targeting prio and 33% more attack speed.";

		public override KeyCode KeyCode => (KeyCode)108;

		public override bool SubsequentDiscount => true;

		public override AudioClipReference? PlacementSound => TowerModelBehaviorExt.GetBehavior<CreateSoundOnTowerPlaceModel>(OriginTowerModel).sound1.assetId;

		public override bool CanApplyTo(Tower tower, ref string helperMessage)
		{
			if (!ModSettingBool.op_Implicit(BuffsInShopMod.BypassTowerRestrictions) && ((EntityModel)tower.towerModel).baseId != TowerType.SniperMonkey)
			{
				helperMessage = "Must be a Sniper Monkey.";
				return false;
			}
			return base.CanApplyTo(tower, ref helperMessage);
		}

		public override IEnumerable<BehaviorMutator> GetMutators(Tower? tower)
		{
			yield return (BehaviorMutator)(object)TowerModelBehaviorExt.GetBehavior<RateSupportModel>(OriginTowerModel).CreateMutator();
			yield return (BehaviorMutator)(object)TowerModelBehaviorExt.GetBehavior<TargetSupplierSupportModel>(OriginTowerModel).CreateMutator();
		}
	}
	public class Energized : ModBuffInShop
	{
		public override string OriginTower => TowerType.MonkeySub;

		public override int OriginTopPath => 5;

		public override float BaseCost => 4000f;

		public override string BaseDescription => "Gives a tower 20% reduced ability cooldowns.";

		public override KeyCode KeyCode => (KeyCode)101;

		public override bool SubsequentDiscount => true;

		public override AudioClipReference? PlacementSound => TowerModelBehaviorExt.GetBehavior<SubmergeModel>(OriginTowerModel).submergeSound.assetId;

		public override bool IsValidOrigin(TowerModel current)
		{
			return TowerModelBehaviorExt.HasBehavior<SubmergeModel>(current);
		}

		public override bool CanApplyTo(Tower tower, ref string helperMessage)
		{
			if (!TowerModelExt.GetAbilities(tower.towerModel).Any())
			{
				helperMessage = "Must have abilities.";
				return false;
			}
			return base.CanApplyTo(tower, ref helperMessage);
		}

		public override IEnumerable<BehaviorMutator> GetMutators(Tower? tower)
		{
			SubmergeModel submerge = TowerModelBehaviorExt.GetBehavior<SubmergeModel>(OriginTowerModel);
			Il2CppReferenceArray<TowerFilterModel> filters = new Il2CppReferenceArray<TowerFilterModel>(0L);
			AbilityCooldownScaleSupport val = new AbilityCooldownScaleSupport();
			Args val2 = new Args();
			((ModelArgs<AbilityCooldownScaleSupportModel>)val2).name = "SubmergeAbilityCooldownScaleGlobal";
			val2.isUnique = true;
			val2.abilityCooldownSpeedScale = submerge.abilityCooldownSpeedScaleGlobal;
			val2.filters = Il2CppArrayBase<TowerFilterModel>.op_Implicit((Il2CppArrayBase<TowerFilterModel>)(object)filters);
			val2.buffLocsName = ((TowerBehaviorBuffModel)submerge).buffLocsName;
			val2.buffIconName = "BuffIconSubHalf5xx";
			val2.mutatorPriority = submerge.supportMutatorPriority;
			val.abilityCooldownScaleSupportModel = CreateAbilityCooldownScaleSupportModelExt.Create(val2);
			yield return (BehaviorMutator)new MutatorTower(val, submerge.abilityCooldownSpeedScaleGlobal, "SubmergeAbilityCooldownScaleGlobal");
		}
	}
	public class EnergizedFully : ModBuffInShop<Energized>
	{
		public override string OriginTower => TowerType.MonkeySub;

		public override int OriginTopPath => 5;

		public override float BaseCost => base.UpgradeCost / 2f - ModContent.GetInstance<Energized>().BaseCost;

		public override string BaseDescription => "Makes an Energized tower have 40% reduced cooldowns if its in water, and/or earn XP 50% faster if its a Hero.";

		public override KeyCode KeyCode => (KeyCode)122;

		public override bool SubsequentDiscount => true;

		public override AudioClipReference? PlacementSound => TowerModelBehaviorExt.GetBehavior<SubmergeModel>(OriginTowerModel).submergeSound.assetId;

		public override bool IsValidOrigin(TowerModel current)
		{
			return TowerModelBehaviorExt.HasBehavior<SubmergeModel>(current);
		}

		public override bool CanApplyTo(Tower tower, ref string helperMessage)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Invalid comparison between Unknown and I4
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			bool flag = !tower.towerModel.IsHero();
			bool flag2 = flag;
			if (flag2)
			{
				AreaType type = tower.GetAreaTowerIsPlacedOn().areaModel.type;
				bool flag3 = (((int)type == 1 || (int)type == 6) ? true : false);
				flag2 = !flag3;
			}
			if (flag2)
			{
				helperMessage = "Must be a Hero or placed in water";
				return false;
			}
			return base.CanApplyTo(tower, ref helperMessage);
		}

		public override IEnumerable<BehaviorMutator> GetMutators(Tower? tower)
		{
			SubmergeModel submerge = TowerModelBehaviorExt.GetBehavior<SubmergeModel>(OriginTowerModel);
			Il2CppReferenceArray<TowerFilterModel> filters = new Il2CppReferenceArray<TowerFilterModel>(0L);
			bool flag = ModSettingBool.op_Implicit(BuffsInShopMod.BypassTowerRestrictions) || tower == null;
			bool flag2 = flag;
			if (!flag2)
			{
				AreaType type = tower.GetAreaTowerIsPlacedOn().areaModel.type;
				bool flag3 = (((int)type == 1 || (int)type == 6) ? true : false);
				flag2 = flag3;
			}
			if (flag2)
			{
				AbilityCooldownScaleSupport val = new AbilityCooldownScaleSupport();
				Args val2 = new Args();
				((ModelArgs<AbilityCooldownScaleSupportModel>)val2).name = "SubmergeAbilityCooldownScale";
				val2.isUnique = true;
				val2.abilityCooldownSpeedScale = submerge.abilityCooldownSpeedScale;
				val2.affectsOnlyWater = true;
				val2.filters = Il2CppArrayBase<TowerFilterModel>.op_Implicit((Il2CppArrayBase<TowerFilterModel>)(object)filters);
				val2.buffLocsName = ((TowerBehaviorBuffModel)submerge).buffLocsName;
				val2.buffIconName = ((TowerBehaviorBuffModel)submerge).buffIconName;
				val2.mutatorPriority = submerge.supportMutatorPriority;
				val.abilityCooldownScaleSupportModel = CreateAbilityCooldownScaleSupportModelExt.Create(val2);
				yield return (BehaviorMutator)new MutatorTower(val, submerge.abilityCooldownSpeedScale, "SubmergeAbilityCooldownScale");
			}
			if (ModSettingBool.op_Implicit(BuffsInShopMod.BypassTowerRestrictions) || tower == null || tower.towerModel.IsHero())
			{
				HeroXpScaleSupport val3 = new HeroXpScaleSupport();
				Args val4 = new Args();
				((ModelArgs<HeroXpScaleSupportModel>)val4).name = "SubmergeHeroXpScale";
				val4.isUnique = true;
				val4.heroXpScale = submerge.heroXpScale;
				val4.filters = Il2CppArrayBase<TowerFilterModel>.op_Implicit((Il2CppArrayBase<TowerFilterModel>)(object)filters);
				val4.buffLocsName = ((TowerBehaviorBuffModel)submerge).buffLocsName;
				val4.buffIconName = ((TowerBehaviorBuffModel)submerge).buffIconName;
				val3.heroXpScaleSupportModel = CreateHeroXpScaleSupportModelExt.Create(val4);
				yield return (BehaviorMutator)new MutatorTower(val3);
			}
		}
	}
	public class EtienneRange : ModBuffInShop
	{
		public override string OriginTower => TowerType.Etienne;

		public override int OriginTopPath => 19;

		public override bool Hero => true;

		public override string BaseDescription => "Give a tower 20% increased range.";

		public override float BaseCost => 900f;

		public override bool SubsequentDiscount => true;

		public override AudioClipReference PlacementSound => new AudioClipReference("11a260d187420194b87a62ebdf36c216");

		public override EffectModel PlacementEffect => new EffectModel("", new PrefabReference("b99b2ce7a50d15547a91abe3cc058e4f"), 1f, 1f);

		public override BehaviorMutator GetMutator(Tower? tower)
		{
			return (BehaviorMutator)(object)TowerModelBehaviorExt.GetBehavior<RangeSupportModel>(OriginTowerModel).CreateMutator();
		}
	}
	public class Fertilizer : ModBuffInShopGeraldo
	{
		public override string ItemLocsId => "Fertilizer";

		public override bool AllowInChimps => false;

		public override float BaseCost => 5000f;

		public override bool CanApplyTo(Tower tower, ref string helperMessage)
		{
			if (!ModSettingBool.op_Implicit(BuffsInShopMod.BypassTowerRestrictions) && ((Model)base.GeraldoItem).GetDescendant<FertilizerBehaviorModel>().IsTowerModelValid(tower.towerModel))
			{
				helperMessage = "Invalid tower";
				return false;
			}
			return base.CanApplyTo(tower, ref helperMessage);
		}

		public override BehaviorMutator GetMutator(Tower? tower)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			return (BehaviorMutator)new FertilizerMutator(((Model)base.GeraldoItem).GetDescendant<FertilizerBehaviorModel>());
		}
	}
	public class FinallyHarmonizing : ModBuffInShop
	{
		public override string OriginTower => TowerType.Mermonkey;

		public override int OriginBotPath => 5;

		public override string BaseDescription => "Gives a Magic monkey +3 pierce, or a Hero 15% improved range and cooldowns.";

		public override float BaseCost => 1250f;

		public override bool SubsequentDiscount => true;

		public override KeyCode KeyCode => (KeyCode)93;

		public override bool CanApplyTo(Tower tower, ref string helperMessage)
		{
			if (!ModSettingBool.op_Implicit(BuffsInShopMod.BypassTowerRestrictions) && !tower.towerModel.CheckSet((TowerSet)4, false) && !tower.towerModel.IsHero())
			{
				helperMessage = "Must be a Magic monkey or Hero.";
				return false;
			}
			return base.CanApplyTo(tower, ref helperMessage);
		}

		public override IEnumerable<BehaviorMutator> GetMutators(Tower? tower)
		{
			if (ModSettingBool.op_Implicit(BuffsInShopMod.BypassTowerRestrictions) || tower == null || tower.towerModel.IsHero())
			{
				yield return (BehaviorMutator)(object)((Model)((Model)OriginTowerModel).GetDescendant<TowerModel>()).GetDescendant<RangeSupportModel>().CreateMutator();
				yield return (BehaviorMutator)(object)((Model)((Model)OriginTowerModel).GetDescendant<TowerModel>()).GetDescendant<AbilityCooldownScaleSupportModel>().CreateMutator();
			}
			if (ModSettingBool.op_Implicit(BuffsInShopMod.BypassTowerRestrictions) || tower == null || tower.towerModel.CheckSet((TowerSet)4, false))
			{
				yield return (BehaviorMutator)(object)((Model)((Model)OriginTowerModel).GetDescendant<TowerModel>()).GetDescendant<PierceSupportModel>().CreateMutator();
			}
		}
	}
	public class FlagshipCarried : ModBuffInShop
	{
		public override string OriginTower => TowerType.MonkeyBuccaneer;

		public override int OriginTopPath => 5;

		public override float BaseCost => ModContent.GetInstance<JungleDrums>().BaseCost;

		public override string BaseDescription => "Gives a water based monkey or Monkey Ace 18% increased attack speed.";

		public override KeyCode KeyCode => (KeyCode)102;

		public override bool SubsequentDiscount => true;

		public override AudioClipReference? PlacementSound => TowerModelBehaviorExt.GetBehavior<CreateSoundOnTowerPlaceModel>(OriginTowerModel).sound1.assetId;

		public override bool CanApplyTo(Tower tower, ref string helperMessage)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Invalid comparison between Unknown and I4
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Invalid comparison between Unknown and I4
			bool flag = !ModSettingBool.op_Implicit(BuffsInShopMod.BypassTowerRestrictions);
			bool flag2 = flag;
			bool flag4;
			bool flag5;
			if (flag2)
			{
				bool flag3 = ((EntityModel)tower.towerModel).baseId == TowerType.MonkeyAce;
				flag4 = flag3;
				if (!flag4)
				{
					Area areaTowerIsPlacedOn = tower.GetAreaTowerIsPlacedOn();
					AreaType? obj;
					if (areaTowerIsPlacedOn == null)
					{
						obj = null;
					}
					else
					{
						AreaModel areaModel = areaTowerIsPlacedOn.areaModel;
						obj = ((areaModel != null) ? new AreaType?(areaModel.type) : ((AreaType?)null));
					}
					AreaType? val = obj;
					if (val.HasValue)
					{
						AreaType valueOrDefault = val.GetValueOrDefault();
						if ((int)valueOrDefault == 1 || (int)valueOrDefault == 6)
						{
							flag5 = true;
							goto IL_0093;
						}
					}
					flag5 = false;
					goto IL_0093;
				}
				goto IL_0097;
			}
			goto IL_009d;
			IL_0097:
			flag2 = !flag4;
			goto IL_009d;
			IL_009d:
			if (flag2)
			{
				helperMessage = "Must be a water based monkey or Monkey Ace.";
				return false;
			}
			return base.CanApplyTo(tower, ref helperMessage);
			IL_0093:
			flag4 = flag5;
			goto IL_0097;
		}

		public override IEnumerable<BehaviorMutator> GetMutators(Tower? tower)
		{
			yield return (BehaviorMutator)(object)TowerModelBehaviorExt.GetBehavior<FlagshipAttackSpeedIncreaseModel>(OriginTowerModel).CreateMutator();
		}
	}
	public class GodBoost : ModBuffInShop
	{
		protected override int Order => 100;

		public override string BaseDescription => "Applies many other Buffs from the Shop at once.";

		public override string? OriginTower => null;

		public override float BaseCost => 500000f;

		public override int PriorityBoost => base.PriorityBoost + 10;

		public override bool SubsequentDiscount => true;

		public override bool AllowInChimps => false;

		public override IEnumerable<BehaviorMutator> GetMutators(Tower? tower)
		{
			return Array.Empty<BehaviorMutator>();
		}

		public override void Apply(Tower tower, float purchaseCost = -1f, bool sideEffects = false)
		{
			base.Apply(tower, purchaseCost, sideEffects);
			if (!sideEffects)
			{
				return;
			}
			foreach (ModBuffInShop item in from buff in ModContent.GetContent<ModBuffInShop>()
				orderby buff.PriorityBoost
				select buff)
			{
				string helperMessage = "";
				if (!item.IncludeInGodBoost || !item.CanApplyTo(tower, ref helperMessage))
				{
					continue;
				}
				item.Apply(tower, 0f, sideEffects: true);
				if (item.MaxStacks > 1)
				{
					for (int num = 1; num < item.MaxStacks; num++)
					{
						item.Apply(tower, 0f, sideEffects);
					}
				}
			}
		}
	}
	public class HeatedUp : ModBuffInShop
	{
		public override string OriginTower => TowerType.Gwendolin;

		public override int OriginTopPath => 4;

		public override bool Hero => true;

		public override string BaseDescription => "Gives a tower +1 Pierce and allows it to pop Lead and Frozen Bloons.";

		public override float BaseCost => 1000f;

		public override bool SubsequentDiscount => true;

		public override IEnumerable<BehaviorMutator> GetMutators(Tower? tower)
		{
			ProjectileModel proj = ((Model)OriginTowerModel).GetDescendant<BonusProjectileAfterIntervalModel>().projectileModel;
			yield return (BehaviorMutator)(object)ProjectileModelBehaviorExt.GetBehavior<PierceUpTowersModel>(proj).CreateMutator();
			yield return (BehaviorMutator)(object)ProjectileModelBehaviorExt.GetBehavior<HeatItUpDamageBuffModel>(proj).CreateMutator();
		}
	}
	public class HomelandDefense : ModBuffInShop<CallToArms>
	{
		public override string OriginTower => TowerType.MonkeyVillage;

		public override int OriginMidPath => 5;

		public override float BaseCost => base.UpgradeCost;

		public override string BaseDescription => "Gives a tower with Call to Arms now +100% attack speed and pops.";

		public override KeyCode KeyCode => (KeyCode)104;

		public override bool SubsequentDiscount => true;

		public override AudioClipReference? PlacementSound => ((Model)OriginTowerModel).GetDescendant<CreateSoundOnAbilityModel>().sound.assetId;

		public override EffectModel? PlacementEffect => ((Model)OriginTowerModel).GetDescendant<CreateEffectOnAbilityModel>().effectModel;

		public override bool IsValidOrigin(TowerModel current)
		{
			return ModelExt.HasDescendant<CallToArmsModel>((Model)(object)current);
		}

		public override BehaviorMutator GetMutator(Tower? tower)
		{
			CallToArmsModel val = ModelExt.Duplicate<CallToArmsModel>(((Model)OriginTowerModel).GetDescendant<CallToArmsModel>());
			BuffIndicatorModel buffIndicator = ((BehaviorMutator)val.Mutator).buffIndicator;
			val._mutator = null;
			CallToArmsMutator mutator = val.Mutator;
			((BehaviorMutator)mutator).buffIndicator = buffIndicator;
			return (BehaviorMutator)(object)mutator;
		}
	}
	public class IceAge : ModBuffInShop
	{
		public override string OriginTower => TowerType.Silas;

		public override int OriginTopPath => 19;

		public override bool Hero => true;

		public override string BaseDescription => "Gives a tower that can Freeze Bloons +150% Freeze duration. Ice Monkeys also get +5 range.";

		public override float BaseCost => 4000f;

		public override bool SubsequentDiscount => true;

		public override bool CanApplyTo(Tower tower, ref string helperMessage)
		{
			if (!ModelExt.HasDescendant<FreezeModel>((Model)(object)tower.towerModel))
			{
				helperMessage = "Must Freeze Bloons";
				return false;
			}
			return base.CanApplyTo(tower, ref helperMessage);
		}

		public override IEnumerable<BehaviorMutator> GetMutators(Tower? tower)
		{
			yield return (BehaviorMutator)(object)TowerModelBehaviorExt.GetBehavior<FreezeDurationSupportModel>(OriginTowerModel).CreateMutator();
			if (((tower != null) ? ((EntityModel)tower.towerModel).baseId : null) == TowerType.IceMonkey)
			{
				yield return (BehaviorMutator)(object)TowerModelBehaviorExt.GetBehavior<RangeSupportModel>(OriginTowerModel).CreateMutator();
			}
		}
	}
	public class JarOfPickles : ModBuffInShopGeraldo
	{
		public override string ItemLocsId => "Jar of Pickles";

		public override BehaviorMutator GetMutator(Tower? tower)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			return (BehaviorMutator)new JarOfPicklesMutator(((Model)base.GeraldoItem).GetDescendant<JarOfPicklesBehaviorModel>(), JarOfPicklesBehaviorModel.mutatorIdV3, 2);
		}
	}
	public class JungleDrums : ModBuffInShop
	{
		public override string OriginTower => TowerType.MonkeyVillage;

		public override int OriginTopPath => 2;

		public override string BaseDescription => "Gives a tower 18% increased attack speed.";

		public override KeyCode KeyCode => (KeyCode)106;

		public override bool SubsequentDiscount => true;

		public override BehaviorMutator GetMutator(Tower? tower)
		{
			return (BehaviorMutator)(object)TowerModelBehaviorExt.GetBehavior<RateSupportModel>(OriginTowerModel, ((ModContent)this).Name).CreateMutator();
		}
	}
	public class MonkeyCity : ModBuffInShop
	{
		public override string OriginTower => TowerType.MonkeyVillage;

		public override int OriginBotPath => 4;

		public override float BaseCost => ModContent.GetInstance<MonkeyTown>().BaseCost;

		public override string BaseDescription => "Gives a tower 20% increased cash generation.";

		public override KeyCode KeyCode => (KeyCode)121;

		public override bool SubsequentDiscount => true;

		public override bool AllowInChimps => false;

		public override bool CanApplyTo(Tower tower, ref string helperMessage)
		{
			if (!ModSettingBool.op_Implicit(BuffsInShopMod.BypassTowerRestrictions) && !defaultMutators.First().Mutate(((Mutable)tower).rootModel, (Model)(object)((Il2CppObjectBase)((Mutable)tower).rootModel.Clone()).Cast<TowerModel>()))
			{
				helperMessage = "Must have cash generation effects.";
				return false;
			}
			return base.CanApplyTo(tower, ref helperMessage);
		}

		public override BehaviorMutator GetMutator(Tower? tower)
		{
			return (BehaviorMutator)(object)TowerModelBehaviorExt.GetBehavior<MonkeyCityIncomeSupportModel>(OriginTowerModel).CreateMutator();
		}
	}
	public class MonkeyIntelligenceBureau : ModBuffInShop
	{
		public override string OriginTower => TowerType.MonkeyVillage;

		public override int OriginMidPath => 3;

		public override string BaseDescription => "Grants special Bloon popping knowledge to a Tower, allowing it to pop all Bloon types.";

		public override KeyCode KeyCode => (KeyCode)105;

		public override bool SubsequentDiscount => true;

		public override BehaviorMutator GetMutator(Tower? tower)
		{
			return (BehaviorMutator)(object)((Model)OriginTowerModel).GetDescendant<DamageTypeSupportModel>().CreateMutator();
		}
	}
	public class MonkeyTown : ModBuffInShop
	{
		public override string OriginTower => TowerType.MonkeyVillage;

		public override int OriginBotPath => 3;

		public override string BaseDescription => "Makes a monkey get 50% extra cash per Bloon pop.";

		public override KeyCode KeyCode => (KeyCode)119;

		public override bool SubsequentDiscount => true;

		public override bool AllowInChimps => false;

		public override BehaviorMutator GetMutator(Tower? tower)
		{
			return (BehaviorMutator)(object)TowerModelBehaviorExt.GetBehavior<AddBehaviorToTowerSupportModel>(OriginTowerModel, "CashUp").CreateMutator();
		}
	}
	public class MonkeyVillager : ModBuffInShop
	{
		public override string OriginTower => TowerType.MonkeyVillage;

		public override float BaseCost => base.TowerCost / 2f;

		public override string BaseDescription => "Gives a tower 10% increased range.";

		public override KeyCode KeyCode => (KeyCode)118;

		public override bool SubsequentDiscount => true;

		public override BehaviorMutator GetMutator(Tower? tower)
		{
			return (BehaviorMutator)(object)TowerModelBehaviorExt.GetBehavior<RangeSupportModel>(OriginTowerModel).CreateMutator();
		}
	}
	public class NaturesClarity : ModBuffInShop
	{
		public override string OriginTower => TowerType.ObynGreenfoot;

		public override int OriginTopPath => 11;

		public override bool Hero => true;

		public override string DisplayName => "Nature's Clarity";

		public override string BaseDescription => "Give a Magic monkey +5 range and +2 pierce.";

		public override float BaseCost => 900f;

		public override bool SubsequentDiscount => true;

		public override bool CanApplyTo(Tower tower, ref string helperMessage)
		{
			if (!ModSettingBool.op_Implicit(BuffsInShopMod.BypassTowerRestrictions) && !tower.towerModel.CheckSet((TowerSet)4, false))
			{
				helperMessage = "Must be a Magic monkey.";
				return false;
			}
			return base.CanApplyTo(tower, ref helperMessage);
		}

		public override IEnumerable<BehaviorMutator> GetMutators(Tower? tower)
		{
			yield return (BehaviorMutator)(object)TowerModelBehaviorExt.GetBehaviors<RangeSupportModel>(OriginTowerModel).Last().CreateMutator();
			yield return (BehaviorMutator)(object)TowerModelBehaviorExt.GetBehaviors<PierceSupportModel>(OriginTowerModel).Last().CreateMutator();
		}
	}
	public class NaturesWrath : ModBuffInShop
	{
		public override string OriginTower => TowerType.ObynGreenfoot;

		public override int OriginTopPath => 19;

		public override bool Hero => true;

		public override string BaseDescription => "Gives a Druid increased pierce, range, income, attack speed, tornado size, and Camo Detection.";

		public override float BaseCost => 5000f;

		public override bool SubsequentDiscount => true;

		public override bool CanApplyTo(Tower tower, ref string helperMessage)
		{
			if (!ModSettingBool.op_Implicit(BuffsInShopMod.BypassTowerRestrictions) && ((EntityModel)tower.towerModel).baseId != TowerType.Druid)
			{
				helperMessage = "Must be a Druid.";
				return false;
			}
			return base.CanApplyTo(tower, ref helperMessage);
		}

		public override IEnumerable<BehaviorMutator> GetMutators(Tower? tower)
		{
			yield return (BehaviorMutator)(object)TowerModelBehaviorExt.GetBehavior<PierceSupportModel>(OriginTowerModel).CreateMutator();
			yield return (BehaviorMutator)(object)TowerModelBehaviorExt.GetBehavior<VisibilitySupportModel>(OriginTowerModel).CreateMutator();
			yield return (BehaviorMutator)(object)TowerModelBehaviorExt.GetBehavior<MonkeyCityIncomeSupportModel>(OriginTowerModel).CreateMutator();
		}
	}
	public class NavalTactics : ModBuffInShop
	{
		public override string OriginTower => TowerType.AdmiralBrickell;

		public override int OriginTopPath => 9;

		public override bool Hero => true;

		public override string BaseDescription => "Gives a water based monkey double attack speed, +1 Pierce, Normal damage type, and Camo detection.";

		public override bool SubsequentDiscount => true;

		public override float BaseCost => 25000f;

		public override AudioClipReference? PlacementSound => AbilityModelBehaviorExt.GetBehavior<CreateSoundOnAbilityModel>(TowerModelExt.GetAbility(OriginTowerModel)).sound.assetId;

		public override EffectModel PlacementEffect
		{
			get
			{
				EffectModel val = ModelExt.Duplicate<EffectModel>(((Model)TowerModelExt.GetAbility(OriginTowerModel)).GetDescendant<EffectModel>());
				val.lifespan = 2f;
				return val;
			}
		}

		public override bool IsValidOrigin(TowerModel current)
		{
			AbilityModel ability = TowerModelExt.GetAbility(current);
			return ((ability != null) ? ability.displayName : null) == ((NamedModContent)this).DisplayName;
		}

		public override bool CanApplyTo(Tower tower, ref string helperMessage)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Invalid comparison between Unknown and I4
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Invalid comparison between Unknown and I4
			bool flag = !ModSettingBool.op_Implicit(BuffsInShopMod.BypassTowerRestrictions);
			bool flag2 = flag;
			if (flag2)
			{
				AreaType type = tower.GetAreaTowerIsPlacedOn().areaModel.type;
				bool flag3 = (((int)type == 1 || (int)type == 6) ? true : false);
				flag2 = !flag3;
			}
			if (flag2)
			{
				helperMessage = "Must be a water based monkey.";
				return false;
			}
			return base.CanApplyTo(tower, ref helperMessage);
		}

		public override IEnumerable<BehaviorMutator> GetMutators(Tower? tower)
		{
			AbilityModel ability = TowerModelExt.GetAbility(OriginTowerModel);
			yield return (BehaviorMutator)(object)AbilityModelBehaviorExt.GetBehavior<ActivateRateSupportZoneModel>(ability).CreateMutator();
			yield return (BehaviorMutator)(object)AbilityModelBehaviorExt.GetBehavior<ActivatePierceSupportZoneModel>(ability).CreateMutator();
			yield return (BehaviorMutator)(object)AbilityModelBehaviorExt.GetBehavior<ActivateTowerDamageSupportZoneModel>(ability).CreateMutator();
			yield return (BehaviorMutator)(object)AbilityModelBehaviorExt.GetBehavior<ActivateVisibilitySupportZoneModel>(ability).CreateMutator();
		}
	}
	public class Overclock : ModBuffInShop
	{
		public override string OriginTower => TowerT