using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BTD_Mod_Helper; using BTD_Mod_Helper.Api; using BTD_Mod_Helper.Api.Data; using BTD_Mod_Helper.Api.ModOptions; using BTD_Mod_Helper.Extensions; using HarmonyLib; using Il2CppAssets.Scripts.Models; using Il2CppAssets.Scripts.Models.Entities; using Il2CppAssets.Scripts.Models.Powers; using Il2CppAssets.Scripts.Models.TowerSets; using Il2CppAssets.Scripts.Models.Towers; using Il2CppAssets.Scripts.Models.Towers.Behaviors; using Il2CppAssets.Scripts.Models.Towers.Weapons.Behaviors; using Il2CppAssets.Scripts.Simulation.Input; using Il2CppAssets.Scripts.Simulation.Objects; using Il2CppAssets.Scripts.Simulation.Towers; using Il2CppAssets.Scripts.Simulation.Towers.Behaviors; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem.Collections.Generic; using MelonLoader; using Microsoft.CodeAnalysis; using Unlimited5thTiers; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonInfo(typeof(Unlimited5thTiersMod), "Unlimited 5th Tiers +", "1.1.12", "doombubbles", null)] [assembly: MelonGame("Ninja Kiwi", "BloonsTD6")] [assembly: MelonGame("Ninja Kiwi", "BloonsTD6-Epic")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("Unlimited5thTiers")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+507c0f5e444f3891b69ca7b10a2b936d1c8c6ec8")] [assembly: AssemblyProduct("Unlimited5thTiers")] [assembly: AssemblyTitle("Unlimited5thTiers")] [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 Unlimited5thTiers { public static class ModHelperData { public const string WorksOnVersion = "55.0"; public const string Version = "1.1.12"; public const string Name = "Unlimited 5th Tiers +"; public const string Description = "- Unlimited amount of the same 5th tier tower allowed\r\n- Unlimited amount of the same Paragon tower allowed\r\n- Unlimited amount of Vengeful True Sun Gods allowed\r\n- Unlimited amount of the same hero (+ using all heroes at once)\r\n- All of the above naturally usable in Sandbox mode\r\n- True Sun Gods can still become Vengeful even if not fully sacrificed\r\n- 1/1/1/1 and 2/2/2/2 Sacrifices are allowed"; public const string RepoOwner = "doombubbles"; public const string PrevRepoName = "unlimited-5th-tiers"; public const string RepoName = "Unlimited5thTiers"; } public class Settings : ModSettings { public static readonly ModSettingBool AllowUnlimited5thTiers = new ModSettingBool(true) { displayName = "Allow Unlimited 5th Tier Towers", icon = ModContent.GetTextureGUID("Icon") }; public static readonly ModSettingBool AllowUnlimited3rdTierPowersPro = new ModSettingBool(true) { displayName = "Allow Unlimited 3rd Tier Powers Pro", icon = "6cfd927d475bb0e4dad72760c2f66a32" }; public static readonly ModSettingBool AllowUnlimitedParagons = new ModSettingBool(true) { displayName = "Allow Unlimited Paragons", icon = "56a54befdd6fa422d87006ca40840131" }; public static readonly ModSettingBool AllowUnlimitedVTSGs = new ModSettingBool(true) { displayName = "Allow Unlimited VTSGs", icon = "afd7922791d61014ca6d601526f94c1e" }; public static readonly ModSettingBool AllowNonMaxedVTSGs = new ModSettingBool(true) { displayName = "Allow Non Maxed VTSGs", icon = "afd7922791d61014ca6d601526f94c1e" }; public static readonly ModSettingBool AllowUnlimitedHeroes = new ModSettingBool(false) { displayName = "Allow Unlimited Heroes", icon = "a94e04831943e4837a4712123f032bb9" }; public static readonly ModSettingBool ShowAllHeroesInGame = new ModSettingBool(false) { displayName = "Show All Heroes in Game", icon = "a94e04831943e4837a4712123f032bb9" }; } public class Unlimited5thTiersMod : BloonsTD6Mod { [HarmonyPatch(typeof(TowerInventory), "SetTowerTierRestrictions")] internal static class TowerInventory_SetTowerTierRestrictions { [HarmonyPostfix] private static void Postfix(TowerInventory __instance, IEnumerable towers) { if (!ModSettingBool.op_Implicit(Settings.AllowUnlimited5thTiers)) { return; } Il2CppGenericIEnumerable.ForEach(towers, (Action)delegate(TowerDetailsModel towerDetails) { if (Il2CppSystemObjectExt.Is((Il2CppObjectBase)(object)towerDetails)) { for (int i = 0; i < 3; i++) { __instance.AddTierRestriction(towerDetails.towerId, i, 5, 9999999); } } }); } } [HarmonyPatch(typeof(TowerInventory), "SetPowersProTierMaxes")] internal static class TowerInventory_SetPowersProTierMaxes { [HarmonyPostfix] internal static void Postfix(TowerInventory __instance, GameModel model) { if (!ModSettingBool.op_Implicit(Settings.AllowUnlimited3rdTierPowersPro)) { return; } foreach (PowerProModel item in (Il2CppArrayBase)(object)model.powersPro) { for (int i = 0; i < 3; i++) { __instance.AddTierRestriction(((EntityModel)((PowerModel)item).tower).baseId, i, 3, 9999999); } } } } [HarmonyPatch(typeof(TowerInventory), "SetTowerMaxes")] internal static class TowerInventory_SetTowerMaxes { [HarmonyPrefix] internal static void Prefix(IEnumerable towers) { Il2CppGenericIEnumerable.ForEach(towers, (Action)delegate(TowerDetailsModel towerDetails) { HeroDetailsModel val = default(HeroDetailsModel); if (Il2CppSystemObjectExt.Is((Il2CppObjectBase)(object)towerDetails, ref val)) { if (ModSettingBool.op_Implicit(Settings.ShowAllHeroesInGame) && ((TowerDetailsModel)val).towerCount == 0) { ((TowerDetailsModel)val).towerCount = 1; } if (ModSettingBool.op_Implicit(Settings.AllowUnlimitedHeroes) && ((TowerDetailsModel)val).towerCount != 0) { ((TowerDetailsModel)val).towerCount = -1; } } }); } } [HarmonyPatch(typeof(MonkeyTemple), "StartSacrifice")] public class MonkeyTemple_StartSacrifice { [HarmonyPostfix] public static void Postfix(MonkeyTemple __instance) { if (ModSettingBool.op_Implicit(Settings.AllowNonMaxedVTSGs) && __instance.monkeyTempleModel.checkForThereCanOnlyBeOne && !__instance.checkTCBOO) { __instance.checkTCBOO = true; } } } [HarmonyPatch(typeof(MonkeyTemple), "CheckTCBOO")] internal class MonkeyTemple_CheckTCBOO { [HarmonyPrefix] internal static bool Prefix(MonkeyTemple __instance) { if (ModSettingBool.op_Implicit(Settings.AllowUnlimitedVTSGs) && __instance.checkTCBOO && __instance.monkeyTempleModel.weaponDelayFrames + __instance.lastSacrificed <= ((RootObject)__instance).Sim.time.elapsed && __instance.monkeyTempleModel.checkForThereCanOnlyBeOne && __instance.lastSacrificed != ((RootObject)__instance).Sim.time.elapsed) { List source = (from tower in Il2CppGenericIEnumerableExt.ToList(((RootObject)__instance).Sim.towerManager.GetTowersByBaseId(TowerType.SuperMonkey)) where ((RootObject)tower).Id != ((RootObject)((TowerBehavior)__instance).tower).Id select tower).ToList(); Tower val = ((IEnumerable)source).FirstOrDefault((Func)((Tower tower) => ((Il2CppArrayBase)(object)tower.towerModel.tiers)[1] == 5)); Tower val2 = ((IEnumerable)source).FirstOrDefault((Func)((Tower tower) => ((Il2CppArrayBase)(object)tower.towerModel.tiers)[2] == 5)); if (val2 != null && val != null) { __instance.SacrificeBatmanAndRoboCop(val, val2); } __instance.checkTCBOO = false; return false; } return true; } } [HarmonyPatch(typeof(Tower), "CanUpgradeToParagon")] internal class Tower_CanUpgradeToParagon { [HarmonyPostfix] internal static void Postfix(Tower __instance, ref bool __result) { if (((RootObject)__instance).Sim.towerManager.IsParagonLocked(__instance, __instance.owner) || __instance.towerModel.paragonUpgrade == null || !ModSettingBool.op_Implicit(Settings.AllowUnlimitedParagons)) { return; } List source = Il2CppGenericIEnumerableExt.ToList(((RootObject)__instance).Sim.towerManager.GetTowersByBaseId(((EntityModel)__instance.towerModel).baseId)); int i; for (i = 0; i < 3; i++) { if (source.All((Tower tower) => ((Il2CppArrayBase)(object)tower.towerModel.tiers)[i] != 5)) { return; } } __result = true; } } [HarmonyPatch(typeof(Tower), "HasReachedParagonLimit")] internal static class Tower_HasParagonLimitBeenReached { [HarmonyPrefix] private static bool Prefix(ref bool __result) { if (ModSettingBool.op_Implicit(Settings.AllowUnlimitedParagons)) { __result = false; return false; } return true; } } [HarmonyPatch] internal static class TowerInventory_HasInventory { private static IEnumerable TargetMethods() { yield return AccessTools.Method(typeof(TowerInventory), "HasInventory", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(TowerInventory), "HasUpgradeInventory", (Type[])null, (Type[])null); } [HarmonyPostfix] internal static void Postfix(TowerModel def, ref bool __result) { if (ModSettingBool.op_Implicit(Settings.AllowUnlimitedParagons) && def.isParagon) { __result = true; } } } public override void OnNewGameModel(GameModel gameModel) { foreach (TowerModel item in Il2CppGenericIEnumerable.AsIEnumerable(gameModel.GetTowersWithBaseId(TowerType.SuperMonkey, false))) { MonkeyTempleModel descendant = ((Model)item).GetDescendant(); if (descendant != null && descendant.towerGroupCount < 4) { descendant.towerGroupCount = 4; } } foreach (TowerModel item2 in ((IEnumerable)gameModel.towers).Where((TowerModel model) => model.tier >= 5)) { Il2CppGenericIEnumerable.ForEach(((Model)item2).GetDescendants(), (Action)delegate(LimitProjectileModel model) { model.globalForPlayer = false; }); } } } }