Decompiled source of UltimateCrosspathing v1.8.3

UltimateCrosspathing.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BTD_Mod_Helper;
using BTD_Mod_Helper.Api;
using BTD_Mod_Helper.Api.Components;
using BTD_Mod_Helper.Api.Data;
using BTD_Mod_Helper.Api.Helpers;
using BTD_Mod_Helper.Api.ModOptions;
using BTD_Mod_Helper.Api.Towers;
using BTD_Mod_Helper.Extensions;
using HarmonyLib;
using Il2Cpp;
using Il2CppAssets.Scripts.Models;
using Il2CppAssets.Scripts.Models.Audio;
using Il2CppAssets.Scripts.Models.Behaviors;
using Il2CppAssets.Scripts.Models.Bloons;
using Il2CppAssets.Scripts.Models.Bloons.Behaviors;
using Il2CppAssets.Scripts.Models.Condition;
using Il2CppAssets.Scripts.Models.Effects;
using Il2CppAssets.Scripts.Models.Entities;
using Il2CppAssets.Scripts.Models.GenericBehaviors;
using Il2CppAssets.Scripts.Models.Map;
using Il2CppAssets.Scripts.Models.SimulationBehaviors;
using Il2CppAssets.Scripts.Models.TowerSets;
using Il2CppAssets.Scripts.Models.Towers;
using Il2CppAssets.Scripts.Models.Towers.Behaviors;
using Il2CppAssets.Scripts.Models.Towers.Behaviors.Abilities;
using Il2CppAssets.Scripts.Models.Towers.Behaviors.Abilities.Behaviors;
using Il2CppAssets.Scripts.Models.Towers.Behaviors.Attack;
using Il2CppAssets.Scripts.Models.Towers.Behaviors.Attack.Behaviors;
using Il2CppAssets.Scripts.Models.Towers.Behaviors.Emissions;
using Il2CppAssets.Scripts.Models.Towers.Behaviors.Emissions.Behaviors;
using Il2CppAssets.Scripts.Models.Towers.Behaviors.PlacementBehaviors;
using Il2CppAssets.Scripts.Models.Towers.Filters;
using Il2CppAssets.Scripts.Models.Towers.Mods;
using Il2CppAssets.Scripts.Models.Towers.Mutators;
using Il2CppAssets.Scripts.Models.Towers.Mutators.Conditions;
using Il2CppAssets.Scripts.Models.Towers.Mutators.Conditions.Behaviors;
using Il2CppAssets.Scripts.Models.Towers.PlacementBehaviors;
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;
using Il2CppAssets.Scripts.Models.Towers.Weapons.Behaviors;
using Il2CppAssets.Scripts.Simulation.Objects;
using Il2CppAssets.Scripts.Simulation.SMath;
using Il2CppAssets.Scripts.Simulation.Towers.Behaviors;
using Il2CppAssets.Scripts.Simulation.Towers.Behaviors.Attack;
using Il2CppAssets.Scripts.Simulation.Towers.Behaviors.Attack.Behaviors;
using Il2CppAssets.Scripts.Simulation.Towers.Projectiles.Behaviors;
using Il2CppAssets.Scripts.Unity;
using Il2CppAssets.Scripts.Unity.UI_New.InGame.TowerSelectionMenu;
using Il2CppAssets.Scripts.Unity.UI_New.Popups;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppNinjaKiwi.Common;
using Il2CppNinjaKiwi.Common.ResourceUtils;
using Il2CppSystem;
using Il2CppSystem.Collections;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Reflection;
using Il2CppSystem.Runtime.Serialization;
using MelonLoader;
using Microsoft.CodeAnalysis;
using UltimateCrosspathing;
using UltimateCrosspathing.Loaders;
using UltimateCrosspathing.Merging;
using UltimateCrosspathing.PostMergeFixes;
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(UltimateCrosspathingMod), "Ultimate Crosspathing", "1.8.3", "doombubbles", null)]
[assembly: MelonGame("Ninja Kiwi", "BloonsTD6")]
[assembly: MelonGame("Ninja Kiwi", "BloonsTD6-Epic")]
[assembly: MelonPriority(-500)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("UltimateCrosspathing")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+2e2712043c3f2bf27331dd0b63bfe15e7b1385a0")]
[assembly: AssemblyProduct("UltimateCrosspathing")]
[assembly: AssemblyTitle("UltimateCrosspathing")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace UltimateCrosspathing
{
	public abstract class LoadInfo : ModContent
	{
		private static readonly Dictionary<string, LoadInfo> Cache = new Dictionary<string, LoadInfo>();

		private ModSettingBool enabled = null;

		public bool? loaded = null;

		public virtual ModByteLoader<TowerModel> Loader { get; }

		public bool Enabled
		{
			get
			{
				return ModSettingBool.op_Implicit(enabled);
			}
			set
			{
				((ModSetting)enabled).SetValue((object)value);
			}
		}

		public virtual bool PowerPro => false;

		public virtual int TopPath => PowerPro ? 3 : 5;

		public virtual int MidPath => PowerPro ? 3 : 5;

		public virtual int BotPath => PowerPro ? 3 : 5;

		protected override int Order
		{
			get
			{
				int num = ((Il2CppArrayBase<string>)(object)TowerType.towers).IndexOf(((ModContent)this).Name);
				return (num >= 0) ? num : 99;
			}
		}

		public override IEnumerable<ModContent> Load()
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			enabled = new ModSettingBool(true)
			{
				button = true,
				category = Settings.IndividualTowers,
				displayName = "[" + ((ModContent)this).Name + "]",
				requiresRestart = true
			};
			base.mod.ModSettings[((ModContent)this).Name + "Enabled"] = (ModSetting)(object)enabled;
			return ((ModContent)this).Load();
		}

		public sealed override void Register()
		{
			Cache[((ModContent)this).Name] = this;
			((ModSetting)enabled).icon = Game.instance.model.GetTowerWithName(((ModContent)this).Name).icon.AssetGUID;
		}

		public static bool TryFind(string baseId, out LoadInfo loadInfo)
		{
			return Cache.TryGetValue(baseId, out loadInfo);
		}

		public static bool ShouldWork(string baseId)
		{
			LoadInfo loadInfo;
			return (!TryFind(baseId, out loadInfo)) ? (ModContent.Find<ModTower>(baseId) != null) : (loadInfo.Enabled && loadInfo.loaded != false);
		}
	}
	public class Alchemist : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<AlchemistLoader>();
	}
	public class BananaFarm : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<BananaFarmLoader>();
	}
	public class BeastHandler : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<BeastHandlerLoader>();
	}
	public class BombShooter : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<BombShooterLoader>();
	}
	public class BoomerangMonkey : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<BoomerangMonkeyLoader>();
	}
	public class DartlingGunner : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<DartlingGunnerLoader>();
	}
	public class DartMonkey : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<DartMonkeyLoader>();
	}
	public class Druid : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<DruidLoader>();
	}
	public class EngineerMonkey : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<EngineerMonkeyLoader>();
	}
	public class GlueGunner : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<GlueGunnerLoader>();
	}
	public class Desperado : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<DesperadoLoader>();
	}
	public class HeliPilot : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<HeliPilotLoader>();
	}
	public class IceMonkey : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<IceMonkeyLoader>();
	}
	public class MonkeyAce : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<MonkeyAceLoader>();
	}
	public class MonkeyBuccaneer : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<MonkeyBuccaneerLoader>();
	}
	public class MonkeySub : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<MonkeySubLoader>();
	}
	public class MonkeyVillage : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<MonkeyVillageLoader>();
	}
	public class MortarMonkey : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<MortarMonkeyLoader>();
	}
	public class NinjaMonkey : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<NinjaMonkeyLoader>();
	}
	public class SniperMonkey : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<SniperMonkeyLoader>();
	}
	public class SpikeFactory : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<SpikeFactoryLoader>();
	}
	public class SuperMonkey : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<SuperMonkeyLoader>();
	}
	public class TackShooter : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<TackShooterLoader>();
	}
	public class WizardMonkey : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<WizardMonkeyLoader>();
	}
	public class Mermonkey : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<MermonkeyLoader>();
	}
	public class Skywarden : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<SkywardenLoader>();
	}
	public class PortableLakePro : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<PortableLakeProLoader>();

		public override bool PowerPro => true;
	}
	public class BananaFarmerPro : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<BananaFarmerProLoader>();

		public override bool PowerPro => true;
	}
	public class SuperMonkeyBeacon : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<SuperMonkeyBeaconLoader>();

		public override bool PowerPro => true;
	}
	public class TechBotPrime : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<TechBotPrimeLoader>();

		public override bool PowerPro => true;
	}
	public class MonkeyBoostPro : LoadInfo
	{
		public override ModByteLoader<TowerModel> Loader => ModContent.GetInstance<MonkeyBoostProLoader>();

		public override bool PowerPro => true;
	}
	public static class ModHelperData
	{
		public const string WorksOnVersion = "56.0";

		public const string Version = "1.8.3";

		public const string Name = "Ultimate Crosspathing";

		public const string Description = "Instead of your Towers being restricted to 5 Upgrades in one path and 2 in another, you can take your upgrades in any path, optionally up to all 15! Note for Mod Browser: This mod's dll is beefy, so if your internet isn't super fast you may need to go into your Mod Helper Settings and increase the 'Request Timeout' duration under Mod Browser Settings.";

		public const string RepoOwner = "doombubbles";

		public const string PrevRepoName = "ultimate-crosspathing";

		public const string RepoName = "UltimateCrosspathing";
	}
	[HarmonyPatch(typeof(UpgradeObject), "CheckBlockedPath")]
	internal class UpgradeObject_CheckBlockedPath
	{
		[HarmonyPostfix]
		internal static void Postfix(UpgradeObject __instance, ref int __result, ref bool __runOriginal)
		{
			if (__instance.tts != null && LoadInfo.ShouldWork(((EntityModel)__instance.tts.Def).baseId) && __runOriginal)
			{
				int tier = __instance.tier;
				Il2CppStructArray<int> tiers = __instance.tts.Def.tiers;
				int num = ((IEnumerable<int>)tiers).Sum();
				int num2 = ModSettingInt.op_Implicit(Settings.MaxTiers) - num;
				__result = tier + num2;
				if (__result > 5)
				{
					__result = 5;
				}
			}
		}
	}
	[HarmonyPatch(typeof(PowerProUpgradeObject), "CheckBlockedPath")]
	internal static class PowerProUpgradeObject_CheckBlockedPath
	{
		[HarmonyPostfix]
		internal static void Postfix(PowerProUpgradeObject __instance, ref int __result, ref bool __runOriginal)
		{
			if (((UpgradeObject)__instance).tts != null && LoadInfo.ShouldWork(((EntityModel)((UpgradeObject)__instance).tts.Def).baseId) && __runOriginal)
			{
				int tier = ((UpgradeObject)__instance).tier;
				Il2CppStructArray<int> tiers = ((UpgradeObject)__instance).tts.Def.tiers;
				int num = ((IEnumerable<int>)tiers).Sum();
				int num2 = ModSettingInt.op_Implicit(Settings.MaxTiersPowersPro) - num;
				__result = tier + num2;
				if (__result > 3)
				{
					__result = 3;
				}
			}
		}
	}
	[HarmonyPatch(typeof(TowerSelectionMenu), "IsUpgradePathClosed")]
	internal class TowerSelectionMenu_IsUpgradePathClosed
	{
		[HarmonyPostfix]
		internal static void Postfix(TowerSelectionMenu __instance, int path, ref bool __result, ref bool __runOriginal)
		{
			if (__instance.selectedTower != null && __runOriginal)
			{
				TowerModel def = __instance.selectedTower.Def;
				bool flag = ((EntityModel)def).baseId == TowerType.BeastHandler && ((IEnumerable<int>)def.tiers).Count((int t) => t > 0) >= 2 && ((Il2CppArrayBase<int>)(object)def.tiers)[path] == 0;
				if (LoadInfo.ShouldWork(((EntityModel)def).baseId) && !flag)
				{
					__result &= ((IEnumerable<int>)def.tiers).Sum() >= ModSettingInt.op_Implicit(__instance.powerProDetails.activeSelf ? Settings.MaxTiersPowersPro : Settings.MaxTiers);
				}
			}
		}
	}
	[HarmonyPatch(typeof(PowerProUpgradeObject), "CheckLocked")]
	internal static class PowerProUpgradeObject_CheckLocked
	{
		[HarmonyPostfix]
		internal static void Postfix(PowerProUpgradeObject __instance, ref bool __runOriginal)
		{
			if (((UpgradeObject)__instance).tts != null && __runOriginal)
			{
				TowerModel def = ((UpgradeObject)__instance).tts.Def;
				if (LoadInfo.ShouldWork(((EntityModel)def).baseId))
				{
					bool activeSelf = ((UpgradeObject)__instance).locked.activeSelf;
					activeSelf &= ((IEnumerable<int>)def.tiers).Sum() >= ModSettingInt.op_Implicit(Settings.MaxTiersPowersPro);
					((UpgradeObject)__instance).locked.SetActive(activeSelf);
				}
			}
		}
	}
	[HarmonyPatch(typeof(UpgradeObject), "LoadUpgrades")]
	internal static class UpgradeObject_LoadUpgrades
	{
		[HarmonyPostfix]
		internal static void Postfix(UpgradeObject __instance)
		{
			__instance.UpdateVisuals(__instance.path, false);
		}
	}
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	internal class Bank_Cash
	{
		[HarmonyPostfix]
		internal static void Postfix(Bank __instance)
		{
			if (__instance.bankModel.autoCollect && __instance.Cash >= __instance.bankModel.capacity)
			{
				__instance.Collect();
			}
		}
	}
	[HarmonyPatch(typeof(Attack), "UpdateActiveTargetSupplier")]
	internal static class Attack_UpdateActiveTargetSupplier
	{
		[HarmonyPrefix]
		internal static void Prefix(Attack __instance)
		{
			TargetSupplier activeTargetSupplier = __instance.activeTargetSupplier;
			if (activeTargetSupplier != null && ((RootObject)activeTargetSupplier).IsDestroyed)
			{
				__instance.activeTargetSupplier = null;
			}
		}
	}
	public class Settings : ModSettings
	{
		public const int MaxTiersMin = 7;

		public const int MaxTiersMax = 15;

		public static readonly ModSettingInt MaxTiers;

		public static readonly ModSettingInt MaxTiersPowersPro;

		public static readonly ModSettingCategory IndividualTowers;

		protected override int Order => 1;

		static Settings()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Expected O, but got Unknown
			ModSettingInt val = new ModSettingInt(15);
			((ModSettingNumber<long>)val).min = 7L;
			((ModSettingNumber<long>)val).max = 15L;
			((ModSettingNumber<long>)val).slider = true;
			((ModSetting)val).description = "Controls the maximum number of upgrades that any one tower can have at once. Having this all the way to 15 will enable the complete Ultimate Crosspathing experience!";
			MaxTiers = val;
			ModSettingInt val2 = new ModSettingInt(9);
			((ModSettingNumber<long>)val2).min = 3L;
			((ModSettingNumber<long>)val2).max = 9L;
			((ModSettingNumber<long>)val2).slider = true;
			((ModSetting)val2).description = "Controls the maximum number of upgrades that any one por power can have at once. Having this all the way to 9 will enable the complete Ultimate Crosspathing experience!";
			MaxTiersPowersPro = val2;
			IndividualTowers = new ModSettingCategory("Individual Towers")
			{
				modifyCategory = delegate(ModHelperCategory category)
				{
					//IL_0025: Unknown result type (might be due to invalid IL or missing references)
					//IL_002a: Unknown result type (might be due to invalid IL or missing references)
					//IL_0072: Unknown result type (might be due to invalid IL or missing references)
					//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
					//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
					//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
					ModHelperButton val3 = ((ModHelperComponent)category).AddButton(new Info("Enable All", 1000f, -100f, 562f, 200f, new Vector2(0.5f, 1f)), "Ui[GreenBtnLong]", Action.op_Implicit((Action)delegate
					{
						foreach (LoadInfo item in ModContent.GetContent<LoadInfo>())
						{
							item.Enabled = true;
						}
					}));
					((ModHelperComponent)val3).LayoutElement.ignoreLayout = true;
					((ModHelperComponent)val3).AddText(new Info("Text", (InfoPreset)0), "Enable All", 80f);
					ModHelperButton val4 = ((ModHelperComponent)category).AddButton(new Info("Disable All", -1000f, -100f, 562f, 200f, new Vector2(0.5f, 1f)), "Ui[RedBtnLong]", Action.op_Implicit((Action)delegate
					{
						foreach (LoadInfo item2 in ModContent.GetContent<LoadInfo>())
						{
							item2.Enabled = false;
						}
					}));
					((ModHelperComponent)val4).LayoutElement.ignoreLayout = true;
					((ModHelperComponent)val4).AddText(new Info("Text", (InfoPreset)0), "Disable All", 80f);
				}
			};
		}
	}
	public static class Towers
	{
		public static readonly Dictionary<string, (int, int, int)> PathPriorities = new Dictionary<string, (int, int, int)>
		{
			{
				TowerType.DartMonkey,
				(0, 2, 1)
			},
			{
				TowerType.TackShooter,
				(0, 1, 2)
			},
			{
				TowerType.BoomerangMonkey,
				(1, 2, 0)
			},
			{
				TowerType.BombShooter,
				(2, 1, 0)
			},
			{
				TowerType.MonkeyBuccaneer,
				(0, 1, 2)
			},
			{
				TowerType.NinjaMonkey,
				(0, 2, 1)
			},
			{
				TowerType.SniperMonkey,
				(1, 2, 0)
			},
			{
				TowerType.DartlingGunner,
				(2, 0, 1)
			},
			{
				TowerType.IceMonkey,
				(2, 0, 1)
			},
			{
				TowerType.SuperMonkey,
				(0, 1, 2)
			},
			{
				TowerType.GlueGunner,
				(2, 0, 1)
			},
			{
				TowerType.WizardMonkey,
				(0, 2, 1)
			},
			{
				TowerType.BananaFarm,
				(1, 2, 0)
			},
			{
				TowerType.SpikeFactory,
				(2, 1, 0)
			},
			{
				TowerType.Mermonkey,
				(1, 2, 0)
			},
			{
				TowerType.Skywarden,
				(0, 1, 2)
			},
			{
				TowerType.BananaFarmerPro,
				(0, 1, 2)
			},
			{
				TowerType.SuperMonkeyBeacon,
				(1, 2, 0)
			},
			{
				"MonkeyBoostPro",
				(0, 1, 2)
			},
			{
				TowerType.TechBotPrime,
				(2, 0, 1)
			},
			{
				TowerType.PortableLakePro,
				(0, 1, 2)
			}
		};

		private static bool GetTiersForMerging(LoadInfo loadInfo, int top, int mid, int bot, out int[] leftTiers, out int[] rightTiers)
		{
			string name = ((ModContent)loadInfo).Name;
			int num;
			int num2;
			int num3;
			if (PathPriorities.TryGetValue(name, out var value))
			{
				(num, num2, num3) = value;
			}
			else
			{
				(num, num2, num3) = PathPriorities[TowerType.DartMonkey];
			}
			int[] array = new int[3] { top, mid, bot };
			leftTiers = new int[3] { top, mid, bot };
			rightTiers = new int[3] { top, mid, bot };
			int[] orderedTiers = array.OrderByDescending((int result) => result).ToArray();
			if (loadInfo.PowerPro)
			{
				int num4 = array.ToList().IndexOf(0);
				if (num4 >= 0)
				{
					if (num4 == num)
					{
						leftTiers[num3] = 0;
						rightTiers[num2] = 0;
					}
					else if (num4 == num2)
					{
						leftTiers[num3] = 0;
						rightTiers[num] = 0;
					}
					else if (num4 == num3)
					{
						leftTiers[num2] = 0;
						rightTiers[num] = 0;
					}
					return true;
				}
			}
			if (array.All((int i) => i == orderedTiers[0]))
			{
				leftTiers[num3] = 0;
				rightTiers[num2] = 0;
			}
			else if (orderedTiers[0] == orderedTiers[1] && orderedTiers[0] >= 3)
			{
				if (array[num3] == orderedTiers[2])
				{
					leftTiers[num2] = Math.Min(2, leftTiers[num2]);
					rightTiers[num] = Math.Min(2, rightTiers[num]);
				}
				else if (array[num2] == orderedTiers[2])
				{
					leftTiers[num3] = Math.Min(2, leftTiers[num3]);
					rightTiers[num] = Math.Min(2, rightTiers[num]);
				}
				else if (array[num] == orderedTiers[2])
				{
					leftTiers[num3] = Math.Min(2, leftTiers[num3]);
					rightTiers[num2] = Math.Min(2, rightTiers[num2]);
				}
			}
			else if (array.Count((int t) => t > 0) == 3)
			{
				if (orderedTiers[1] == orderedTiers[2])
				{
					if (orderedTiers[0] == array[num])
					{
						leftTiers[num3] = 0;
						rightTiers[num2] = 0;
					}
					else if (orderedTiers[0] == array[num2])
					{
						leftTiers[num3] = 0;
						rightTiers[num] = 0;
					}
					else if (orderedTiers[0] == array[num3])
					{
						leftTiers[num2] = 0;
						rightTiers[num] = 0;
					}
				}
				else
				{
					for (int num5 = 0; num5 < 3; num5++)
					{
						if (array[num5] == orderedTiers[2])
						{
							leftTiers[num5] = 0;
							break;
						}
					}
					for (int num6 = 2; num6 >= 0; num6--)
					{
						if (array[num6] == orderedTiers[1])
						{
							rightTiers[num6] = 0;
							break;
						}
					}
				}
			}
			else
			{
				for (int num7 = 0; num7 < 3; num7++)
				{
					if (array[num7] == orderedTiers[1])
					{
						leftTiers[num7] = Math.Min(2, leftTiers[num7]);
						break;
					}
				}
				for (int num8 = 2; num8 >= 0; num8--)
				{
					if (array[num8] == orderedTiers[0])
					{
						rightTiers[num8] = Math.Min(2, rightTiers[num8]);
						break;
					}
				}
			}
			return true;
		}

		public static IEnumerable<MergeInfo> GetMergeInfo(LoadInfo loadInfo)
		{
			string baseId = ((ModContent)loadInfo).Name;
			Dictionary<string, TowerModel> towers = Il2CppGenericIEnumerable.AsIEnumerable<TowerModel>(Game.instance.model.GetTowersWithBaseId(baseId, false)).DistinctBy((TowerModel model) => ((Model)model).name).ToDictionary((TowerModel model) => ((Model)model).name);
			towers[baseId + "-000"] = towers[baseId];
			for (int top = 0; top <= loadInfo.TopPath; top++)
			{
				for (int mid = 0; mid <= loadInfo.MidPath; mid++)
				{
					for (int bot = 0; bot <= loadInfo.BotPath; bot++)
					{
						string newTowerName = $"{baseId}-{top}{mid}{bot}";
						int num = top + mid + bot;
						bool flag = ((num <= 0 || num > 15) ? true : false);
						if (!flag && !towers.ContainsKey(newTowerName) && GetTiersForMerging(loadInfo, top, mid, bot, out var leftTiers, out var rightTiers))
						{
							int[] commonAncestorTiers = new int[3]
							{
								Math.Min(leftTiers[0], rightTiers[0]),
								Math.Min(leftTiers[1], rightTiers[1]),
								Math.Min(leftTiers[2], rightTiers[2])
							};
							string leftName = baseId + "-" + ArrayExt.Printed(leftTiers);
							string rightName = baseId + "-" + ArrayExt.Printed(rightTiers);
							string commonAncestorName = baseId + "-" + ArrayExt.Printed(commonAncestorTiers);
							if (towers.TryGetValue(leftName, out var leftTowerModel) && towers.TryGetValue(rightName, out var rightTowerModel) && towers.TryGetValue(commonAncestorName, out var commonAncestor))
							{
								TowerModel result = ModelExt.Duplicate<TowerModel>(leftTowerModel);
								TowerModel left = ModelExt.Duplicate<TowerModel>(leftTowerModel);
								TowerModel right = ModelExt.Duplicate<TowerModel>(rightTowerModel);
								ModHelper.Msg<UltimateCrosspathingMod>((object)$"Creating {newTowerName} from {leftName} and {rightName}");
								yield return new MergeInfo(result, left, right, commonAncestor);
								leftTiers = null;
								rightTiers = null;
								leftTowerModel = null;
								rightTowerModel = null;
								commonAncestor = null;
							}
						}
					}
				}
			}
		}

		public static TowerModel NewMerge(MergeInfo mergeInfo)
		{
			MergeInfo mergeInfo2 = mergeInfo;
			mergeInfo2.Deconstruct(out var result, out var left, out var right, out var commonAncestor);
			TowerModel val = result;
			TowerModel val2 = left;
			TowerModel val3 = right;
			TowerModel ancestor = commonAncestor;
			for (int i = 0; i < 3; i++)
			{
				((Il2CppArrayBase<int>)(object)val.tiers)[i] = Math.Max(((Il2CppArrayBase<int>)(object)val2.tiers)[i], ((Il2CppArrayBase<int>)(object)val3.tiers)[i]);
			}
			val.tier = Math.Max(val2.tier, val3.tier);
			((Model)val).name = $"{((EntityModel)val).baseId}-{((Il2CppArrayBase<int>)(object)val.tiers)[0]}{((Il2CppArrayBase<int>)(object)val.tiers)[1]}{((Il2CppArrayBase<int>)(object)val.tiers)[2]}";
			MergeUpgrades(val, val2, val3);
			FieldInfo field = Il2CppType.Of<TowerModel>().GetField("range");
			DeepMerging.MergeField((MemberInfo)(object)field, (Object)(object)val, (Object)(object)val3, (Object)(object)ancestor);
			FieldInfo field2 = Il2CppType.Of<TowerModel>().GetField("mods");
			DeepMerging.MergeField((MemberInfo)(object)field2, (Object)(object)val, (Object)(object)val3, (Object)(object)ancestor);
			FieldInfo field3 = Il2CppType.Of<TowerModel>().GetField("behaviors");
			DeepMerging.MergeField((MemberInfo)(object)field3, (Object)(object)val, (Object)(object)val3, (Object)(object)ancestor);
			return val;
		}

		private static void MergeUpgrades(TowerModel towerModel, TowerModel first, TowerModel second)
		{
			foreach (string item in (Il2CppArrayBase<string>)(object)second.appliedUpgrades)
			{
				if (!((Il2CppArrayBase<string>)(object)towerModel.appliedUpgrades).Contains(item))
				{
					towerModel.appliedUpgrades = Il2CppStringArray.op_Implicit(CollectionExtensions.AddItem<string>((IEnumerable<string>)towerModel.appliedUpgrades, item).ToArray());
				}
			}
			Dictionary<string, UpgradePathModel> dictionary = new Dictionary<string, UpgradePathModel>();
			foreach (UpgradePathModel item2 in ((IEnumerable<UpgradePathModel>)first.upgrades).Concat((IEnumerable<UpgradePathModel>)second.upgrades))
			{
				if (!((Il2CppArrayBase<string>)(object)towerModel.appliedUpgrades).Contains(item2.upgrade))
				{
					dictionary[item2.upgrade] = ((Il2CppObjectBase)((Object)item2).MemberwiseClone()).Cast<UpgradePathModel>();
				}
			}
			foreach (UpgradePathModel value in dictionary.Values)
			{
				string text = value.tower.Split('-')[1];
				int[] array = new int[3]
				{
					Math.Max(int.Parse(text[0].ToString()), ((Il2CppArrayBase<int>)(object)towerModel.tiers)[0]),
					Math.Max(int.Parse(text[1].ToString()), ((Il2CppArrayBase<int>)(object)towerModel.tiers)[1]),
					Math.Max(int.Parse(text[2].ToString()), ((Il2CppArrayBase<int>)(object)towerModel.tiers)[2])
				};
				value.tower = ((array.Sum() <= 15) ? $"{((EntityModel)towerModel).baseId}-{array[0]}{array[1]}{array[2]}" : null);
			}
			towerModel.upgrades = IEnumerableExt.ToIl2CppReferenceArray<UpgradePathModel>(dictionary.Values.Where((UpgradePathModel u) => u.tower != null));
		}

		public static void AddUpgradeToPrevs(TowerModel towerModel)
		{
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Expected O, but got Unknown
			for (int i = 0; i < 3; i++)
			{
				int num = ((Il2CppArrayBase<int>)(object)towerModel.tiers)[i];
				if (num <= 0)
				{
					continue;
				}
				int[] array = ((IEnumerable<int>)towerModel.tiers).ToArray();
				array[i]--;
				string text = ((EntityModel)towerModel).baseId + "-" + ArrayExt.Printed(array);
				TowerModel prevTowerModel = Game.instance.model.GetTowerWithName(text);
				if (prevTowerModel != null)
				{
					string upgradeNeeded = ((IEnumerable<string>)towerModel.appliedUpgrades).FirstOrDefault((string upgrade) => !((Il2CppArrayBase<string>)(object)prevTowerModel.appliedUpgrades).Contains(upgrade));
					if (upgradeNeeded != null && ((IEnumerable<UpgradePathModel>)prevTowerModel.upgrades).All((UpgradePathModel upm) => upm.upgrade != upgradeNeeded))
					{
						UpgradePathModel val = new UpgradePathModel(upgradeNeeded, ((Model)towerModel).name);
						prevTowerModel.upgrades = Il2CppReferenceArrayExt.AddTo<UpgradePathModel>(prevTowerModel.upgrades, val);
					}
				}
			}
		}

		public static void PostMerge(TowerModel model)
		{
			foreach (PostMergeFix item in ModContent.GetContent<PostMergeFix>())
			{
				item.Apply(model);
			}
		}
	}
	public class UltimateCrosspathingMod : BloonsTD6Mod
	{
		private const string HelpUrl = "https://github.com/doombubbles/ultimate-crosspathing/blob/main/HELP.md";

		public override void OnMainMenu()
		{
			int failedTowers = ModContent.GetContent<LoadInfo>().Count((LoadInfo info) => info.loaded != true && info.Enabled);
			if (failedTowers <= 0)
			{
				return;
			}
			TaskScheduler.ScheduleTask((Action)delegate
			{
				PopupScreen.instance.ShowPopup((Placement)2, "Crosspathing Issue", $"{failedTowers} tower(s) failed to Ultimately Crosspath. " + "An update to the mod, Mod Helper, or MelonLoader may be required. Press 'Help' to be taken to the common issues page.", ReturnCallback.op_Implicit((Action)delegate
				{
					ProcessHelper.OpenURL("https://github.com/doombubbles/ultimate-crosspathing/blob/main/HELP.md");
				}), "Help", (ReturnCallback)null, "Cancel", (TransitionAnim)1, (BackGround)1, false, false);
			}, (Func<bool>)(() => (Object)(object)PopupScreen.instance != (Object)null && !PopupScreen.instance.IsPopupActive()));
		}
	}
}
namespace UltimateCrosspathing.Tasks
{
	public class Loading : ModLoadTask
	{
		public override string DisplayName => "Ultimately Crosspathing...";

		public override bool ShowProgressBar => true;

		public override IEnumerator Coroutine()
		{
			List<LoadInfo> loadInfos = (from info in ModContent.GetContent<LoadInfo>()
				where info.Enabled
				select info).ToList();
			Dictionary<LoadInfo, List<TowerModel>> validInfosTowers = new Dictionary<LoadInfo, List<TowerModel>>();
			foreach (LoadInfo loadInfo in loadInfos)
			{
				try
				{
					List<TowerModel> towers = (from model in (IEnumerable<Model>)((EntityModel)loadInfo.Loader.LoadResult()).behaviors
						where model != null
						select ((Il2CppObjectBase)model).TryCast<TowerModel>()).ToList();
					validInfosTowers[loadInfo] = towers;
				}
				catch (Exception ex)
				{
					ModHelper.Warning<UltimateCrosspathingMod>((object)ex);
					ModHelper.Warning<UltimateCrosspathingMod>((object)("Failed loading " + ((ModContent)loadInfo).Name + "s :("));
					loadInfo.loaded = false;
				}
				yield return null;
			}
			int i = 0;
			foreach (var (loadInfo3, towers2) in validInfosTowers)
			{
				((ModLoadTask)this).Progress = (float)i++ / (float)validInfosTowers.Count;
				try
				{
					foreach (TowerModel towerModel in towers2)
					{
						Towers.PostMerge(towerModel);
					}
				}
				catch (Exception ex2)
				{
					ModHelper.Warning<UltimateCrosspathingMod>((object)ex2);
					ModHelper.Warning<UltimateCrosspathingMod>((object)("Failed loading " + ((ModContent)loadInfo3).Name + "s :("));
					loadInfo3.loaded = false;
					continue;
				}
				yield return null;
				GameModelExt.AddTowersToGame(Game.instance.model, (IEnumerable<TowerModel>)towers2);
				yield return null;
				try
				{
					foreach (TowerModel towerModel2 in towers2)
					{
						Towers.AddUpgradeToPrevs(towerModel2);
					}
				}
				catch (Exception ex3)
				{
					ModHelper.Warning<UltimateCrosspathingMod>((object)ex3);
					ModHelper.Warning<UltimateCrosspathingMod>((object)("Failed loading " + ((ModContent)loadInfo3).Name + "s :("));
					loadInfo3.loaded = false;
					continue;
				}
				yield return null;
				loadInfo3.loaded = true;
				ModHelper.Msg<UltimateCrosspathingMod>((object)("Finished loading " + ((ModContent)loadInfo3).Name + "s!"));
				((ModLoadTask)this).Description = StringExt.Spaced(((ModContent)loadInfo3).Name) + "s";
				loadInfo3.Loader.Dispose();
			}
			((ModLoadTask)this).Description = "Done!";
		}
	}
}
namespace UltimateCrosspathing.PostMergeFixes
{
	public class FixAbilities : PostMergeFix
	{
		public override void Apply(TowerModel model)
		{
			foreach (AbilityModel item in TowerModelExt.GetAbilities(model).Where(delegate(AbilityModel abilityModel)
			{
				string displayName = abilityModel.displayName;
				return (displayName == "Supply Drop" || displayName == "Bomb Blitz") ? true : false;
			}))
			{
				ActivateAttackModel descendant = ((Model)item).GetDescendant<ActivateAttackModel>();
				if (descendant != null)
				{
					descendant.isOneShot = true;
				}
			}
			if (((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("Elite Sniper"))
			{
				TowerModelBehaviorExt.RemoveBehavior<TargetSupplierSupportModel>(model);
			}
		}
	}
	public class FixAdvancedIntel : PostMergeFix
	{
		public override void Apply(TowerModel model)
		{
			if (((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("Advanced Intel"))
			{
				Il2CppGenericIEnumerable.ForEach<TargetFirstSharedRangeModel>(((Model)model).GetDescendants<TargetFirstSharedRangeModel>(), (Action<TargetFirstSharedRangeModel>)delegate(TargetFirstSharedRangeModel m)
				{
					m.isSharedRangeEnabled = true;
				});
				Il2CppGenericIEnumerable.ForEach<TargetLastSharedRangeModel>(((Model)model).GetDescendants<TargetLastSharedRangeModel>(), (Action<TargetLastSharedRangeModel>)delegate(TargetLastSharedRangeModel m)
				{
					m.isSharedRangeEnabled = true;
				});
				Il2CppGenericIEnumerable.ForEach<TargetCloseSharedRangeModel>(((Model)model).GetDescendants<TargetCloseSharedRangeModel>(), (Action<TargetCloseSharedRangeModel>)delegate(TargetCloseSharedRangeModel m)
				{
					m.isSharedRangeEnabled = true;
				});
				Il2CppGenericIEnumerable.ForEach<TargetStrongSharedRangeModel>(((Model)model).GetDescendants<TargetStrongSharedRangeModel>(), (Action<TargetStrongSharedRangeModel>)delegate(TargetStrongSharedRangeModel m)
				{
					m.isSharedRangeEnabled = true;
				});
			}
		}
	}
	public class FixAircraftCarriers : PostMergeFix
	{
		public override void Apply(TowerModel model)
		{
			if (!((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("Buccaneer-Aircraft Carrier"))
			{
				return;
			}
			if (((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("Buccaneer-Monkey Pirates"))
			{
				AttackModelBehaviorExt.RemoveBehavior<RotateToTargetModel>(((Model)TowerModelExt.GetAbility(model)).GetDescendant<AttackModel>());
			}
			Il2CppGenericIEnumerable.ForEach<WeaponModel>(((Model)model).GetDescendants<WeaponModel>(), (Action<WeaponModel>)delegate(WeaponModel weaponModel)
			{
				CreateTowerModel descendant = ((Model)weaponModel).GetDescendant<CreateTowerModel>();
				SubTowerFilterModel descendant2 = ((Model)weaponModel).GetDescendant<SubTowerFilterModel>();
				if (descendant != null && descendant2 != null)
				{
					descendant2.baseSubTowerId = ((EntityModel)descendant.tower).baseId;
					descendant2.baseSubTowerIds = Il2CppStringArray.op_Implicit(new string[1] { descendant2.baseSubTowerId });
				}
			});
			TowerModelExt.GetAttackModels(model).ForEach(delegate(AttackModel attackModel)
			{
				//IL_0079: Unknown result type (might be due to invalid IL or missing references)
				//IL_007f: Unknown result type (might be due to invalid IL or missing references)
				//IL_008c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0096: Expected O, but got Unknown
				Il2CppGenericIEnumerable.ForEach<RotateToTargetModel>(((Model)attackModel).GetDescendants<RotateToTargetModel>(), (Action<RotateToTargetModel>)delegate(RotateToTargetModel targetModel)
				{
					targetModel.rotateTower = false;
				});
				Il2CppGenericIEnumerable.ForEach<EmissionModel>(((Model)attackModel).GetDescendants<EmissionModel>(), (Action<EmissionModel>)delegate(EmissionModel emissionModel)
				{
					//IL_0078: Unknown result type (might be due to invalid IL or missing references)
					//IL_007f: Expected O, but got Unknown
					//IL_010a: Unknown result type (might be due to invalid IL or missing references)
					//IL_0111: Expected O, but got Unknown
					if (emissionModel.behaviors != null)
					{
						List<EmissionBehaviorModel> list = Il2CppReferenceArrayExt.ToList<EmissionBehaviorModel>(emissionModel.behaviors);
						foreach (EmissionRotationOffTowerDirectionModel emission in Il2CppReferenceArrayExt.GetItemsOfType<EmissionBehaviorModel, EmissionRotationOffTowerDirectionModel>(emissionModel.behaviors))
						{
							list.RemoveAll((EmissionBehaviorModel behaviorModel) => ((Model)behaviorModel).name == ((Model)emission).name);
							((Model)emissionModel).RemoveChildDependant<EmissionRotationOffTowerDirectionModel>(emission);
							EmissionRotationOffDisplayModel val = new EmissionRotationOffDisplayModel("EmissionRotationOffDisplayModel_", emission.offsetRotation);
							list.Add((EmissionBehaviorModel)(object)val);
							((Model)emissionModel).AddChildDependant<EmissionRotationOffDisplayModel>(val);
						}
						foreach (EmissionArcRotationOffTowerDirectionModel emission2 in Il2CppReferenceArrayExt.GetItemsOfType<EmissionBehaviorModel, EmissionArcRotationOffTowerDirectionModel>(emissionModel.behaviors))
						{
							list.RemoveAll((EmissionBehaviorModel behaviorModel) => ((Model)behaviorModel).name == ((Model)emission2).name);
							((Model)emissionModel).RemoveChildDependant<EmissionArcRotationOffTowerDirectionModel>(emission2);
							EmissionArcRotationOffDisplayDirectionModel val2 = new EmissionArcRotationOffDisplayDirectionModel("EmissionArcRotationOffDisplayDirectionModel_", emission2.offsetRotation);
							list.Add((EmissionBehaviorModel)(object)val2);
							((Model)emissionModel).AddChildDependant<EmissionArcRotationOffDisplayDirectionModel>(val2);
						}
						emissionModel.behaviors = ListExt.ToIl2CppReferenceArray<EmissionBehaviorModel>(list);
					}
				});
				if (!AttackModelBehaviorExt.HasBehavior<DisplayModel>(attackModel))
				{
					AttackModelBehaviorExt.AddBehavior<DisplayModel>(attackModel, new DisplayModel("DisplayModel_AttackDisplay", ModContent.CreatePrefabReference(""), 0, (DisplayCategory)1, default(Vector3), 1f, false, 0f, false));
				}
			});
		}
	}
	public class FixAutoCollectings : PostMergeFix
	{
		public override void Apply(TowerModel model)
		{
			if (((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("Banana Salvage"))
			{
				Il2CppGenericIEnumerable.ForEach<BankModel>(((Model)model).GetDescendants<BankModel>(), (Action<BankModel>)delegate(BankModel bankModel)
				{
					bankModel.autoCollect = true;
				});
			}
		}
	}
	public class FixBananas : PostMergeFix
	{
		public override void Apply(TowerModel model)
		{
			if (((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("Marketplace") || ((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("Monkey Bank"))
			{
				ProjectileModelBehaviorExt.RemoveBehaviors<PickupModel>(TowerModelExt.GetWeapon(model).projectile);
				ProjectileModelBehaviorExt.RemoveBehaviors<ArriveAtTargetModel>(TowerModelExt.GetWeapon(model).projectile);
				ProjectileModelBehaviorExt.RemoveBehaviors<ScaleProjectileModel>(TowerModelExt.GetWeapon(model).projectile);
				AgeModel behavior = ProjectileModelBehaviorExt.GetBehavior<AgeModel>(TowerModelExt.GetWeapon(model).projectile);
				if (behavior != null)
				{
					behavior.Lifespan = 0f;
				}
				CreateTextEffectModel descendant = ((Model)model).GetDescendant<CreateTextEffectModel>();
				if (descendant != null)
				{
					descendant.useTowerPosition = true;
				}
			}
		}
	}
	public class FixBehaviorNames : PostMergeFix
	{
		public override void Apply(TowerModel model)
		{
			List<Model> list = ((IEnumerable<Model>)((EntityModel)model).behaviors).ToList();
			for (int i = 0; i < list.Count; i++)
			{
				Model behavior = list[i];
				if (list.Take(i).Any((Model b) => b.name == behavior.name))
				{
					Model obj = behavior;
					obj.name += i;
				}
			}
		}
	}
	public class FixCannonShips : PostMergeFix
	{
		public override void Apply(TowerModel model)
		{
			if (((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("Buccaneer-Cannon Ship"))
			{
				if (((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("Buccaneer-Aircraft Carrier"))
				{
				}
				if (((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("Buccaneer-Destroyer"))
				{
					WeaponModel weapon = TowerModelExt.GetWeapon(model, 4);
					weapon.Rate /= 5f;
					WeaponModel weapon2 = TowerModelExt.GetWeapon(model, 5);
					weapon2.Rate /= 5f;
				}
			}
		}
	}
	public class FixClusterMauling : PostMergeFix
	{
		public override void Apply(TowerModel model)
		{
			if (!((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("MOAB Mauler"))
			{
				return;
			}
			List<DamageModifierForTagModel> source = Il2CppGenericIEnumerableExt.ToList<DamageModifierForTagModel>(((Model)model).GetDescendants<DamageModifierForTagModel>());
			DamageModifierForTagModel val = ((IEnumerable<DamageModifierForTagModel>)source).FirstOrDefault((Func<DamageModifierForTagModel, bool>)((DamageModifierForTagModel m) => m.tag == "Moabs"));
			DamageModifierForTagModel val2 = ((IEnumerable<DamageModifierForTagModel>)source).FirstOrDefault((Func<DamageModifierForTagModel, bool>)((DamageModifierForTagModel m) => m.tag == "Ceramic"));
			foreach (ProjectileModel item in from p in Il2CppGenericIEnumerableExt.ToList<ProjectileModel>(((Model)model).GetDescendants<ProjectileModel>())
				where p.id == "Explosion"
				select p)
			{
				ProjectileModelBehaviorExt.RemoveBehaviors<DamageModifierForTagModel>(item);
				if (val != null)
				{
					ProjectileModelBehaviorExt.AddBehavior<DamageModifierForTagModel>(item, ModelExt.Duplicate<DamageModifierForTagModel>(val));
				}
				if (val2 != null)
				{
					ProjectileModelBehaviorExt.AddBehavior<DamageModifierForTagModel>(item, ModelExt.Duplicate<DamageModifierForTagModel>(val2));
				}
			}
		}
	}
	public class FixCrowsNest : PostMergeFix
	{
		public override void Apply(TowerModel model)
		{
			if (((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("Buccaneer-Crow's Nest"))
			{
				Il2CppGenericIEnumerable.ForEach<FilterInvisibleModel>(((Model)model).GetDescendants<FilterInvisibleModel>(), (Action<FilterInvisibleModel>)delegate(FilterInvisibleModel filter)
				{
					filter.isActive = false;
				});
			}
		}
	}
	public class FixGlueOverriding : PostMergeFix
	{
		public override void Apply(TowerModel model)
		{
			if (!((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("MOAB Glue"))
			{
				return;
			}
			Il2CppGenericIEnumerable.ForEach<ProjectileModel>(((Model)model).GetDescendants<ProjectileModel>(), (Action<ProjectileModel>)delegate(ProjectileModel projectileModel)
			{
				List<Model> list = Il2CppReferenceArrayExt.ToList<Model>(projectileModel.behaviors);
				list.RemoveAll((Model m) => m.name == "SlowModifierForTagModel_");
				projectileModel.behaviors = ListExt.ToIl2CppReferenceArray<Model>(list);
			});
			float lifeSpan = 0f;
			Il2CppGenericIEnumerable.ForEach<SlowForBloonModel>(((Model)model).GetDescendants<SlowForBloonModel>(), (Action<SlowForBloonModel>)delegate(SlowForBloonModel m)
			{
				lifeSpan = Math.Max(lifeSpan, ((SlowModel)m).Lifespan);
			});
			Il2CppGenericIEnumerable.ForEach<SlowModel>(((Model)model).GetDescendants<SlowModel>(), (Action<SlowModel>)delegate(SlowModel m)
			{
				lifeSpan = Math.Max(lifeSpan, m.Lifespan);
			});
			Il2CppGenericIEnumerable.ForEach<AddBehaviorToBloonModel>(((Model)model).GetDescendants<AddBehaviorToBloonModel>(), (Action<AddBehaviorToBloonModel>)delegate(AddBehaviorToBloonModel m)
			{
				lifeSpan = Math.Max(lifeSpan, m.lifespan);
			});
			Il2CppGenericIEnumerable.ForEach<SlowForBloonModel>(((Model)model).GetDescendants<SlowForBloonModel>(), (Action<SlowForBloonModel>)delegate(SlowForBloonModel m)
			{
				((SlowModel)m).Lifespan = lifeSpan;
			});
			Il2CppGenericIEnumerable.ForEach<SlowModel>(((Model)model).GetDescendants<SlowModel>(), (Action<SlowModel>)delegate(SlowModel m)
			{
				m.Lifespan = lifeSpan;
			});
			Il2CppGenericIEnumerable.ForEach<AddBehaviorToBloonModel>(((Model)model).GetDescendants<AddBehaviorToBloonModel>(), (Action<AddBehaviorToBloonModel>)delegate(AddBehaviorToBloonModel m)
			{
				m.lifespan = lifeSpan;
			});
			Il2CppGenericIEnumerable.ForEach<AttackFilterModel>(((Model)model).GetDescendants<AttackFilterModel>(), (Action<AttackFilterModel>)delegate(AttackFilterModel filterModel)
			{
				List<FilterModel> list = Il2CppReferenceArrayExt.ToList<FilterModel>(filterModel.filters);
				list.RemoveAll((FilterModel m) => Il2CppSystemObjectExt.IsType<FilterOutTagModel>((Object)(object)m));
				filterModel.filters = ListExt.ToIl2CppReferenceArray<FilterModel>(list);
			});
			Il2CppGenericIEnumerable.ForEach<ProjectileFilterModel>(((Model)model).GetDescendants<ProjectileFilterModel>(), (Action<ProjectileFilterModel>)delegate(ProjectileFilterModel filterModel)
			{
				List<FilterModel> list = Il2CppReferenceArrayExt.ToList<FilterModel>(filterModel.filters);
				list.RemoveAll((FilterModel m) => Il2CppSystemObjectExt.IsType<FilterOutTagModel>((Object)(object)m));
				filterModel.filters = ListExt.ToIl2CppReferenceArray<FilterModel>(list);
			});
		}
	}
	public class FixHomingProjectiles : PostMergeFix
	{
		public override void Apply(TowerModel model)
		{
			Enumerator<ProjectileModel> enumerator = Il2CppGenerics.Where<ProjectileModel>(Il2CppGenericIEnumerableExt.ToIl2CppList<ProjectileModel>(((Model)model).GetDescendants<ProjectileModel>()), (Func<ProjectileModel, bool>)((ProjectileModel projectileModel) => ProjectileModelBehaviorExt.GetBehavior<RetargetOnContactModel>(projectileModel) != null)).GetEnumerator();
			while (enumerator.MoveNext())
			{
				ProjectileModel current = enumerator.Current;
				ProjectileModelBehaviorExt.RemoveBehavior<FollowPathModel>(current);
			}
		}
	}
	public class FixIceMonkeyRange : PostMergeFix
	{
		public override void Apply(TowerModel model)
		{
			SlowBloonsZoneModel val = default(SlowBloonsZoneModel);
			if (Il2CppSystemObjectExt.IsType<SlowBloonsZoneModel>((Object)(object)((Model)model).GetDescendant<SlowBloonsZoneModel>(), ref val))
			{
				val.zoneRadius = model.range + 5f;
			}
		}
	}
	public class FixLifespans : PostMergeFix
	{
		public override void Apply(TowerModel model)
		{
			Il2CppGenericIEnumerable.ForEach<AgeModel>(((Model)model).GetDescendants<AgeModel>(), (Action<AgeModel>)delegate(AgeModel ageModel)
			{
				ageModel.Lifespan = Math.Max(ageModel.Lifespan, (float)ageModel.lifespanFrames / 60f);
			});
		}
	}
	public class FixMermonkey : PostMergeFix
	{
		public override void Apply(TowerModel model)
		{
			if (((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("Symphonic Resonance"))
			{
				model.towerSelectionMenuThemeId = "MermonkeyTrance";
				if (((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("UpgradeType.SymphonicResonance"))
				{
					AttackModel val = ((Il2CppArrayBase<AttackModel>)(object)((Model)model).GetDescendant<ActivateAttackModel>().attacks)[0];
					AttackModelBehaviorExt.RemoveBehavior<TargetSelectedPointOrDefaultModel>(val);
					((Model)val).RemoveChildDependant<TargetSupplierModel>(val.targetProvider);
					val.targetProvider = null;
				}
			}
		}
	}
	public class FixPlasmaBeams : PostMergeFix
	{
		public override void Apply(TowerModel model)
		{
			if (((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("Plasma Accelerator"))
			{
				TowerModelExt.GetWeapon(model).projectile.radius = 2f;
			}
			List<AttackModel> list = (from attackModel in TowerModelExt.GetAttackModels(model)
				where Il2CppReferenceArray.Any<WeaponModel>(attackModel.weapons, (Func<WeaponModel, bool>)((WeaponModel weaponModel) => Il2CppSystemObjectExt.IsType<LineProjectileEmissionModel>((Object)(object)weaponModel.emission)))
				select attackModel).ToList();
			if (list.Count <= 1)
			{
				return;
			}
			List<Model> list2 = ((IEnumerable<Model>)((EntityModel)model).behaviors).ToList();
			AttackModel val = default(AttackModel);
			list2.RemoveAll((Model m) => Il2CppSystemObjectExt.IsType<AttackModel>((Object)(object)m, ref val) && Il2CppReferenceArray.Any<WeaponModel>(val.weapons, (Func<WeaponModel, bool>)((WeaponModel weaponModel) => Il2CppSystemObjectExt.IsType<LineProjectileEmissionModel>((Object)(object)weaponModel.emission))));
			list2.Add((Model)(object)list[0]);
			((EntityModel)model).behaviors = ListExt.ToIl2CppReferenceArray<Model>(list2);
		}
	}
	public class FixPowersPro : PostMergeFix
	{
		public override void Apply(TowerModel model)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			if (string.IsNullOrEmpty(model.powerName))
			{
				return;
			}
			TowerModelBehaviorExt.RemoveBehaviors<PowerProTowerModel>(model);
			TowerModelBehaviorExt.AddBehavior<PowerProTowerModel>(model, new PowerProTowerModel(((Model)model).name, model.powerName));
			if (((EntityModel)model).baseId == TowerType.SuperMonkeyBeacon)
			{
				((Model)model).GetDescendant<ActivateAttackModel>().Lifespan = (((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("Reverberation") ? 3.05f : (((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("Storm Tremors") ? 2.05f : 0f));
				foreach (WeaponModel item in Il2CppGenericIEnumerable.AsIEnumerable<WeaponModel>(((Model)model).GetDescendants<WeaponModel>()))
				{
					if (((Model)item).name.Contains("FollowUp"))
					{
						item.customStartCooldown = 2f;
					}
					else if (((Model)item).name.Contains("Third"))
					{
						item.customStartCooldown = 3f;
					}
				}
			}
			if (((EntityModel)model).baseId == "MonkeyBoostPro")
			{
				AbilityModel ability = TowerModelExt.GetAbility(model);
				if (((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("Resistance"))
				{
					ability.Cooldown = 60f;
				}
				int lifespan = (((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("NoQuit") ? 30 : (((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("HighReps") ? 20 : 15));
				Il2CppGenericIEnumerable.ForEach<ActivateRateSupportZoneModel>(((Model)ability).GetDescendants<ActivateRateSupportZoneModel>(), (Action<ActivateRateSupportZoneModel>)delegate(ActivateRateSupportZoneModel m)
				{
					m.lifespan = lifespan;
				});
				Il2CppGenericIEnumerable.ForEach<ActivateRangeSupportZoneModel>(((Model)ability).GetDescendants<ActivateRangeSupportZoneModel>(), (Action<ActivateRangeSupportZoneModel>)delegate(ActivateRangeSupportZoneModel m)
				{
					m.lifespan = lifespan;
				});
				Il2CppGenericIEnumerable.ForEach<ActivateVisibilitySupportZoneModel>(((Model)ability).GetDescendants<ActivateVisibilitySupportZoneModel>(), (Action<ActivateVisibilitySupportZoneModel>)delegate(ActivateVisibilitySupportZoneModel m)
				{
					m.lifespan = lifespan;
				});
				Il2CppGenericIEnumerable.ForEach<ActivateAttackCollisionSupportZoneModel>(((Model)ability).GetDescendants<ActivateAttackCollisionSupportZoneModel>(), (Action<ActivateAttackCollisionSupportZoneModel>)delegate(ActivateAttackCollisionSupportZoneModel m)
				{
					m.lifespan = lifespan;
				});
				Il2CppGenericIEnumerable.ForEach<ActivateSpreadSupportZoneModel>(((Model)ability).GetDescendants<ActivateSpreadSupportZoneModel>(), (Action<ActivateSpreadSupportZoneModel>)delegate(ActivateSpreadSupportZoneModel m)
				{
					m.lifespan = lifespan;
				});
				Il2CppGenericIEnumerable.ForEach<ActivateIgnoreStunSupportZoneModel>(((Model)ability).GetDescendants<ActivateIgnoreStunSupportZoneModel>(), (Action<ActivateIgnoreStunSupportZoneModel>)delegate(ActivateIgnoreStunSupportZoneModel m)
				{
					m.lifespan = lifespan;
				});
			}
			if (!(((EntityModel)model).baseId == TowerType.TechBotPrime))
			{
				return;
			}
			if (((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("NEUR0MAP"))
			{
				Il2CppGenericIEnumerable.ForEach<TechBotLinkModel>(((Model)model).GetDescendants<TechBotLinkModel>(), (Action<TechBotLinkModel>)delegate(TechBotLinkModel m)
				{
					m.activateInRadius = true;
				});
			}
			if (((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("DroneAmbusNetwork"))
			{
				TowerModelBehaviorExt.RemoveBehavior<AttackModel>(model);
				TowerModelBehaviorExt.RemoveBehavior<AbilityModel>(model, "AmbushTechAbility");
				model.UpdateTargetProviders();
			}
		}
	}
	public class FixSmallRanges : PostMergeFix
	{
		public override void Apply(TowerModel model)
		{
			List<AttackModel> attackModels = TowerModelExt.GetAttackModels(model);
			foreach (AttackModel item in attackModels.Where((AttackModel attackModel) => attackModel.range < model.range))
			{
				item.range = model.range;
			}
		}
	}
	public class FixSpikeStorm : PostMergeFix
	{
		public override void Apply(TowerModel model)
		{
			if (((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("Spike Storm"))
			{
				ProjectileModel realProjectile = TowerModelExt.GetWeapon(model).projectile;
				Il2CppReferenceArray.ForEach<AttackModel>(AbilityModelBehaviorExt.GetBehavior<ActivateAttackModel>(TowerModelExt.GetAbility(model)).attacks, (Action<AttackModel>)delegate(AttackModel attackModel)
				{
					ProjectileModel projectile = ((Il2CppArrayBase<WeaponModel>)(object)attackModel.weapons)[0].projectile;
					AgeRandomModel val = ModelExt.Duplicate<AgeRandomModel>(ProjectileModelBehaviorExt.GetBehavior<AgeRandomModel>(projectile));
					ProjectileModel val2 = ModelExt.Duplicate<ProjectileModel>(realProjectile);
					ProjectileModelBehaviorExt.RemoveBehaviors<AgeModel>(val2);
					ProjectileModelBehaviorExt.AddBehavior<AgeRandomModel>(val2, val);
					((Il2CppArrayBase<WeaponModel>)(object)attackModel.weapons)[0].projectile = val2;
				});
			}
		}
	}
	public class FixTemples : PostMergeFix
	{
		public override void Apply(TowerModel model)
		{
			if (!((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("Sun Temple"))
			{
				return;
			}
			foreach (AttackModel attackModel in TowerModelExt.GetAttackModels(model))
			{
				RotateToTargetModel behavior = AttackModelBehaviorExt.GetBehavior<RotateToTargetModel>(attackModel);
				if (behavior != null)
				{
					behavior.rotateTower = false;
				}
				AttackModelBehaviorExt.RemoveBehaviors<RotateToMiddleOfTargetsModel>(attackModel);
			}
		}
	}
	public abstract class PostMergeFix : ModContent
	{
		protected override float RegistrationPriority => 0f;

		public override int RegisterPerFrame => 999;

		public sealed override void Register()
		{
		}

		public abstract void Apply(TowerModel model);
	}
}
namespace UltimateCrosspathing.Merging
{
	public static class DeepMerging
	{
		public class History
		{
			public readonly Stack<Object> left;

			public readonly Stack<Object> right;

			public readonly Stack<Object> ancestor;

			public int depth;

			public History()
			{
				left = new Stack<Object>();
				right = new Stack<Object>();
				ancestor = new Stack<Object>();
				depth = -1;
			}

			public void Push(Object l, Object r, Object a)
			{
				left.Push(l);
				right.Push(r);
				ancestor.Push(a);
				depth++;
			}

			public Object Pop()
			{
				Object result = left.Pop();
				right.Pop();
				ancestor.Pop();
				depth--;
				return result;
			}

			public T GetLeft<T>() where T : Object
			{
				return (from o in left
					where Il2CppSystemObjectExt.IsType<T>(o)
					select ((Il2CppObjectBase)o).Cast<T>()).FirstOrDefault();
			}

			public T GetRight<T>() where T : Object
			{
				return (from o in right
					where Il2CppSystemObjectExt.IsType<T>(o)
					select ((Il2CppObjectBase)o).Cast<T>()).FirstOrDefault();
			}

			public T GetAncestor<T>() where T : Object
			{
				return (from o in ancestor
					where Il2CppSystemObjectExt.IsType<T>(o)
					select ((Il2CppObjectBase)o).Cast<T>()).FirstOrDefault();
			}
		}

		private static readonly HashSet<string> DontMerge = new HashSet<string>
		{
			"animation", "offsetX", "offsetY", "offsetZ", "ejectX", "ejectY", "ejectZ", "rate", "rateFrames", "isPowerTower",
			"isGeraldoItem", "isPowerProTower"
		};

		private static readonly HashSet<string> Multiplicative = new HashSet<string> { "pierce", "range" };

		private static readonly Dictionary<string, string> StringOverrides = new Dictionary<string, string>
		{
			{ "fcddee8a92f5d2e4d8605a8924566620", "69bf8d5932f2bea4f9ce36f861240d2e" },
			{ "0ddd8752be0d3554cb0db6abe6686e8e", "69bf8d5932f2bea4f9ce36f861240d2e" }
		};

		private static readonly Dictionary<Tuple<string, Type>, bool> BetterBooleans = new Dictionary<Tuple<string, Type>, bool>
		{
			{
				new Tuple<string, Type>("isActive", Il2CppType.Of<FilterModel>()),
				false
			},
			{
				new Tuple<string, Type>("ignoreBlockers", Il2CppType.Of<ProjectileModel>()),
				true
			},
			{
				new Tuple<string, Type>("isSharedRangeEnabled", Il2CppType.Of<TargetSupplierModel>()),
				true
			}
		};

		private static readonly string[] SharedAbilityNames = new string[2] { "Super Monkey Beacon", "Monkey Boost Pro" };

		private static Object DeepMerge(Object left, Object right, Object ancestor, History history, bool shallow = false)
		{
			if (right == null)
			{
				return left;
			}
			if (left == null)
			{
				return right;
			}
			history.Push(left, right, ancestor);
			try
			{
				WeaponModel val = default(WeaponModel);
				WeaponModel val2 = default(WeaponModel);
				WeaponModel val3 = default(WeaponModel);
				if (Il2CppSystemObjectExt.IsType<WeaponModel>(left, ref val) && Il2CppSystemObjectExt.IsType<WeaponModel>(right, ref val2) && ancestor != null && Il2CppSystemObjectExt.IsType<WeaponModel>(ancestor, ref val3))
				{
					WeaponModel obj = val;
					obj.Rate *= val2.Rate / val3.Rate;
				}
				Model leftModel = default(Model);
				Model rightModel = default(Model);
				if (Il2CppSystemObjectExt.IsType<Model>(left, ref leftModel) && Il2CppSystemObjectExt.IsType<Model>(right, ref rightModel) && !(ModelsAreTheSame(leftModel, rightModel, array: false, history) || shallow))
				{
					return MergeDifferentModels(left, right, ancestor, history);
				}
				Il2CppReferenceArray<FieldInfo> fields = left.GetIl2CppType().GetFields();
				foreach (FieldInfo item in (Il2CppArrayBase<FieldInfo>)(object)fields)
				{
					string fieldName = ((MemberInfo)item).Name;
					if (!DontMerge.Any((string s) => fieldName.Contains(s)))
					{
						MergeField((MemberInfo)(object)item, left, right, ancestor, history, shallow);
					}
				}
				Il2CppReferenceArray<PropertyInfo> properties = left.GetIl2CppType().GetProperties();
				foreach (PropertyInfo item2 in (Il2CppArrayBase<PropertyInfo>)(object)properties)
				{
					string propertyName = ((MemberInfo)item2).Name;
					if (propertyName.ToUpper()[0] != propertyName[0] && !DontMerge.Any((string s) => propertyName.Contains(s)))
					{
						MergeField((MemberInfo)(object)item2, left, right, ancestor, history, shallow);
					}
				}
				return left;
			}
			finally
			{
				history.Pop();
			}
		}

		public static void MergeField(MemberInfo memberInfo, Object left, Object right, Object ancestor, History history = null, bool shallow = false)
		{
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Expected I4, but got Unknown
			Type val = memberInfo.Type();
			Object value = memberInfo.GetValue(left);
			Object value2 = memberInfo.GetValue(right);
			if (history == null)
			{
				history = new History();
				history.Push(left, right, ancestor);
			}
			Log(memberInfo.Name + " (" + ((MemberInfo)val).Name + ")", history.depth);
			Object val2 = null;
			if (ancestor != null && ((Il2CppArrayBase<MemberInfo>)(object)ancestor.GetIl2CppType().GetMember(memberInfo.Name)).Length > 0)
			{
				val2 = memberInfo.GetValue(ancestor);
			}
			if (value == null && value2 == null)
			{
				return;
			}
			if (val.IsArray)
			{
				memberInfo.SetValue(left, MergeArray(memberInfo, value, value2, val2, history, shallow));
			}
			else if (val.IsType<float>())
			{
				memberInfo.SetValue(left, MergeFloat(memberInfo, value, value2, val2));
			}
			else if (val.IsType<int>())
			{
				memberInfo.SetValue(left, MergeInt(memberInfo, value, value2, val2));
			}
			else if (val.IsType<bool>())
			{
				memberInfo.SetValue(left, MergeBool(memberInfo, value, value2, history));
			}
			else if (val.IsType<Model>())
			{
				memberInfo.SetValue(left, DeepMerge(value, value2, val2, history));
			}
			else if (val.IsType<string>())
			{
				FieldInfo val3 = ((Il2CppObjectBase)memberInfo).TryCast<FieldInfo>();
				if (val3 == (FieldInfo)null || (!val3.IsLiteral && !val3.IsInitOnly))
				{
					memberInfo.SetValue(left, MergeString(memberInfo, value, value2, val2));
				}
			}
			else if (val.IsType<BloonProperties>())
			{
				BloonProperties val4 = ((Il2CppObjectBase)value).Unbox<BloonProperties>();
				BloonProperties val5 = ((Il2CppObjectBase)value2).Unbox<BloonProperties>();
				int num = val4 & val5;
				memberInfo.SetValue(left, Il2CppSystemObjectExt.ToIl2Cpp(num));
			}
		}

		private static Object MergeArray(MemberInfo memberInfo, Object left, Object right, Object ancestor, History history, bool shallow = false)
		{
			if (left == null && right != null)
			{
				return right;
			}
			if (right == null && left != null)
			{
				return left;
			}
			history.depth++;
			Type elementType = memberInfo.Type().GetElementType();
			List<Object> list = new List<Object>();
			List<Object> list2 = new List<Object>();
			IEnumerator enumerator = ((Il2CppObjectBase)left).Cast<Array>().GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					Object current = enumerator.Current;
					list2.Add(current);
				}
			}
			finally
			{
				if (enumerator is IDisposable disposable)
				{
					disposable.Dispose();
				}
			}
			List<Object> list3 = new List<Object>();
			IEnumerator enumerator2 = ((Il2CppObjectBase)right).Cast<Array>().GetEnumerator();
			try
			{
				while (enumerator2.MoveNext())
				{
					Object current2 = enumerator2.Current;
					list3.Add(current2);
				}
			}
			finally
			{
				if (enumerator2 is IDisposable disposable2)
				{
					disposable2.Dispose();
				}
			}
			List<Object> list4 = new List<Object>();
			if (ancestor != null)
			{
				IEnumerator enumerator3 = ((Il2CppObjectBase)ancestor).Cast<Array>().GetEnumerator();
				try
				{
					while (enumerator3.MoveNext())
					{
						Object current3 = enumerator3.Current;
						list4.Add(current3);
					}
				}
				finally
				{
					if (enumerator3 is IDisposable disposable3)
					{
						disposable3.Dispose();
					}
				}
			}
			if (!elementType.IsType<Model>())
			{
				list = ((memberInfo.Name == "collisionPasses") ? ((list3.Count > list2.Count) ? list3 : list2) : ((list2.Count != list4.Count || list3.Count == list4.Count) ? list2 : list3));
			}
			else
			{
				AttackModel val2 = default(AttackModel);
				foreach (Object item in list2)
				{
					Model leftModel = ((Il2CppObjectBase)item).Cast<Model>();
					Model val = list3.Select((Object rightThing) => ((Il2CppObjectBase)rightThing).Cast<Model>()).FirstOrDefault((Func<Model, bool>)((Model model) => ModelsAreTheSame(leftModel, model, array: true, history)));
					if (val != null && !shallow)
					{
						Model ancestor2 = list4.Select((Object ancestorThing) => ((Il2CppObjectBase)ancestorThing).Cast<Model>()).FirstOrDefault((Func<Model, bool>)((Model model) => ModelsAreTheSame(leftModel, model, array: true, history)));
						Log(leftModel.name + " (" + ((MemberInfo)((Object)leftModel).GetIl2CppType()).Name + ")", history.depth);
						DeepMerge((Object)(object)leftModel, (Object)(object)val, (Object)(object)ancestor2, history);
					}
					list.Add((Object)(object)leftModel);
					if (Il2CppSystemObjectExt.IsType<AttackModel>((Object)(object)leftModel, ref val2))
					{
						TowerModel left2 = history.GetLeft<TowerModel>();
						TowerModel right2 = history.GetRight<TowerModel>();
						if ((double)Math.Abs(right2.range - val2.range) < 10000000.0 && left2.range > right2.range)
						{
							val2.range = Math.Max(left2.range, val2.range);
						}
					}
				}
				Model val5 = default(Model);
				AttackModel val6 = default(AttackModel);
				foreach (Object item2 in list3)
				{
					Model rightModel = ((Il2CppObjectBase)item2).Cast<Model>();
					Model val3 = list2.Select((Object leftThing) => ((Il2CppObjectBase)leftThing).Cast<Model>()).FirstOrDefault((Func<Model, bool>)((Model model) => ModelsAreTheSame(model, rightModel, array: true, history)));
					if (val3 != null)
					{
						continue;
					}
					list.Add((Object)(object)rightModel);
					Object val4 = history.left.Peek();
					if (val4 != null && Il2CppSystemObjectExt.IsType<Model>(val4, ref val5))
					{
						val5.AddChildDependant<Model>(rightModel);
					}
					if (Il2CppSystemObjectExt.IsType<AttackModel>((Object)(object)rightModel, ref val6))
					{
						TowerModel left3 = history.GetLeft<TowerModel>();
						TowerModel right3 = history.GetRight<TowerModel>();
						if ((double)Math.Abs(right3.range - val6.range) < 10000000.0 && left3.range > right3.range)
						{
							val6.range = Math.Max(left3.range, val6.range);
						}
					}
				}
			}
			Array val7 = Array.CreateInstance(memberInfo.Type().GetElementType(), list.Count);
			for (int num = 0; num < list.Count; num++)
			{
				val7.SetValue(list[num], num);
			}
			history.depth--;
			return (Object)(object)val7;
		}

		private static Object MergeInt(MemberInfo memberInfo, Object leftValue, Object rightValue, Object ancestorValue)
		{
			if (leftValue == null)
			{
				return rightValue;
			}
			if (rightValue == null)
			{
				return leftValue;
			}
			int num = ((Il2CppObjectBase)leftValue).Unbox<int>();
			int num2 = ((Il2CppObjectBase)rightValue).Unbox<int>();
			if (ancestorValue != null && num != num2)
			{
				int num3 = ((Il2CppObjectBase)ancestorValue).Unbox<int>();
				num = ((!Multiplicative.Any((string s) => memberInfo.Name.Contains(s))) ? (num + (num2 - num3)) : (num * num2 / num3));
			}
			return Il2CppSystemObjectExt.ToIl2Cpp(num);
		}

		private static Object MergeFloat(MemberInfo memberInfo, Object leftValue, Object rightValue, Object ancestorValue)
		{
			if (leftValue == null)
			{
				return rightValue;
			}
			if (rightValue == null)
			{
				return leftValue;
			}
			float num = ((Il2CppObjectBase)leftValue).Unbox<float>();
			float num2 = ((Il2CppObjectBase)rightValue).Unbox<float>();
			if (ancestorValue != null && (double)Math.Abs(num - num2) > 1E-07)
			{
				float num3 = ((Il2CppObjectBase)ancestorValue).Unbox<float>();
				num = ((!Multiplicative.Any((string s) => memberInfo.Name.Contains(s))) ? (num + (num2 - num3)) : (num * (num2 / num3)));
			}
			return Il2CppSystemObjectExt.ToIl2Cpp(num);
		}

		private static Object MergeBool(MemberInfo memberInfo, Object leftValue, Object rightValue, History history)
		{
			if (leftValue == null)
			{
				return rightValue;
			}
			if (rightValue == null)
			{
				return leftValue;
			}
			string name = memberInfo.Name;
			bool flag = ((Il2CppObjectBase)leftValue).Unbox<bool>();
			bool flag2 = ((Il2CppObjectBase)rightValue).Unbox<bool>();
			if (flag != flag2)
			{
				foreach (KeyValuePair<Tuple<string, Type>, bool> betterBoolean in BetterBooleans)
				{
					betterBoolean.Deconstruct(out var key, out var value);
					key.Deconstruct(out var item, out var item2);
					string value2 = item;
					Type val = item2;
					bool flag3 = value;
					if (name.Contains(value2) && ((Object)history.GetLeft<Model>()).GetIl2CppType().IsSubclassOf(val))
					{
						return Il2CppSystemObjectExt.ToIl2Cpp(flag3);
					}
				}
			}
			return Il2CppSystemObjectExt.ToIl2Cpp(flag);
		}

		private static Object MergeString(MemberInfo memberInfo, Object leftValue, Object rightValue, Object ancestorValue)
		{
			try
			{
				if (leftValue == null)
				{
					return rightValue;
				}
				if (rightValue == null)
				{
					return leftValue;
				}
				string text = leftValue.ToString();
				string text2 = rightValue.ToString();
				if (StringOverrides.ContainsKey(text) && StringOverrides[text] == text2)
				{
					return Object.op_Implicit(text);
				}
				if (StringOverrides.ContainsKey(text2) && StringOverrides[text2] == text)
				{
					return Object.op_Implicit(text2);
				}
				if (ancestorValue != null)
				{
					string text3 = ancestorValue.ToString();
					if (text == text3 && text2 != text3)
					{
						return rightValue;
					}
				}
			}
			catch (Exception innerException)
			{
				throw new Exception("Failed to merge strings for " + memberInfo.Name, innerException);
			}
			return leftValue;
		}

		private static Object MergeDifferentModels(Object left, Object right, Object ancestor, History history)
		{
			Model val = ((Il2CppObjectBase)left).Cast<Model>();
			Model val2 = ((Il2CppObjectBase)right).Cast<Model>();
			Model val3 = null;
			if (ancestor != null)
			{
				val3 = ((Il2CppObjectBase)ancestor).Cast<Model>();
			}
			EmissionModel emissionModel = default(EmissionModel);
			EmissionModel emissionModel2 = default(EmissionModel);
			if (Il2CppSystemObjectExt.IsType<EmissionModel>((Object)(object)val, ref emissionModel) && Il2CppSystemObjectExt.IsType<EmissionModel>((Object)(object)val2, ref emissionModel2))
			{
				if (Il2CppSystemObjectExt.IsType<SendToBankModel>((Object)(object)val2))
				{
					return (Object)(object)val2;
				}
				int countForEmissionModel = GetCountForEmissionModel(left, emissionModel);
				int countForEmissionModel2 = GetCountForEmissionModel(right, emissionModel2);
				TowerModel left2 = history.GetLeft<TowerModel>();
				if (((left2 != null) ? TowerModelBehaviorExt.GetBehavior<LinkProjectileRadiusToTowerRangeModel>(left2) : null) != null)
				{
					WeaponModel left3 = history.GetLeft<WeaponModel>();
					WeaponModel ancestor2 = history.GetAncestor<WeaponModel>();
					if (left3 != null && ancestor2 != null)
					{
						int countForEmissionModel3 = GetCountForEmissionModel(ancestor, ((Il2CppObjectBase)val3).Cast<EmissionModel>());
						ProjectileModelExt.GetDamageModel(left3.projectile).damage = (float)Math.Round(ProjectileModelExt.GetDamageModel(left3.projectile).damage * (float)countForEmissionModel2 / (float)countForEmissionModel3);
						TowerModelBehaviorExt.GetBehavior<LinkProjectileRadiusToTowerRangeModel>(history.GetLeft<TowerModel>()).projectileModel = left3.projectile;
					}
					return (Object)(object)val;
				}
				return (Object)(object)((countForEmissionModel2 > countForEmissionModel) ? val2 : val);
			}
			ProjectileModel val4 = default(ProjectileModel);
			ProjectileModel val5 = default(ProjectileModel);
			ProjectileModel val6 = default(ProjectileModel);
			if (Il2CppSystemObjectExt.IsType<ProjectileModel>((Object)(object)val, ref val4) && Il2CppSystemObjectExt.IsType<ProjectileModel>((Object)(object)val2, ref val5) && Il2CppSystemObjectExt.IsType<ProjectileModel>((Object)(object)val3, ref val6))
			{
				return DeepMerge((Object)(object)val, (Object)(object)val2, ancestor, history, shallow: true);
			}
			return (Object)(object)val;
		}

		private static Object ShallowMerge(Object left, Object right, Object ancestor, History history)
		{
			Il2CppReferenceArray<FieldInfo> fields = left.GetIl2CppType().GetFields();
			foreach (FieldInfo item in (Il2CppArrayBase<FieldInfo>)(object)fields)
			{
				Object value = item.GetValue(left);
				Object value2 = item.GetValue(right);
				string fieldName = ((MemberInfo)item).Name;
				if (!DontMerge.Any((string s) => fieldName.Contains(s)))
				{
					if (((MemberInfo)(object)item).Type().IsArray)
					{
						item.SetValue(left, MergeArray((MemberInfo)(object)item, value, value2, ancestor, history, shallow: true));
					}
					else
					{
						MergeField((MemberInfo)(object)item, left, right, ancestor, history);
					}
				}
			}
			Il2CppReferenceArray<PropertyInfo> properties = left.GetIl2CppType().GetProperties();
			foreach (PropertyInfo item2 in (Il2CppArrayBase<PropertyInfo>)(object)properties)
			{
				Object value3 = item2.GetValue(left);
				Object value4 = item2.GetValue(right);
				string propertyName = ((MemberInfo)item2).Name;
				if (propertyName.ToUpper()[0] != propertyName[0] && !DontMerge.Any((string s) => propertyName.Contains(s)))
				{
					if (((MemberInfo)(object)item2).Type().IsArray)
					{
						item2.SetValue(left, MergeArray((MemberInfo)(object)item2, left, right, ancestor, history, shallow: true));
					}
					else
					{
						MergeField((MemberInfo)(object)item2, left, right, ancestor, history);
					}
				}
			}
			return left;
		}

		private static int GetCountForEmissionModel(Object methodInfo, EmissionModel emissionModel)
		{
			int result = 1;
			if (Il2CppSystemObjectExt.IsType<LineProjectileEmissionModel>((Object)(object)emissionModel))
			{
				result = 10000;
			}
			PropertyInfo property = ((Object)emissionModel).GetIl2CppType().GetProperty("count");
			if (property != (PropertyInfo)null)
			{
				Object value = property.GetValue(methodInfo);
				if (value != null)
				{
					result = ((Il2CppObjectBase)value).Unbox<int>();
				}
			}
			FieldInfo field = ((Object)emissionModel).GetIl2CppType().GetField("count");
			if (field != (FieldInfo)null)
			{
				Object value2 = field.GetValue(methodInfo);
				if (value2 != null)
				{
					result = ((Il2CppObjectBase)value2).Unbox<int>();
				}
			}
			return result;
		}

		private static void Log(string msg, int depth)
		{
			for (int i = 0; i < depth; i++)
			{
				msg = "|  " + msg;
			}
		}

		private static bool ModelsAreTheSame(Model leftModel, Model rightModel, bool array, History history)
		{
			AbilityModel leftAbility = default(AbilityModel);
			AbilityModel rightAbility = default(AbilityModel);
			if (Il2CppSystemObjectExt.IsType<AbilityModel>((Object)(object)leftModel, ref leftAbility) && Il2CppSystemObjectExt.IsType<AbilityModel>((Object)(object)rightModel, ref rightAbility))
			{
				return leftAbility.displayName == rightAbility.displayName || ArrayExt.Any<string>(SharedAbilityNames, (Func<string, bool>)((string name) => leftAbility.displayName.StartsWith(name) && rightAbility.displayName.StartsWith(name)));
			}
			if (Il2CppSystemObjectExt.IsType<TowerBehaviorModel>((Object)(object)leftModel) && Il2CppSystemObjectExt.IsType<TowerBehaviorModel>((Object)(object)rightModel) && leftModel.name.Contains("Create") && rightModel.name.Contains("Create") && leftModel.name.Contains("On") && rightModel.name.Contains("On") && ((MemberInfo)((Object)leftModel).GetIl2CppType()).Name == ((MemberInfo)((Object)rightModel).GetIl2CppType()).Name)
			{
				return true;
			}
			if (Il2CppSystemObjectExt.IsType<ProjectileModel>((Object)(object)leftModel) && Il2CppSystemObjectExt.IsType<ProjectileModel>((Object)(object)rightModel))
			{
				ProjectileModel val = ((Il2CppObjectBase)leftModel).Cast<ProjectileModel>();
				ProjectileModel val2 = ((Il2CppObjectBase)rightModel).Cast<ProjectileModel>();
				return val.id == val2.id || array;
			}
			AttackModel val3 = default(AttackModel);
			AttackModel val4 = default(AttackModel);
			if (Il2CppSystemObjectExt.IsType<AttackModel>((Object)(object)leftModel, ref val3) && Il2CppSystemObjectExt.IsType<AttackModel>((Object)(object)rightModel, ref val4))
			{
				bool flag = Il2CppReferenceArray.Any<WeaponModel>(val3.weapons, (Func<WeaponModel, bool>)((WeaponModel weapon) => Il2CppSystemObjectExt.IsType<LineProjectileEmissionModel>((Object)(object)weapon.emission)));
				bool flag2 = Il2CppReferenceArray.Any<WeaponModel>(val4.weapons, (Func<WeaponModel, bool>)((WeaponModel weapon) => Il2CppSystemObjectExt.IsType<LineProjectileEmissionModel>((Object)(object)weapon.emission)));
				if (flag2 != flag)
				{
					return false;
				}
				if (AttackModelBehaviorExt.HasBehavior<RotateToTargetModel>(val3) != AttackModelBehaviorExt.HasBehavior<RotateToTargetModel>(val4))
				{
					return false;
				}
				DisplayModel behavior = AttackModelBehaviorExt.GetBehavior<DisplayModel>(val3);
				DisplayModel behavior2 = AttackModelBehaviorExt.GetBehavior<DisplayModel>(val4);
				if (behavior != null && behavior2 != null)
				{
					if (behavior.display != behavior2.display)
					{
						return false;
					}
				}
				else if (behavior != null || behavior2 != null)
				{
					return false;
				}
			}
			return rightModel.name == leftModel.name && ((MemberInfo)((Object)rightModel).GetIl2CppType()).Name == ((MemberInfo)((Object)leftModel).GetIl2CppType()).Name;
		}

		private static bool IsType<T>(this Type typ)
		{
			if (typeof(T).IsEnum)
			{
				return typeof(T).FullName.EndsWith(typ.FullName);
			}
			Type val = Il2CppType.From(typeof(T));
			return val.IsAssignableFrom(typ);
		}

		public static Type Type(this MemberInfo memberInfo)
		{
			if (((Object)memberInfo).GetIl2CppType().IsType<FieldInfo>())
			{
				return ((Il2CppObjectBase)memberInfo).Cast<FieldInfo>().FieldType;
			}
			if (((Object)memberInfo).GetIl2CppType().IsType<PropertyInfo>())
			{
				return ((Il2CppObjectBase)memberInfo).Cast<PropertyInfo>().PropertyType;
			}
			return null;
		}

		public static Object GetValue(this MemberInfo memberInfo, Object obj)
		{
			if (((Object)memberInfo).GetIl2CppType().IsType<FieldInfo>())
			{
				return ((Il2CppObjectBase)memberInfo).Cast<FieldInfo>().GetValue(obj);
			}
			if (((Object)memberInfo).GetIl2CppType().IsType<PropertyInfo>())
			{
				return ((Il2CppObjectBase)memberInfo).Cast<PropertyInfo>().GetValue(obj);
			}
			return null;
		}

		public static void SetValue(this MemberInfo memberInfo, Object obj, Object newValue)
		{
			if (((Object)memberInfo).GetIl2CppType().IsType<FieldInfo>())
			{
				((Il2CppObjectBase)memberInfo).Cast<FieldInfo>().SetValue(obj, newValue);
			}
			if (((Object)memberInfo).GetIl2CppType().IsType<PropertyInfo>())
			{
				((Il2CppObjectBase)memberInfo).Cast<PropertyInfo>().SetValue(obj, newValue, (Il2CppReferenceArray<Object>)null);
			}
		}
	}
	public struct MergeInfo
	{
		public TowerModel result;

		public TowerModel left;

		public TowerModel right;

		public TowerModel commonAncestor;

		public string SucessMessage => $"Successfully made {((Model)result).name} from {((Model)left).name} and {((Model)right).name}";

		public MergeInfo(TowerModel result, TowerModel left, TowerModel right, TowerModel commonAncestor)
		{
			this.result = result;
			this.left = left;
			this.right = right;
			this.commonAncestor = commonAncestor;
		}

		public void Deconstruct(out TowerModel result, out TowerModel left, out TowerModel right, out TowerModel commonAncestor)
		{
			result = this.result;
			left = this.left;
			right = this.right;
			commonAncestor = this.commonAncestor;
		}
	}
}
namespace UltimateCrosspathing.Loaders
{
	public class AlchemistLoader : ModByteLoader<TowerModel>
	{
		private const BindingFlags bindFlags = (BindingFlags)60;

		private BinaryReader br = null;

		private int mIndex = 1;

		protected override string BytesFileName => "Alchemists.bytes";

		private void LinkArray<T>() where T : Il2CppObjectBase
		{
			int num = br.ReadInt32();
			for (int i = 0; i < num; i++)
			{
				int num2 = br.ReadInt32();
				Il2CppReferenceArray<T> val = (Il2CppReferenceArray<T>)((ModByteLoader)this).m[num2];
				for (int j = 0; j < ((Il2CppArrayBase<T>)(object)val).Length; j++)
				{
					((Il2CppArrayBase<T>)(object)val)[j] = (T)((ModByteLoader)this).m[br.ReadInt32()];
				}
			}
		}

		private void LinkList<T>() where T : Il2CppObjectBase
		{
			int num = br.ReadInt32();
			for (int i = 0; i < num; i++)
			{
				int num2 = br.ReadInt32();
				List<T> val = (List<T>)((ModByteLoader)this).m[num2];
				for (int j = 0; j < val.Capacity; j++)
				{
					val.Add((T)((ModByteLoader)this).m[br.ReadInt32()]);
				}
			}
		}

		private void LinkDictionary<T>() where T : Il2CppObjectBase
		{
			int num = br.ReadInt32();
			for (int i = 0; i < num; i++)
			{
				int num2 = br.ReadInt32();
				Dictionary<string, T> val = (Dictionary<string, T>)((ModByteLoader)this).m[num2];
				int num3 = br.ReadInt32();
				for (int j = 0; j < num3; j++)
				{
					string text = br.ReadString();
					int num4 = br.ReadInt32();
					val[text] = (T)((ModByteLoader)this).m[num4];
				}
			}
		}

		private void LinkModelDictionary<T>() where T : Model
		{
			int num = br.ReadInt32();
			for (int i = 0; i < num; i++)
			{
				int num2 = br.ReadInt32();
				Dictionary<string, T> val = (Dictionary<string, T>)((ModByteLoader)this).m[num2];
				int num3 = br.ReadInt32();
				for (int j = 0; j < num3; j++)
				{
					int num4 = br.ReadInt32();
					T val2 = (T)((ModByteLoader)this).m[num4];
					val[((Model)val2).name] = val2;
				}
			}
		}

		private void LinkSerializableDictionary<T>() where T : Il2CppObjectBase
		{
			int num = br.ReadInt32();
			for (int i = 0; i < num; i++)
			{
				int num2 = br.ReadInt32();
				SerializableDictionary<string, T> val = (SerializableDictionary<string, T>)((ModByteLoader)this).m[num2];
				int num3 = br.ReadInt32();
				for (int j = 0; j < num3; j++)
				{
					string text = br.ReadString();
					int num4 = br.ReadInt32();
					val[text] = (T)((ModByteLoader)this).m[num4];
				}
			}
		}

		private void LinkModelSerializableDictionary<T>() where T : Model
		{
			int num = br.ReadInt32();
			for (int i = 0; i < num; i++)
			{
				int num2 = br.ReadInt32();
				SerializableDictionary<string, T> val = (SerializableDictionary<string, T>)((ModByteLoader)this).m[num2];
				int num3 = br.ReadInt32();
				for (int j = 0; j < num3; j++)
				{
					int num4 = br.ReadInt32();
					T val2 = (T)((ModByteLoader)this).m[num4];
					val[((Model)val2).name] = val2;
				}
			}
		}

		private void Read_a_Int32_Array()
		{
			int num = br.ReadInt32();
			int num2 = num;
			for (int i = 0; i < num2; i++)
			{
				int num3 = br.ReadInt32();
				Il2CppStructArray<int> val = new Il2CppStructArray<int>((long)num3);
				for (int j = 0; j < ((Il2CppArrayBase<int>)(object)val).Length; j++)
				{
					((Il2CppArrayBase<int>)(object)val)[j] = br.ReadInt32();
				}
				((ModByteLoader)this).m[mIndex++] = val;
			}
		}

		private void Read_a_Single_Array()
		{
			int num = br.ReadInt32();
			int num2 = num;
			for (int i = 0; i < num2; i++)
			{
				int num3 = br.ReadInt32();
				Il2CppStructArray<float> val = new Il2CppStructArray<float>((long)num3);
				for (int j = 0; j < ((Il2CppArrayBase<float>)(object)val).Length; j++)
				{
					((Il2CppArrayBase<float>)(object)val)[j] = br.ReadSingle();
				}
				((ModByteLoader)this).m[mIndex++] = val;
			}
		}

		private void Read_a_String_Array()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			int num = br.ReadInt32();
			int num2 = num;
			for (int i = 0; i < num2; i++)
			{
				int num3 = br.ReadInt32();
				Il2CppStringArray val = new Il2CppStringArray((long)num3);
				for (int j = 0; j < ((Il2CppArrayBase<string>)(object)val).Length; j++)
				{
					((Il2CppArrayBase<string>)(object)val)[j] = (br.ReadBoolean() ? null : br.ReadString());
				}
				((ModByteLoader)this).m[mIndex++] = val;
			}
		}

		private void Read_a_TargetType_Array()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			int num = br.ReadInt32();
			int num2 = num;
			for (int i = 0; i < num2; i++)
			{
				int num3 = br.ReadInt32();
				Il2CppReferenceArray<TargetType> val = new Il2CppReferenceArray<TargetType>((long)num3);
				for (int j = 0; j < ((Il2CppArrayBase<TargetType>)(object)val).Length; j++)
				{
					((Il2CppArrayBase<TargetType>)(object)val)[j] = new TargetType
					{
						id = br.ReadString(),
						isActionable = br.ReadBoolean()
					};
				}
				((ModByteLoader)this).m[mIndex++] = val;
			}
		}

		private void Read_a_AreaType_Array()
		{
			int num = br.ReadInt32();
			int num2 = num;
			for (int i = 0; i < num2; i++)
			{
				int num3 = br.ReadInt32();
				AreaType[] array = (AreaType[])(object)new AreaType[num3];
				for (int j = 0; j < array.Length; j++)
				{
					array[j] = (AreaType)br.ReadInt32();
				}
				((ModByteLoader)this).m[mIndex++] = array;
			}
		}

		private void Read_String_v_Single_Dictionary()
		{
			int num = br.ReadInt32();
			int num2 = num;
			for (int i = 0; i < num2; i++)
			{
				int num3 = br.ReadInt32();
				Dictionary<string, float> val = new Dictionary<string, float>(num3);
				for (int j = 0; j < num3; j++)
				{
					string text = (br.ReadBoolean() ? null : br.ReadString());
					float num4 = br.ReadSingle();
					val[text] = num4;
				}
				((ModByteLoader)this).m[mIndex++] = val;
			}
		}

		private void Read_String_v_String_Dictionary()
		{
			int num = br.ReadInt32();
			int num2 = num;
			for (int i = 0; i < num2; i++)
			{
				int num3 = br.ReadInt32();
				Dictionary<string, string> val = new Dictionary<string, string>(num3);
				for (int j = 0; j < num3; j++)
				{
					string text = (br.ReadBoolean() ? null : br.ReadString());
					string text2 = (br.ReadBoolean() ? null : br.ReadString());
					val[text] = text2;
				}
				((ModByteLoader)this).m[mIndex++] = val;
			}
		}

		private void CreateArraySet<T>() where T : Il2CppObjectBase
		{
			int num = br.ReadInt32();
			for (int i = 0; i < num; i++)
			{
				((ModByteLoader)this).m[mIndex++] = new Il2CppReferenceArray<T>((long)br.ReadInt32());
			}
		}

		private void CreateListSet<T>() where T : Il2CppObjectBase
		{
			int num = br.ReadInt32();
			for (int i = 0; i < num; i++)
			{
				((ModByteLoader)this).m[mIndex++] = new List<T>(br.ReadInt32());
			}
		}

		private void CreateDictionarySet<K, T>()
		{
			int num = br.ReadInt32();
			for (int i = 0; i < num; i++)
			{
				((ModByteLoader)this).m[mIndex++] = new Dictionary<K, T>(br.ReadInt32());
			}
		}

		private void CreateSerializableDictionarySet<K, T>()
		{
			int num = br.ReadInt32();
			for (int i = 0; i < num; i++)
			{
				((ModByteLoader)this).m[mIndex++] = new SerializableDictionary<K, T>(br.ReadInt32());
			}
		}

		private void Create_Records<T>() where T : Il2CppObjectBase
		{
			int num = br.ReadInt32();
			Type val = Il2CppType.Of<T>();
			for (int i = 0; i < num; i++)
			{
				((ModByteLoader)this).m[mIndex++] = ((Il2CppObjectBase)FormatterServices.GetUninitializedObject(val)).Cast<T>();
			}
		}

		private void Set_v_EntityModel_Fields(int start, int count)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			Set_v_Model_Fields(start, count);
			for (int i = 0; i < count; i++)
			{
				EntityModel val = (EntityModel)((ModByteLoader)this).m[i + start];
				val.baseId = (br.ReadBoolean() ? null : br.ReadString());
				val.display = ModContent.CreatePrefabReference(br.ReadString());
				val.behaviors = (Il2CppReferenceArray<Model>)((ModByteLoader)this).m[br.ReadInt32()];
				val.radius = br.ReadSingle();
			}
		}

		private void Set_v_Model_Fields(int start, int count)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			Type val = Il2CppType.Of<Model>();
			FieldInfo field = val.GetField("runtimeTypeIndex", (BindingFlags)60);
			FieldInfo field2 = val.GetField("isTower", (BindingFlags)60);
			FieldInfo field3 = val.GetField("childDependants", (BindingFlags)60);
			FieldInfo field4 = val.GetField("_name", (BindingFlags)60);
			for (int i = 0; i < count; i++)
			{
				Model val2 = (Model)((ModByteLoader)this).m[i + start];
				field.SetValue((Object)(object)val2, Il2CppSystemObjectExt.ToIl2Cpp(br.ReadInt32()));
				field2.SetValue((Object)(object)val2, Il2CppSystemObjectExt.ToIl2Cpp(br.ReadBoolean()));
				field3.SetValue((Object)(object)val2, (Object)(object)(List<Model>)((ModByteLoader)this).m[br.ReadInt32()]);
				field4.SetValue((Object)(object)val2, Object.op_Implicit(br.ReadBoolean() ? null : string.Intern(br.ReadString())));
			}
		}

		private void Set_v_TowerModel_Fields(int start, int count)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Expected O, but got Unknown
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Expected O, but got Unknown
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Expected O, but got Unknown
			Set_v_EntityModel_Fields(start, count);
			for (int i = 0; i < count; i++)
			{
				TowerModel val = (TowerModel)((ModByteLoader)this).m[i + start];
				val.cost = br.ReadSingle();
				val.range = br.ReadSingle();
				val.ignoreBlockers = br.ReadBoolean();
				val.isGlobalRange = br.ReadBoolean();
				val.tier = br.ReadInt32();
				val.tiers = (Il2CppStructArray<int>)((ModByteLoader)this).m[br.ReadInt32()];
				val.towerSet = (TowerSet)br.ReadInt32();
				val.towerTheme = (br.ReadBoolean() ? null : br.ReadString());
				val.icon = ModContent.CreateSpriteReference(br.ReadString());
				val.icon3D = ModContent.CreatePrefabReference(br.ReadString());
				val.portrait = ModContent.CreateSpriteReference(br.ReadString());
				val.instaIcon = ModContent.CreateSpriteReference(br.ReadString());
				val.areaTypes = Il2CppStructArray<AreaType>.op_Implicit((AreaType[])((ModByteLoader)this).m[br.ReadInt32()]);
				val.mods = (Il2CppReferenceArray<ApplyModModel>)((ModByteLoader)this).m[br.ReadInt32()];
				val.ignoreTowerForSelection = br.ReadBoolean();
				val.footprint = (FootprintModel)((ModByteLoader)this).m[br.ReadInt32()];
				val.dontDisplayUpgrades = br.ReadBoolean();
				val.emoteSpriteSmall = ModContent.CreateSpriteReference(br.ReadString());
				val.emoteSpriteLarge = ModContent.CreateSpriteReference(br.ReadString());
				val.doesntRotate = br.ReadBoolean();
				val.hideInfoButton = br.ReadBoolean();
				val.bonusSelectionRadius = br.ReadSingle();
				val.upgrades = (Il2CppReferenceArray<UpgradePathModel>)((ModByteLoader)this).m[br.ReadInt32()];
				val.appliedUpgrades = (Il2CppStringArray)((ModByteLoader)this).m[br.ReadInt32()];
				val.targetTypes = (Il2CppReferenceArray<TargetType>)((ModByteLoader)this).m[br.ReadInt32()];
				val.paragonUpgrade = (UpgradePathModel)((ModByteLoader)this).m[br.ReadInt32()];
				val.isSubTower = br.ReadBoolean();
				val.isBakable = br.ReadBoolean();
				val.powerName = (br.ReadBoolean() ? null : br.ReadString());
				val.showPowerTowerBuffs = br.ReadBoolean();
				val.animationSpeed = br.ReadSingle();
				val.towerSelectionMenuThemeId = (br.ReadBoolean() ? null : br.ReadString());
				val.secondarySelectionMenu = ModContent.CreatePrefabReference(br.ReadString());
				val.ignoreCoopAreas = br.ReadBoolean();
				val.ignoreAreaChanges = br.ReadBoolean();
				val.canAlwaysBeSold = br.ReadBoolean();
				val.blockSelling = br.ReadBoolean();
				val.isParagon = br.ReadBoolean();
				val.ignoreMaxSellPercent = br.ReadBoolean();
				val.isStunned = br.ReadBoolean();
				val.ignoreStun = br.ReadBoolean();
				val.isPrimedForRedeploy = br.ReadBoolean();
				val.geraldoItemName = (br.ReadBoolean() ? null : br.ReadString());
				val.sellbackModifierAdd = br.ReadSingle();
				val.skinName = (br.ReadBoolean() ? null : br.ReadString());
				val.dontAddMutatorsFromParent = br.ReadBoolean();
				val.showBuffs = br.ReadBoolean();
				val.destroyTowerOnRedistribution = br.ReadBoolean();
				val.displayScale = br.ReadSingle();
				val.useAirUnitHeight = br.ReadBoolean();
				val.isTransformedTower = br.ReadBoolean();
				val.cantBeStunned = br.ReadBoolean();
				val.frontierId = br.ReadInt32();
			}
		}

		private void Set_v_ApplyModModel_Fields(int start, int count)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			Set_v_Model_Fields(start, count);
			for (int i = 0; i < count; i++)
			{
				ApplyModModel val = (ApplyModModel)((ModByteLoader)this).m[i + start];
				val.mod = (br.ReadBoolean() ? null : br.ReadString());
				val.target = (br.ReadBoolean() ? null : br.ReadString());
			}
		}

		private void Set_v_FootprintModel_Fields(int start, int count)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			Set_v_TowerBehaviorModel_Fields(start, count);
			for (int i = 0; i < count; i++)
			{
				FootprintModel val = (FootprintModel)((ModByteLoader)this).m[i + start];
				val.doesntBlockTowerPlacement = br.ReadBoolean();
				val.ignoresPlacementCheck = br.ReadBoolean();
				val.ignoresTowerOverlap = br.ReadBoolean();
			}
		}

		private void Set_v_TowerBehaviorModel_Fields(int start, int count)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			Set_v_EntityBehaviorModel_Fields(start, count);
			for (int i = 0; i < count; i++)
			{
				TowerBehaviorModel val = (TowerBehaviorModel)((ModByteLoader)this).m[i + start];
			}
		}

		private void Set_v_EntityBehaviorModel_Fields(int start, int count)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			Set_v_Model_Fields(start, count);
			for (int i = 0; i < count; i++)
			{
				EntityBehaviorModel val = (EntityBehaviorModel)((ModByteLoader)this).m[i + start];
			}
		}

		private void Set_v_CircleFootprintModel_Fields(int start, int count)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			Set_v_FootprintModel_Fields(start, count);
			for (int i = 0; i < count; i++)
			{
				CircleFootprintModel val = (CircleFootprintModel)((ModByteLoader)this).m[i + start];
				val.radius = br.ReadSingle();
			}
		}

		private void Set_v_UpgradePathModel_Fields(int start, int count)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			Set_v_Model_Fields(start, count);
			for (int i = 0; i < count; i++)
			{
				UpgradePathModel val = (UpgradePathModel)((ModByteLoader)this).m[i + start];
				val.tower = (br.ReadBoolean() ? null : br.ReadString());
				val.upgrade = (br.ReadBoolean() ? null : br.ReadString());
			}
		}

		private void Set_v_CreateEffectOnPlaceModel_Fields(int start, int count)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			Set_v_TowerBehaviorModel_Fields(start, count);
			for (int i = 0; i < count; i++)
			{
				CreateEffectOnPlaceModel val = (CreateEffectOnPlaceModel)((ModByteLoader)this).m[i + start];
				val.effectModel = (EffectModel)((ModByteLoader)this).m[br.ReadInt32()];
			}
		}

		private void Set_v_EffectModel_Fields(int start, int count)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			Set_v_Model_Fields(start, count);
			for (int i = 0; i < count; i++)
			{
				EffectModel val = (EffectModel)((ModByteLoader)this).m[i + start];
				val.assetId = ModContent.CreatePrefabReference(br.ReadString());
				val.scale = br.ReadSingle();
				val.lifespan = br.ReadSingle();
				val.fullscreen = (Fullscreen)br.ReadInt32();
				val.useCenterPosition = br.ReadBoolean();
				val.useTransformPosition = br.ReadBoolean();
				val.useTransfromRotation = br.ReadBoolean();
				val.destroyOnTransformDestroy = br.ReadBoolean();
				val.alwaysUseAge = br.ReadBoolean();
				val.useRoundTime = br.ReadBoolean();
			}
		}

		private void Set_v_TowerBehaviorBuffModel_Fields(int start, int count)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			Set_v_TowerBehaviorModel_Fields(start, count);
			for (int i = 0; i < count; i++)
			{
				TowerBehaviorBuffModel val = (TowerBehaviorBuffModel)((ModByteLoader)this).m[i + start];
				val.buffLocsName = (br.ReadBoolean() ? null : br.ReadString());
				val.buffIconName = (br.ReadBoolean() ? null : br.ReadString());
				val.maxStackSize = br.ReadInt32();
				val.isGlobalRange = br.ReadBoolean();
			}
		}

		private void Set_v_CanBuffIndicatorModel_Fields(int start, int count)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			Set_v_TowerBehaviorBuffModel_Fields(start, count);
			for (int i = 0; i < count; i++)
			{
				CanBuffIndicatorModel val = (CanBuffIndicatorModel)((ModByteLoader)this).m[i + start];
				val.isDisabled = br.ReadBoolean();
			}
		}

		private void Set_v_BuffIndicatorModel_Fields(int start, int count)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			Set_v_TowerBehaviorModel_Fields(start, count);
			for (int i = 0; i < count; i++)
			{
				BuffIndicatorModel val = (BuffIndicatorModel)((ModByteLoader)this).m[i + start];
				val.buffName = (br.ReadBoolean() ? null : br.ReadString());
				val.iconName = (br.ReadBoolean() ? null : br.ReadString());
				val.stackable = br.ReadBoolean();
				val.maxStackSize = br.ReadInt32();
				val.globalRange = br.ReadBoolean();
				val.onlyShowBuffIfMutated = br.ReadBoolean();
				val.dontShowX = br.ReadBoolean();
			}
		}

		private void Set_v_CreateSoundOnSellModel_Fields(int start, int count)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			Set_v_TowerBehaviorModel_Fields(start, count);
			for (int i = 0; i < count; i++)
			{
				CreateSoundOnSellModel val = (CreateSoundOnSellModel)((ModByteLoader)this).m[i + start];
				val.sound = (SoundModel)((ModByteLoader)this).m[br.ReadInt32()];
			}
		}

		private void Set_v_SoundModel_Fields(int start, int count)
		{
			//IL_0019: Unknown result type (might be du