using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BTD_Mod_Helper;
using BTD_Mod_Helper.Api;
using BTD_Mod_Helper.Api.Components;
using BTD_Mod_Helper.Api.Data;
using BTD_Mod_Helper.Api.ModOptions;
using BTD_Mod_Helper.Api.Towers;
using BTD_Mod_Helper.Extensions;
using HarmonyLib;
using Il2Cpp;
using Il2CppAssets.Scripts;
using Il2CppAssets.Scripts.Models;
using Il2CppAssets.Scripts.Models.Bloons;
using Il2CppAssets.Scripts.Models.Bloons.Behaviors;
using Il2CppAssets.Scripts.Models.Entities;
using Il2CppAssets.Scripts.Models.GenericBehaviors;
using Il2CppAssets.Scripts.Models.Profile;
using Il2CppAssets.Scripts.Models.SimulationBehaviors;
using Il2CppAssets.Scripts.Models.TowerSets;
using Il2CppAssets.Scripts.Models.Towers;
using Il2CppAssets.Scripts.Models.Towers.Behaviors;
using Il2CppAssets.Scripts.Models.Towers.Behaviors.Abilities;
using Il2CppAssets.Scripts.Models.Towers.Behaviors.Abilities.Behaviors;
using Il2CppAssets.Scripts.Models.Towers.Behaviors.Attack;
using Il2CppAssets.Scripts.Models.Towers.Behaviors.Attack.Behaviors;
using Il2CppAssets.Scripts.Models.Towers.Projectiles.Behaviors;
using Il2CppAssets.Scripts.Models.Towers.TowerFilters;
using Il2CppAssets.Scripts.Models.Towers.Weapons;
using Il2CppAssets.Scripts.Models.Towers.Weapons.Behaviors;
using Il2CppAssets.Scripts.Simulation;
using Il2CppAssets.Scripts.Simulation.Behaviors;
using Il2CppAssets.Scripts.Simulation.Bloons;
using Il2CppAssets.Scripts.Simulation.Objects;
using Il2CppAssets.Scripts.Simulation.SMath;
using Il2CppAssets.Scripts.Simulation.SimulationBehaviors;
using Il2CppAssets.Scripts.Simulation.Towers;
using Il2CppAssets.Scripts.Simulation.Towers.Behaviors;
using Il2CppAssets.Scripts.Simulation.Towers.Behaviors.Abilities;
using Il2CppAssets.Scripts.Simulation.Towers.Behaviors.Abilities.Behaviors;
using Il2CppAssets.Scripts.Simulation.Towers.Behaviors.Attack;
using Il2CppAssets.Scripts.Simulation.Towers.Behaviors.Attack.Behaviors;
using Il2CppAssets.Scripts.Simulation.Towers.TowerFilters;
using Il2CppAssets.Scripts.Simulation.Towers.Weapons;
using Il2CppAssets.Scripts.Simulation.Track;
using Il2CppAssets.Scripts.Unity.Bridge;
using Il2CppAssets.Scripts.Unity.UI_New.InGame;
using Il2CppAssets.Scripts.Unity.UI_New.InGame.TowerSelectionMenu;
using Il2CppAssets.Scripts.Unity.UI_New.InGame.TowerSelectionMenu.TowerSelectionMenuThemes;
using Il2CppAssets.Scripts.Unity.UI_New.Popups;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppNinjaKiwi.Common.ResourceUtils;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.IO;
using Il2CppSystem.Linq;
using MelonLoader;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using TacticalTweaks;
using UnityEngine;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(TacticalTweaksMod), "Tactical Tweaks", "1.2.2", "doombubbles", null)]
[assembly: MelonGame("Ninja Kiwi", "BloonsTD6")]
[assembly: MelonGame("Ninja Kiwi", "BloonsTD6-Epic")]
[assembly: HarmonyDontPatchAll]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("TacticalTweaks")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+ba6e6d2aef38cecefb394242dfbd4478c24a70de")]
[assembly: AssemblyProduct("TacticalTweaks")]
[assembly: AssemblyTitle("TacticalTweaks")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace TacticalTweaks
{
public static class ModHelperData
{
public const string WorksOnVersion = "55.3";
public const string Version = "1.2.2";
public const string Name = "Tactical Tweaks";
public const string Description = "Adds an assortment of minor gameplay altering tweaks to BTD6, including **Buffable Paragons**!. See the Main Readme for full details.\r\n\r\nNew: Beast Handler Lone T5s, Brickell Mermonkeys, Elite Defender Target Switch, Etienne Targeting, Sticky Bomb Attack Speed, Better Laser Blasts, Better Trojan, Better Monkey City, Better Central Market, Auto Collect/Deposit Banks, Obyn Price Tweak, More Overclock Interactions, More Unfreezable Towers\r\nFormerly Useful Utilities: Dartling/Mortary/Sentry Targeting, Auto Trap Refresh\r\nOld Mods: Better Armor Piercing, Better Ezili Totem";
public const string RepoOwner = "doombubbles";
public const string PrevRepoName = "tactical-tweaks";
public const string RepoName = "TacticalTweaks";
}
public abstract class TacticalTweak : NamedModContent, IModSettings, IModContent
{
protected virtual bool CreateCategory => false;
protected virtual string Icon => ((ModContent)this).TextureExists(((ModContent)this).Name) ? ((ModContent)this).GetTextureGUID(((ModContent)this).Name) : null;
protected virtual string DisableIfModPresent => ((ModContent)this).Name;
protected static Instance MelonLogger => ((MelonBase)ModContent.GetInstance<TacticalTweaksMod>()).LoggerInstance;
public sealed override IEnumerable<ModContent> Load()
{
if (!ModHelper.HasMod(DisableIfModPresent))
{
Type[] nestedTypes = ((object)this).GetType().GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic);
foreach (Type nestedType in nestedTypes)
{
((ModContent)this).mod.ApplyHarmonyPatches(nestedType);
}
OnLoad();
yield return (ModContent)(object)this;
}
}
public sealed override void Register()
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Expected O, but got Unknown
TacticalTweaksMod.TacticalTweaks[((ModContent)this).Name] = this;
if (CreateCategory)
{
ModSettingCategory category = new ModSettingCategory(((NamedModContent)this).DisplayName)
{
icon = Icon,
collapsed = true
};
foreach (ModSetting item in ((ModContent)this).mod.ModSettings.Values.Where((ModSetting setting) => (object)setting.source == this))
{
item.category = category;
}
}
OnRegister();
}
public virtual void OnLoad()
{
}
public virtual void OnRegister()
{
}
public virtual void OnSaveSettings()
{
}
public virtual void OnUpdate()
{
}
public virtual void OnGameObjectsReset()
{
}
public virtual void OnNewGameModel(GameModel gameModel)
{
}
public virtual void OnTowerSaved(Tower tower, TowerSaveDataModel saveData)
{
}
public virtual void OnTowerLoaded(Tower tower, TowerSaveDataModel saveData)
{
}
}
public class TacticalTweaksMod : BloonsTD6Mod
{
public static readonly Dictionary<string, TacticalTweak> TacticalTweaks = new Dictionary<string, TacticalTweak>();
public static readonly ModSettingCategory Overclock = new ModSettingCategory("Overclock")
{
icon = "c101127fbd522584dbcce02cdb22afdb",
order = 1
};
public static readonly ModSettingCategory Targeting = new ModSettingCategory("Targeting")
{
icon = "IngameUi[CamoTargetIconCross]",
order = 2
};
public static readonly ModSettingBool DefaultToNewTargeting = new ModSettingBool(true)
{
description = "Whether to default to the new targeting options, aka setting these towers to be First by default",
category = Targeting
};
public static MelonPreferences_Category Preferences { get; private set; } = null;
public override void OnApplicationStart()
{
Preferences = MelonPreferences.CreateCategory("TacticalTweaksPreferences");
CollectionExtensions.Do<Type>(from type in AccessTools.GetTypesFromAssembly(((MelonBase)this).MelonAssembly.Assembly)
where !type.IsNested
select type, (Action<Type>)((BloonsMod)this).ApplyHarmonyPatches);
}
public static void AddAllTargets(AttackModel attackModel)
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Expected O, but got Unknown
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Expected O, but got Unknown
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Expected O, but got Unknown
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Expected O, but got Unknown
List<TargetSupplierModel> list = AttackModelBehaviorExt.GetBehaviors<TargetSupplierModel>(attackModel).ToList();
AttackModelBehaviorExt.AddBehavior<TargetFirstModel>(attackModel, CreateTargetFirstModelExt.Create(new Args
{
isSelectable = true
}));
AttackModelBehaviorExt.AddBehavior<TargetLastModel>(attackModel, CreateTargetLastModelExt.Create(new Args
{
isSelectable = true
}));
AttackModelBehaviorExt.AddBehavior<TargetCloseModel>(attackModel, CreateTargetCloseModelExt.Create(new Args
{
isSelectable = true
}));
AttackModelBehaviorExt.AddBehavior<TargetStrongModel>(attackModel, CreateTargetStrongModelExt.Create(new Args
{
isSelectable = true
}));
if (!ModSettingBool.op_Implicit(DefaultToNewTargeting))
{
return;
}
foreach (TargetSupplierModel item in list)
{
AttackModelBehaviorExt.RemoveBehavior<TargetSupplierModel>(attackModel, item);
AttackModelBehaviorExt.AddBehavior<TargetSupplierModel>(attackModel, item);
}
}
public static void UpdatePointer(AttackModel attackModel, bool? rotateTower = null)
{
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Expected O, but got Unknown
RotateToPointerModel behavior = AttackModelBehaviorExt.GetBehavior<RotateToPointerModel>(attackModel);
AttackModelBehaviorExt.AddBehavior<RotateToTargetModel>(attackModel, CreateRotateToTargetModelExt.Create(new Args
{
rotateOnlyOnThrow = behavior.rotateOnlyOnEmit,
rotateTower = (rotateTower ?? behavior.rotateTower)
}));
LineEffectModel val = default(LineEffectModel);
if (ModelExt.HasDescendant<LineEffectModel>((Model)(object)attackModel, ref val))
{
val.useRotateToPointer = false;
}
}
public override void OnSaveSettings(JObject settings)
{
foreach (TacticalTweak value in TacticalTweaks.Values)
{
value.OnSaveSettings();
}
}
public override void OnUpdate()
{
foreach (TacticalTweak value in TacticalTweaks.Values)
{
value.OnUpdate();
}
}
public override void OnGameObjectsReset()
{
foreach (TacticalTweak value in TacticalTweaks.Values)
{
value.OnGameObjectsReset();
}
}
public override void OnNewGameModel(GameModel gameModel)
{
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Expected O, but got Unknown
foreach (TacticalTweak value in TacticalTweaks.Values)
{
value.OnNewGameModel(gameModel);
}
TowerModel heroWithNameAndLevel = gameModel.GetHeroWithNameAndLevel(TowerType.StrikerJones, 20, false);
if (heroWithNameAndLevel != null)
{
TowerModelBehaviorExt.AddBehavior<SupportRemoveFilterOutTagModel>(heroWithNameAndLevel, CreateSupportRemoveFilterOutTagModelExt.Create(new Args
{
mutatorId = "Striker:DdtDamageModifier",
removeScriptWithSupportMutatorId = "Striker:Level9BlackBuff",
isGlobal = true
}));
}
}
public override void OnTowerSaved(Tower tower, TowerSaveDataModel saveData)
{
foreach (TacticalTweak value in TacticalTweaks.Values)
{
value.OnTowerSaved(tower, saveData);
}
}
public override void OnTowerLoaded(Tower tower, TowerSaveDataModel saveData)
{
foreach (TacticalTweak value in TacticalTweaks.Values)
{
value.OnTowerLoaded(tower, saveData);
}
}
}
public abstract class ToggleableTweak : TacticalTweak
{
private ModSettingBool setting = null;
protected abstract bool DefaultEnabled { get; }
public bool Enabled => ModSettingBool.op_Implicit(setting);
public abstract override string Description { get; }
protected virtual ModSettingCategory Category => null;
public override void OnLoad()
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Expected O, but got Unknown
//IL_005c: Expected O, but got Unknown
Dictionary<string, ModSetting> modSettings = ((ModContent)this).mod.ModSettings;
string name = ((ModContent)this).Name;
ModSettingBool val = new ModSettingBool(DefaultEnabled)
{
displayName = ((NamedModContent)this).DisplayName,
icon = Icon,
category = Category,
description = ((NamedModContent)this).Description,
source = (IModSettings)(object)this
};
ModSettingBool value = val;
setting = val;
modSettings[name] = (ModSetting)(object)value;
}
}
}
namespace TacticalTweaks.Tweaks
{
public class AutoBloonTrapRetarget : TacticalTweak
{
private enum TrapRetargetSetting
{
Off,
StartOfRound,
Constantly
}
[HarmonyPatch(typeof(Simulation), "RoundStart")]
internal static class Simulation_RoundStart
{
[HarmonyPostfix]
internal static void Postfix(Simulation __instance)
{
if (ModSettingEnum<TrapRetargetSetting>.op_Implicit(AutoTrapRetarget) != TrapRetargetSetting.StartOfRound)
{
return;
}
Il2CppGenericIEnumerable.ForEach<TargetSelectedPoint>(__instance.factory.GetUncast<TargetSelectedPoint>(), (Action<TargetSelectedPoint>)delegate(TargetSelectedPoint point)
{
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
if (((RootBehavior)((AttackBehavior)point).attack).model.name.Contains("BloonTrap") && point.HasValidPoint)
{
Vector3 targetPoint = point.targetPoint;
((TargetSupplier)point).ApplyTargetTypeData(((Vector3)(ref targetPoint)).ToVector2());
}
});
}
}
[HarmonyPatch(typeof(Weapon), "Process")]
internal static class Weapon_Process
{
[HarmonyPostfix]
internal static void Postfix(Weapon __instance)
{
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
TargetSelectedPoint val = default(TargetSelectedPoint);
if (ModSettingEnum<TrapRetargetSetting>.op_Implicit(AutoTrapRetarget) == TrapRetargetSetting.Constantly && ((RootBehavior)((AttackBehavior)__instance).attack).model.name.Contains("BloonTrap") && Il2CppSystemObjectExt.Is<TargetSelectedPoint>((Il2CppObjectBase)(object)((AttackBehavior)__instance).attack.activeTargetSupplier, ref val) && __instance.IsReloadReady && val.HasValidPoint)
{
TargetSelectedPoint obj = val;
Vector3 targetPoint = val.targetPoint;
((TargetSupplier)obj).ApplyTargetTypeData(((Vector3)(ref targetPoint)).ToVector2());
}
}
}
private static readonly ModSettingEnum<TrapRetargetSetting> AutoTrapRetarget = new ModSettingEnum<TrapRetargetSetting>(TrapRetargetSetting.Off)
{
icon = "dc5d21f63f63bff40a8798a2b666a5aa",
description = "For Engineers with with Bloon Trap and Larger Service Area, traps will now be automatically retargeted on the same spot to refresh them."
};
}
public class AutoCollectBanks : ToggleableTweak
{
protected override bool DefaultEnabled => false;
public override string Description => "All Banks will auto collect when full like the XX2 Banks do.";
protected override string Icon => "01a32a1a35c684d6a8d137b62d3a7f1b";
public override void OnNewGameModel(GameModel gameModel)
{
BankModel val = default(BankModel);
foreach (TowerModel item in Il2CppGenericIEnumerable.AsIEnumerable<TowerModel>(gameModel.GetTowersWithBaseId(TowerType.BananaFarm, false)))
{
if (TowerModelBehaviorExt.HasBehavior<BankModel>(item, ref val))
{
val.autoCollect = true;
}
}
}
}
public class AutoDepositBanks : ToggleableTweak
{
[HarmonyPatch(typeof(Bank), "Collect")]
internal static class Bank_Collect
{
[HarmonyPrefix]
internal static void Prefix(Bank __instance, ref float __state)
{
__state = __instance.cash;
}
[HarmonyPostfix]
internal static void Postfix(Bank __instance, float __state)
{
if (ModContent.GetInstance<AutoDepositBanks>().Enabled && TowerModelBehaviorExt.HasBehavior<BankDepositsModel>(((TowerBehavior)__instance).tower.towerModel) && !(__state < __instance.bankModel.capacity))
{
((RootObject)__instance).Sim.RemoveCash((double)(__state / 2f), (CashType)2, InGame.Bridge.MyPlayerNumber, (CashSource)6);
__instance.DepositCash(__state / 2f);
}
}
}
protected override bool DefaultEnabled => false;
public override string Description => "When making a full collection from a Monkey Bank that has Deposits enabled, half of the amount collected will be automatically deposited back.";
protected override string Icon => "1728a8a7ee4434f589617ff0d2672b9c";
}
public class BeastHandlerLoneT5s : ToggleableTweak
{
[HarmonyPatch(typeof(ContributionMutator), "Mutate")]
internal static class ContributionMutator_Mutate
{
[HarmonyPostfix]
internal static void Postfix(ContributionMutator __instance, Model model)
{
TowerModel val = default(TowerModel);
if (ModContent.GetInstance<BeastHandlerLoneT5s>().Enabled && __instance.towerBaseId == TowerType.Piranha && Il2CppSystemObjectExt.Is<TowerModel>((Il2CppObjectBase)(object)model, ref val) && val.tier >= 5 && __instance.power < 84)
{
((Model)model.GetDescendant<TowerModel>()).GetDescendant<CreateGreatWhiteEffectModel>().maxGrabBloonName = "Zomg";
}
}
}
private class T5Description : ModTextOverride
{
private string Upgrade { get; init; } = null;
public override string Name => Upgrade;
public override string LocalizationKey => Upgrade + " Description";
public override bool Active => ModContent.GetInstance<BeastHandlerLoneT5s>().Enabled;
public override string TextValue => StringExt.RegexReplace(((ModTextOverride)this).OriginalText, " Requires.*$", "");
public override IEnumerable<ModContent> Load()
{
yield return (ModContent)(object)new T5Description
{
Upgrade = "Megalodon"
};
yield return (ModContent)(object)new T5Description
{
Upgrade = "Giganotosaurus"
};
yield return (ModContent)(object)new T5Description
{
Upgrade = "Pouakai"
};
}
}
public override string DisplayName => "Beast Handler Lone T5s";
protected override bool DefaultEnabled => false;
public override string Description => "Allows Tier 5 Beast Handlers to be purchased even without any other Beast Handlers contributing to them.\r\nMegalodon still requires 84 Beast Power to insta kill BAD Bloons.";
protected override string Icon => "MonkeyIcons[BeastHandlerIcon]";
public override void OnNewGameModel(GameModel gameModel)
{
if (!base.Enabled)
{
return;
}
foreach (BeastHandlerPetModel item in ((IEnumerable<TowerModel>)MonoLinqHelper.ToArray<TowerModel>(gameModel.GetTowersWithBaseId(TowerType.BeastHandler, false))).SelectMany((TowerModel model) => (IEnumerable<TowerModel>)MonoLinqHelper.ToArray<TowerModel>(((Model)model).GetDescendants<TowerModel>())).SelectMany((TowerModel model) => (IEnumerable<BeastHandlerPetModel>)MonoLinqHelper.ToArray<BeastHandlerPetModel>(((Model)model).GetDescendants<BeastHandlerPetModel>())))
{
item.requiredCount = 0;
}
}
}
public class BetterArmorPiercingDarts : ToggleableTweak
{
protected override bool DefaultEnabled => false;
public override string Description => "Makes Monkey Subs with the Armor Piercing Darts upgrade to be able to pop Lead Bloons";
protected override string Icon => "89a459fa46fc4c6419f64888fb30cfa7";
public override void OnNewGameModel(GameModel gameModel)
{
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
foreach (TowerModel item in from model in Il2CppGenericIEnumerable.AsIEnumerable<TowerModel>(gameModel.GetTowersWithBaseId(TowerType.MonkeySub, false))
where ((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("Armor Piercing Darts")
select model)
{
DamageModel damageModel = ProjectileModelExt.GetDamageModel(TowerModelExt.GetWeapon(item).projectile);
damageModel.immuneBloonProperties = (BloonProperties)(damageModel.immuneBloonProperties & -2);
damageModel.immuneBloonPropertiesOriginal = (BloonProperties)(damageModel.immuneBloonPropertiesOriginal & -2);
}
}
}
public class BetterCentralMarket : ToggleableTweak
{
[HarmonyPatch(typeof(CentralMarketBuff), "TestTower")]
internal static class CentralMarketBuff_TestTower
{
[HarmonyPrefix]
internal static bool Prefix(CentralMarketBuff __instance, Tower testTower)
{
if (!ModContent.GetInstance<BetterCentralMarket>().Enabled)
{
return true;
}
TowerModel val = default(TowerModel);
if (testTower == ((TowerBehavior)__instance).tower || !Il2CppSystemObjectExt.Is<TowerModel>(testTower.towerModel, ref val) || val.CheckSet((TowerSet)8, false))
{
return false;
}
testTower.RemoveMutatorIncludeSubTowers((BehaviorMutator)(object)__instance.mutator);
testTower.AddMutatorIncludeSubTowers((BehaviorMutator)(object)__instance.mutator, -1, true, true, false, true, -1);
return false;
}
}
[HarmonyPatch(typeof(CentralMarketBuff), "Attatched")]
internal static class CentralMarketBuff_Attatched
{
[HarmonyPrefix]
internal static void Prefix(CentralMarketBuff __instance)
{
if (ModContent.GetInstance<BetterCentralMarket>().Enabled)
{
Enumerator<Tower> enumerator = ((RootObject)__instance).Sim.factory.GetRaw<Tower>().list.GetEnumerator();
while (enumerator.MoveNext())
{
Tower current = enumerator.Current;
__instance.TestTower(current, ((TowerBehavior)__instance).tower.towerModel, 0f, 0);
}
}
}
}
[HarmonyPatch(typeof(CentralMarketMutator), "Mutate")]
internal static class CentralMarketMutator_CentralMarketMutator
{
public class CentralMarketDescription : ModTextOverride
{
public override string LocalizationKey => "Central Market Description";
public override bool Active => ModContent.GetInstance<BetterCentralMarket>().Enabled;
public override string TextValue => "Earns heaps of money each round and increases income generated by all non-Support towers by 10%.";
}
[HarmonyPostfix]
internal static void Postfix(CentralMarketBuff __instance, Model model, ref bool __result)
{
if (!ModContent.GetInstance<BetterCentralMarket>().Enabled)
{
return;
}
float multiplier = __instance.centralMarketBuffModel.multiplier;
float num = multiplier - 1f;
foreach (CashModel item in Il2CppGenericIEnumerable.AsIEnumerable<CashModel>(model.GetDescendants<CashModel>()))
{
item.bonusMultiplier += num;
__result = true;
}
foreach (CashPerTowerInRangeModel item2 in Il2CppGenericIEnumerable.AsIEnumerable<CashPerTowerInRangeModel>(model.GetDescendants<CashPerTowerInRangeModel>()))
{
item2.baseCash *= multiplier;
for (int i = 0; i < ((Il2CppArrayBase<float>)(object)item2.extraCashPerTier).Count; i++)
{
Il2CppStructArray<float> extraCashPerTier = item2.extraCashPerTier;
int num2 = i;
((Il2CppArrayBase<float>)(object)extraCashPerTier)[num2] = ((Il2CppArrayBase<float>)(object)extraCashPerTier)[num2] * multiplier;
}
__result = true;
}
foreach (IncreaseBloonWorthModel item3 in Il2CppGenericIEnumerable.AsIEnumerable<IncreaseBloonWorthModel>(model.GetDescendants<IncreaseBloonWorthModel>()))
{
if (item3.cash > 0f)
{
item3.cash *= multiplier;
}
else
{
item3.cashMultiplier *= multiplier;
}
__result = true;
}
foreach (MoabTakedownModel item4 in Il2CppGenericIEnumerable.AsIEnumerable<MoabTakedownModel>(model.GetDescendants<MoabTakedownModel>()))
{
item4.multiplier *= multiplier;
__result = true;
}
foreach (EatBloonModel item5 in Il2CppGenericIEnumerable.AsIEnumerable<EatBloonModel>(model.GetDescendants<EatBloonModel>()))
{
item5.rbeCashMultiplier *= multiplier;
__result = true;
}
foreach (WallOfTreesModel item6 in Il2CppGenericIEnumerable.AsIEnumerable<WallOfTreesModel>(model.GetDescendants<WallOfTreesModel>()))
{
item6.rbeCashMultiplier *= multiplier;
__result = true;
}
}
}
protected override bool DefaultEnabled => false;
public override string Description => "Makes the Central Market buff affect all non-Support towers' income generation not just Merchantmen.";
protected override string Icon => "6b345ca20df5d40308baf66c662f6e33";
}
public class BetterEziliTotem : ToggleableTweak
{
protected override bool DefaultEnabled => false;
public override string Description => "Makes Ezili's Sacrificial Totem not cost any lives";
protected override string Icon => "6316d713002ae4bfab93838017b598ee";
public override void OnNewGameModel(GameModel gameModel)
{
if (!base.Enabled)
{
return;
}
for (int i = 7; i <= 20; i++)
{
TowerModel heroWithNameAndLevel = gameModel.GetHeroWithNameAndLevel(TowerType.Ezili, i, false);
AbilityModel val = ((IEnumerable<AbilityModel>)TowerModelExt.GetAbilities(heroWithNameAndLevel)).FirstOrDefault((Func<AbilityModel, bool>)((AbilityModel b) => ((Model)b).name.Contains("Totem")));
if (val != null)
{
val.livesCost = 0;
}
}
}
}
public class BetterLaserBlasts : ToggleableTweak
{
protected override bool DefaultEnabled => false;
public override string Description => "Makes the Laser Blasts upgrade give a minor Attack Speed buff for Super Monkeys. Plasma Blasts unaffected.\r\nRates for 0/0/0, 1/0/0, 2/0/0: .045, 0.45, .03 -> .045, .04, .03";
protected override string Icon => "1e6e95d36ce3cc54ba1920cfa5378360";
public override void OnNewGameModel(GameModel gameModel)
{
if (!base.Enabled)
{
return;
}
foreach (TowerModel item in ((IEnumerable<TowerModel>)Enumerable.ToArray<TowerModel>(gameModel.GetTowersWithBaseId(TowerType.SuperMonkey, false))).Where((TowerModel model) => ((Il2CppArrayBase<int>)(object)model.tiers)[0] == 1))
{
TowerModel tower = gameModel.GetTower(TowerType.SuperMonkey, 0, ((Il2CppArrayBase<int>)(object)item.tiers)[1], ((Il2CppArrayBase<int>)(object)item.tiers)[2]);
TowerModel tower2 = gameModel.GetTower(TowerType.SuperMonkey, 2, ((Il2CppArrayBase<int>)(object)item.tiers)[1], ((Il2CppArrayBase<int>)(object)item.tiers)[2]);
float rate = ((Il2CppArrayBase<WeaponModel>)(object)TowerModelExt.GetAttackModel(tower).weapons)[0].Rate;
float rate2 = ((Il2CppArrayBase<WeaponModel>)(object)TowerModelExt.GetAttackModel(tower2).weapons)[0].Rate;
((Il2CppArrayBase<WeaponModel>)(object)TowerModelExt.GetAttackModel(item).weapons)[0].Rate = (rate * 2f + rate2) / 3f;
}
}
}
public class BetterMonkeyCity : ToggleableTweak
{
[HarmonyPatch(typeof(MutatorTower), "Mutate")]
internal static class MonkeyCityIncomeSupport_Mutate
{
[HarmonyPostfix]
internal static void Postfix(MutatorTower __instance, Model model, ref bool __result)
{
if (!ModContent.GetInstance<BetterMonkeyCity>().Enabled)
{
return;
}
foreach (IncreaseBloonWorthModel item in Il2CppGenericIEnumerable.AsIEnumerable<IncreaseBloonWorthModel>(model.GetDescendants<IncreaseBloonWorthModel>()))
{
if (item.cash > 0f)
{
item.cash *= __instance.multiplier;
}
else
{
item.cashMultiplier *= __instance.multiplier;
}
__result = true;
}
foreach (ImfLoanModel item2 in Il2CppGenericIEnumerable.AsIEnumerable<ImfLoanModel>(model.GetDescendants<ImfLoanModel>()))
{
item2.amount *= __instance.multiplier;
item2.imfLoanCollection.amount = item2.amount;
__result = true;
}
foreach (MoabTakedownModel item3 in Il2CppGenericIEnumerable.AsIEnumerable<MoabTakedownModel>(model.GetDescendants<MoabTakedownModel>()))
{
item3.multiplier *= __instance.multiplier;
__result = true;
}
}
}
protected override bool DefaultEnabled => false;
public override string Description => "Makes the Monkey City income buff affect more things, including Lead to Gold, IMF Loan, Monkey-Nomics, Monkey Pirates, and similar effects.";
protected override string Icon => "92d1f357799f3407b99ac503dbf8b36f";
}
public class BetterTrojan : ToggleableTweak
{
[HarmonyPatch(typeof(BloonWorthMutator), "Mutate")]
internal static class IncreaseBloonWorthWithTierModel_BloonWorthMutator_Mutate
{
[HarmonyPrefix]
internal static void Prefix(Model model, Model baseModel, ref int __state)
{
BloonModel val = default(BloonModel);
BloonModel val2 = default(BloonModel);
if (ModContent.GetInstance<BetterTrojan>().Enabled && Il2CppSystemObjectExt.Is<BloonModel>((Il2CppObjectBase)(object)model, ref val) && Il2CppSystemObjectExt.Is<BloonModel>((Il2CppObjectBase)(object)baseModel, ref val2))
{
__state = val.layerNumber;
val.layerNumber = (int)val2.GetTotalLayers(InGame.Bridge.Model);
}
}
[HarmonyPostfix]
internal static void Postfix(Model model, ref int __state)
{
BloonModel val = default(BloonModel);
if (ModContent.GetInstance<BetterTrojan>().Enabled && Il2CppSystemObjectExt.Is<BloonModel>((Il2CppObjectBase)(object)model, ref val))
{
val.layerNumber = __state;
}
}
}
protected override bool DefaultEnabled => false;
public override string Description => "Makes Benjamin's Bloon Trojan use the real internal layer count for Bloons so that it no longer loses money.";
protected override string Icon => "3f5b06699342a46498a873362b0aa85a";
}
public class BrickellMermonkeys : ToggleableTweak
{
protected override bool DefaultEnabled => true;
public override string Description => "Makes Brickell's effects apply to non-exclusively water based towers again.";
protected override string Icon => "dc1d82f5e96b24e4bab87e09a9f47866";
public override void OnNewGameModel(GameModel gameModel)
{
if (!base.Enabled)
{
return;
}
FilterTowerByPlaceableAreaModel val = default(FilterTowerByPlaceableAreaModel);
foreach (TowerModel item in (Il2CppArrayBase<TowerModel>)(object)gameModel.towers)
{
if (((EntityModel)item).baseId != TowerType.AdmiralBrickell)
{
continue;
}
List<TowerFilterModel> filters = new List<TowerFilterModel>();
Il2CppGenericIEnumerable.ForEach<Model>(((Model)item).GetDescendants<Model>(), (Action<Model>)delegate(Model model)
{
ActivateRateSupportZoneModel val2 = default(ActivateRateSupportZoneModel);
if (Il2CppSystemObjectExt.Is<ActivateRateSupportZoneModel>((Il2CppObjectBase)(object)model, ref val2))
{
filters.AddRange((IEnumerable<TowerFilterModel>)val2.filters);
}
ActivatePierceSupportZoneModel val3 = default(ActivatePierceSupportZoneModel);
if (Il2CppSystemObjectExt.Is<ActivatePierceSupportZoneModel>((Il2CppObjectBase)(object)model, ref val3))
{
filters.AddRange((IEnumerable<TowerFilterModel>)val3.filters);
}
ActivateTowerDamageSupportZoneModel val4 = default(ActivateTowerDamageSupportZoneModel);
if (Il2CppSystemObjectExt.Is<ActivateTowerDamageSupportZoneModel>((Il2CppObjectBase)(object)model, ref val4))
{
filters.AddRange((IEnumerable<TowerFilterModel>)val4.filters);
}
ActivateVisibilitySupportZoneModel val5 = default(ActivateVisibilitySupportZoneModel);
if (Il2CppSystemObjectExt.Is<ActivateVisibilitySupportZoneModel>((Il2CppObjectBase)(object)model, ref val5))
{
filters.AddRange((IEnumerable<TowerFilterModel>)val5.filters);
}
PierceSupportModel val6 = default(PierceSupportModel);
if (Il2CppSystemObjectExt.Is<PierceSupportModel>((Il2CppObjectBase)(object)model, ref val6))
{
filters.AddRange((IEnumerable<TowerFilterModel>)((SupportModel)val6).filters);
}
});
foreach (TowerFilterModel item2 in filters)
{
if (Il2CppSystemObjectExt.Is<FilterTowerByPlaceableAreaModel>((Il2CppObjectBase)(object)item2, ref val))
{
val.exclusive = false;
}
}
}
}
}
public class BuffableParagons : ToggleableTweak
{
[HarmonyPatch(typeof(Tower), "IsParagonBased")]
internal static class Tower_IsParagonBased
{
[HarmonyPrefix]
internal static bool Prefix(ref bool __result)
{
if (!ModContent.GetInstance<BuffableParagons>().Enabled)
{
return true;
}
__result = false;
return false;
}
}
[HarmonyPatch(typeof(ParagonTower), "Finish")]
internal static class ParagonTower_Finish
{
[HarmonyPostfix]
internal static void Postfix(ParagonTower __instance)
{
if (!ModContent.GetInstance<BuffableParagons>().Enabled)
{
return;
}
foreach (Tower item in MonoLinqHelper.ToArray<Tower>(((RootObject)__instance).Sim.towerManager.GetTowers()))
{
Action onSuspendedChanged = ((CommonBehaviorProxy<ITowerBehavior>)(object)item).onSuspendedChanged;
if (onSuspendedChanged != null)
{
onSuspendedChanged.Invoke();
}
}
}
}
[HarmonyPatch(typeof(TapTowerAbilityBehavior), "IsBanned")]
internal static class TapTowerAbilityBehavior_IsBanned
{
[HarmonyPrefix]
internal static void Prefix(Tower tower, ref bool __state)
{
if (ModContent.GetInstance<BuffableParagons>().Enabled)
{
__state = tower.towerModel.isParagon;
tower.towerModel.isParagon = false;
}
}
[HarmonyPostfix]
internal static void Postfix(Tower tower, ref bool __state)
{
if (ModContent.GetInstance<BuffableParagons>().Enabled)
{
tower.towerModel.isParagon = __state;
}
}
}
[HarmonyPatch(typeof(BrewTargetting), "FilterTower")]
internal static class BrewTargetting_FilterTower
{
[HarmonyPrefix]
internal static void Prefix(Tower tower, ref bool __state)
{
if (ModContent.GetInstance<BuffableParagons>().Enabled)
{
__state = tower.towerModel.isParagon;
tower.towerModel.isParagon = false;
}
}
[HarmonyPostfix]
internal static void Postfix(Tower tower, ref bool __state)
{
if (ModContent.GetInstance<BuffableParagons>().Enabled)
{
tower.towerModel.isParagon = __state;
}
}
}
[HarmonyPatch]
internal static class TargetFriendly_GetTargets
{
private static IEnumerable<MethodBase> TargetMethods()
{
yield return MoreAccessTools.SafeGetNestedClassMethod(typeof(TargetFriendly), "GetTargets", "MoveNext", 0);
}
[HarmonyPrefix]
internal static void Prefix(ref Tower[] __state)
{
if (ModContent.GetInstance<BuffableParagons>().Enabled)
{
__state = ((IEnumerable<Tower>)MonoLinqHelper.ToArray<Tower>(InGame.Bridge.Simulation.factory.GetUncast<Tower>())).Where((Tower tower) => tower.towerModel.isParagon).ToArray();
Tower[] array = __state;
foreach (Tower val in array)
{
val.towerModel.isParagon = false;
}
}
}
[HarmonyPostfix]
internal static void Postfix(ref Tower[] __state)
{
if (ModContent.GetInstance<BuffableParagons>().Enabled)
{
Tower[] array = __state;
foreach (Tower val in array)
{
val.towerModel.isParagon = true;
}
}
}
}
[HarmonyPatch(typeof(Tower), "AddParagonMutator")]
internal static class Tower_AddParagonMutator
{
[HarmonyPrefix]
internal static bool Prefix(Tower __instance, BehaviorMutator mutator, int time, bool updateDuration, bool applyMutation, bool onlyTimeoutWhenActive, bool useRoundTime, int roundsRemaining)
{
if (!ModContent.GetInstance<BuffableParagons>().Enabled || !__instance.towerModel.isParagon)
{
return true;
}
((Mutable)__instance).AddMutator(mutator, time, updateDuration, applyMutation, onlyTimeoutWhenActive, useRoundTime, false, false, false, roundsRemaining, false, false);
return false;
}
}
[HarmonyPatch(typeof(Tower), "AddParagonMutatorFromParent")]
internal static class Tower_AddParagonMutatorFromParent
{
[HarmonyPrefix]
internal static bool Prefix(Tower __instance, BehaviorMutator mutator, int time, bool updateDuration, bool applyMutation, bool onlyTimeoutWhenActive, bool useRoundTime, int roundsRemaining)
{
if (!ModContent.GetInstance<BuffableParagons>().Enabled || !__instance.towerModel.isParagon)
{
return true;
}
__instance.AddMutatorFromParent(mutator, time, updateDuration, applyMutation, onlyTimeoutWhenActive, useRoundTime, roundsRemaining);
return false;
}
}
[HarmonyPatch(typeof(Tower), "AddParagonMutatorIncludeSubTowers")]
internal static class Tower_AddParagonMutatorIncludeSubTowers
{
[HarmonyPrefix]
internal static bool Prefix(Tower __instance, BehaviorMutator mutator, int time, bool updateDuration, bool applyMutation, bool onlyTimeoutWhenActive, bool useRoundTime, int roundsRemaining)
{
if (!ModContent.GetInstance<BuffableParagons>().Enabled || !__instance.towerModel.isParagon)
{
return true;
}
__instance.AddMutatorIncludeSubTowers(mutator, time, updateDuration, applyMutation, onlyTimeoutWhenActive, useRoundTime, roundsRemaining);
return false;
}
}
protected override float RegistrationPriority => -1f;
protected override bool DefaultEnabled => false;
public override string Description => "Makes Paragons able to receive buffs like normal towers.";
protected override string Icon => "Ui[ParagonPip]";
public override void OnNewGameModel(GameModel gameModel)
{
if (base.Enabled)
{
Il2CppGenericIEnumerable.ForEach<SupportModel>(((Model)gameModel.GetParagonTower(TowerType.BoomerangMonkey)).GetDescendants<SupportModel>(), (Action<SupportModel>)delegate(SupportModel model)
{
model.onlyAffectParagon = false;
});
}
}
}
public class DartlingGunnerTargeting : ToggleableTweak
{
[HarmonyPatch(typeof(RotateToPointer), "SetRotation")]
internal static class RotateToPointer_SetRotation
{
[HarmonyPrefix]
internal static bool Prefix(RotateToPointer __instance)
{
Attack attack = ((AttackBehavior)__instance).attack;
TargetSupplier val = default(TargetSupplier);
if (!ModContent.GetInstance<DartlingGunnerTargeting>().Enabled || !Il2CppSystemObjectExt.Is<TargetSupplier>(attack.activeTargetSupplier, ref val))
{
return true;
}
bool flag = false;
bool flag2 = false;
Enumerator<AttackBehavior> enumerator = attack.attackBehaviors.GetEnumerator();
while (enumerator.MoveNext())
{
AttackBehavior current = enumerator.Current;
flag |= Il2CppSystemObjectExt.Is<RotateToPointer>((Il2CppObjectBase)(object)current);
flag2 |= Il2CppSystemObjectExt.Is<RotateToTarget>((Il2CppObjectBase)(object)current);
}
if (!flag || !flag2)
{
return true;
}
bool flag3 = Il2CppSystemObjectExt.Is<TargetFirst>((Il2CppObjectBase)(object)val) || Il2CppSystemObjectExt.Is<TargetLast>((Il2CppObjectBase)(object)val) || Il2CppSystemObjectExt.Is<TargetClose>((Il2CppObjectBase)(object)val) || Il2CppSystemObjectExt.Is<TargetStrong>((Il2CppObjectBase)(object)val) || Il2CppSystemObjectExt.Is<TargetCamo>((Il2CppObjectBase)(object)val);
return !flag3;
}
}
[HarmonyPatch(typeof(RotateToTarget), "ApplyRotation")]
internal static class RotateToTarget_ApplyRotation
{
[HarmonyPrefix]
internal static bool Prefix(RotateToTarget __instance)
{
Attack attack = ((AttackBehavior)__instance).attack;
TargetSupplier val = default(TargetSupplier);
if (!ModContent.GetInstance<DartlingGunnerTargeting>().Enabled || !Il2CppSystemObjectExt.Is<TargetSupplier>(attack.activeTargetSupplier, ref val))
{
return true;
}
bool flag = false;
bool flag2 = false;
Enumerator<AttackBehavior> enumerator = attack.attackBehaviors.GetEnumerator();
while (enumerator.MoveNext())
{
AttackBehavior current = enumerator.Current;
flag |= Il2CppSystemObjectExt.Is<RotateToPointer>((Il2CppObjectBase)(object)current);
flag2 |= Il2CppSystemObjectExt.Is<RotateToTarget>((Il2CppObjectBase)(object)current);
}
if (!flag || !flag2)
{
return true;
}
return Il2CppSystemObjectExt.Is<TargetFirst>((Il2CppObjectBase)(object)val) || Il2CppSystemObjectExt.Is<TargetLast>((Il2CppObjectBase)(object)val) || Il2CppSystemObjectExt.Is<TargetClose>((Il2CppObjectBase)(object)val) || Il2CppSystemObjectExt.Is<TargetStrong>((Il2CppObjectBase)(object)val) || Il2CppSystemObjectExt.Is<TargetCamo>((Il2CppObjectBase)(object)val);
}
}
protected override bool DefaultEnabled => true;
public override string Description => "Gives all Dartling Gunners First/Last/Close/Strong targeting";
protected override ModSettingCategory Category => TacticalTweaksMod.Targeting;
protected override string Icon => "MonkeyIcons[DartlingGunnerIcon]";
protected override string DisableIfModPresent => "MegaKnowledge";
public override void OnNewGameModel(GameModel gameModel)
{
if (!base.Enabled)
{
return;
}
foreach (TowerModel item in ((IEnumerable<TowerModel>)gameModel.towers).Where((TowerModel model) => ((EntityModel)model).baseId == TowerType.DartlingGunner && !((Il2CppArrayBase<string>)(object)model.appliedUpgrades).Contains("Bloon Area Denial System")))
{
AttackModel attackModel = TowerModelExt.GetAttackModel(item);
bool value = !((Il2CppArrayBase<string>)(object)item.appliedUpgrades).Contains("Ray of Doom") && !((Il2CppArrayBase<string>)(object)item.appliedUpgrades).Contains("Buckshot");
TacticalTweaksMod.UpdatePointer(attackModel, value);
TacticalTweaksMod.AddAllTargets(attackModel);
item.UpdateTargetProviders();
}
}
}
public class EliteDefenderTargetSwitch : ToggleableTweak
{
[HarmonyPatch(typeof(Ability), "Activate")]
internal static class Ability_Activate
{
[HarmonyPostfix]
internal static void Postfix(Ability __instance)
{
if (ModContent.GetInstance<EliteDefenderTargetSwitch>().Enabled)
{
AbilityModel abilityModel = __instance.abilityModel;
if (((abilityModel != null) ? abilityModel.displayName : null) == "Retaliation")
{
((TowerBehavior)__instance).tower.SetTargetType(TargetType.first);
}
}
}
}
protected override bool DefaultEnabled => false;
public override string Description => "An Elite Defender will switch to First targeting after a Bloon leak activates its ability.";
protected override string Icon => "c9cb42be6c73344b0bd7757d4201de65";
protected override ModSettingCategory Category => TacticalTweaksMod.Targeting;
}
public class EtienneTargeting : ToggleableTweak
{
protected override bool DefaultEnabled => false;
public override string Description => "Replaces Etienne's targeting options with the standard Fist, Last, Close Strong.";
protected override string Icon => "MonkeyIcons[EtienneIcon]";
protected override ModSettingCategory Category => TacticalTweaksMod.Targeting;
public override void OnNewGameModel(GameModel gameModel)
{
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Expected O, but got Unknown
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Expected O, but got Unknown
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_008f: Expected O, but got Unknown
if (!base.Enabled)
{
return;
}
foreach (TowerModel item in Il2CppGenericIEnumerable.AsIEnumerable<TowerModel>(gameModel.GetTowersWithBaseId(TowerType.Etienne, false)))
{
AttackModel attackModel = TowerModelExt.GetAttackModel(item);
AttackModelBehaviorExt.RemoveBehaviors<TargetDivideAndConquerModel>(attackModel);
AttackModelBehaviorExt.RemoveBehaviors<TargetZoneDefenceModel>(attackModel);
AttackModelBehaviorExt.AddBehavior<TargetLastModel>(attackModel, CreateTargetLastModelExt.Create(new Args
{
isSelectable = true
}));
AttackModelBehaviorExt.AddBehavior<TargetCloseModel>(attackModel, CreateTargetCloseModelExt.Create(new Args
{
isSelectable = true
}));
AttackModelBehaviorExt.AddBehavior<TargetStrongModel>(attackModel, CreateTargetStrongModelExt.Create(new Args
{
isSelectable = true
}));
item.UpdateTargetProviders();
}
}
}
public class FixIceMonkeyParagon : TacticalTweak
{
public override void OnNewGameModel(GameModel gameModel)
{
TowerModel paragonTower = gameModel.GetParagonTower(TowerType.IceMonkey);
AbilityModel ability = TowerModelExt.GetAbility(paragonTower);
if (ability != null)
{
AgeModel descendant = ((Model)ability).GetDescendant<AgeModel>();
if (descendant != null)
{
descendant.rounds = 999999;
}
}
}
}
public class HeroBoostDebt : ToggleableTweak
{
[HarmonyPatch(typeof(TowerSelectionMenu), "UpdateHeroBooster")]
internal static class TowerSelectionMenu_UpdateHeroBooster
{
[HarmonyPostfix]
internal static void Postfix(TowerSelectionMenu __instance)
{
if (ModContent.GetInstance<HeroBoostDebt>().Enabled)
{
__instance.heroBoosterButtonText.SetText("▼$");
if (IEnumerableExt.OfIl2CppType<ImfLoanCollection>((IEnumerable)__instance.Bridge.simulation.GetBehaviors().ToArray()).Any())
{
((Selectable)__instance.heroBoosterButton).interactable = false;
}
}
}
}
[HarmonyPatch(typeof(TowerSelectionMenu), "OnHeroBoosterButtonClicked")]
internal static class TowerSelectionMenu_OnHeroBoosterButtonClicked
{
[HarmonyPrefix]
internal static bool Prefix(TowerSelectionMenu __instance)
{
if (!ModContent.GetInstance<HeroBoostDebt>().Enabled)
{
return true;
}
TowerToSimulation tower = __instance.selectedTower;
PopupScreen.instance.ShowPopup((Placement)0, "Hero Boost Debt", $"Do you want to boost to level {tower.hero.level + 1}?\nYou will gain a debt of ${tower.hero.costToLevelUp:N0}", ReturnCallback.op_Implicit((Action)delegate
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Expected O, but got Unknown
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Expected O, but got Unknown
__instance.Bridge.UpgradeHeroToLevel(tower.Id, Action<bool>.op_Implicit((Action<bool>)delegate
{
}), tower.hero.level + 1);
Simulation simulation = __instance.Bridge.Simulation;
Args val = new Args();
((ModelArgs<ImfLoanCollectionModel>)val).name = "HeroBoostDebt";
val.collectionRate = 0.5f;
val.amount = tower.hero.costToLevelUp;
simulation.AddBehavior<ImfLoanCollection>((SimulationBehaviorModel)(object)CreateImfLoanCollectionModelExt.Create(val));
__instance.UpdateHeroBooster(tower);
}), "Yes", ReturnCallback.op_Implicit((Action)delegate
{
__instance.UpdateHeroBooster(tower);
}), "No", (TransitionAnim)1, (BackGround)0, false, false);
return false;
}
}
protected override bool DefaultEnabled => true;
public override string Description => "Replaces the Monkey Money Hero Boost with a button that lets you purchase the next level up of the hero by going into debt.";
protected override string Icon => "9419ea792c2a1344c8e538f00d4537a5";
}
public class MoreUnfreezableTowers : ToggleableTweak
{
[HarmonyPatch(typeof(ApplyTowerFreeze), "FreezeTower")]
internal static class ApplyTowerFreeze_FreezeTower
{
[HarmonyPrefix]
internal static bool Prefix(ApplyTowerFreeze __instance, ObjectId towerID)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
if (!ModContent.GetInstance<MoreUnfreezableTowers>().Enabled)
{
return true;
}
Tower towerById = ((RootObject)__instance).Sim.towerManager.GetTowerById(towerID);
TowerModel towerModel = towerById.towerModel;
Il2CppStringArray appliedUpgrades = towerModel.appliedUpgrades;
int result;
if (appliedUpgrades == null || !((Il2CppArrayBase<string>)(object)appliedUpgrades).Contains("Ring of Fire"))
{
Il2CppStringArray appliedUpgrades2 = towerModel.appliedUpgrades;
if (appliedUpgrades2 == null || !((Il2CppArrayBase<string>)(object)appliedUpgrades2).Contains("Signal Flare"))
{
Il2CppStringArray appliedUpgrades3 = towerModel.appliedUpgrades;
if (appliedUpgrades3 == null || !((Il2CppArrayBase<string>)(object)appliedUpgrades3).Contains("Dragon's Breath"))
{
Il2CppStringArray appliedUpgrades4 = towerModel.appliedUpgrades;
if (appliedUpgrades4 == null || !((Il2CppArrayBase<string>)(object)appliedUpgrades4).Contains("Tidal Chill"))
{
Il2CppStringArray appliedUpgrades5 = towerModel.appliedUpgrades;
if ((appliedUpgrades5 == null || !((Il2CppArrayBase<string>)(object)appliedUpgrades5).Contains("The Blazing Sun")) && ((EntityModel)towerModel).baseId != TowerType.Gwendolin)
{
result = ((towerById.towerSkinName != "Fusty the Snowman") ? 1 : 0);
goto IL_00e6;
}
}
}
}
}
result = 0;
goto IL_00e6;
IL_00e6:
return (byte)result != 0;
}
}
[HarmonyPatch(typeof(PyrotechnicsSupportFilter), "FilterTowerModel")]
internal static class PyrotechnicsSupportFilter_FilterTowerModel
{
[HarmonyPostfix]
internal static void Postfix(TowerModel towerModel, ref bool __result)
{
__result |= ((EntityModel)towerModel).baseId == TowerType.Desperado && (((Il2CppArrayBase<string>)(object)towerModel.appliedUpgrades)?.Contains("The Blazing Sun") ?? false);
}
}
protected override bool DefaultEnabled => true;
public override string Description => "Fire Towers and certain other Ice Towers also no longer get frozen on Glacial Trail.\r\nThis includes: Gwen (Any Skin), Fusty the Snowman, Ring of Fire Tack Shooters, Dragon's Breath Wizards, Signal Flare Mortar Monkeys, Tidal Chill Mermonkeys, The Blazing Sun.";
protected override string Icon => "MapImages[MapSelectGlacialTrailButton]";
}
public class MortarMonkeyTargeting : ToggleableTweak
{
protected override bool DefaultEnabled => true;
public override string Description => "Gives all Mortar Monkeys First/Last/Close/Strong targeting";
protected override ModSettingCategory Category => TacticalTweaksMod.Targeting;
protected override string Icon => "MonkeyIcons[MortarMonkeyIcon]";
protected override string DisableIfModPresent => "MegaKnowledge";
public override void OnNewGameModel(GameModel gameModel)
{
if (!base.Enabled)
{
return;
}
foreach (TowerModel item in ((IEnumerable<TowerModel>)gameModel.towers).Where((TowerModel model) => ((EntityModel)model).baseId == TowerType.MortarMonkey))
{
AttackModel attackModel = TowerModelExt.GetAttackModel(item);
TacticalTweaksMod.AddAllTargets(attackModel);
item.towerSelectionMenuThemeId = "ActionButton";
item.UpdateTargetProviders();
}
}
}
public class ObynBuffsGlobal : ToggleableTweak
{
protected override bool DefaultEnabled => false;
public override string Description => "Makes Obyn's buff apply to all Druids, not just ones within range.";
protected override string Icon => "UiBuffIcons[BuffIconObynLevel11]";
public override void OnNewGameModel(GameModel gameModel)
{
foreach (TowerModel item in Il2CppGenericIEnumerable.AsIEnumerable<TowerModel>(gameModel.GetTowersWithBaseId(TowerType.ObynGreenfoot, false)))
{
foreach (SupportModel behavior in TowerModelBehaviorExt.GetBehaviors<SupportModel>(item))
{
behavior.isGlobal = true;
}
}
}
}
public class ObynPriceTweak : ToggleableTweak
{
protected override bool DefaultEnabled => false;
public override string Description => "Changes Obyn's base price so that he's able to be used as a CHIMPs start like he used to be.";
protected override string Icon => "MonkeyIcons[ObynGreenFootIcon]";
public override void OnNewGameModel(GameModel gameModel)
{
TowerModel towerWithName = gameModel.GetTowerWithName(TowerType.Sauda);
foreach (TowerModel item in Il2CppGenericIEnumerable.AsIEnumerable<TowerModel>(gameModel.GetTowersWithBaseId(TowerType.ObynGreenfoot, false)))
{
item.cost = towerWithName.cost;
}
}
}
public class OverclockBanks : ToggleableTweak
{
[HarmonyPatch(typeof(OverclockMutator), "Mutate")]
internal static class OverclockMutator_Mutate
{
[HarmonyPostfix]
internal static void Postfix(OverclockMutator __instance, Model model)
{
TowerModel towerModel = default(TowerModel);
if (ModContent.GetInstance<OverclockBanks>().Enabled && Il2CppSystemObjectExt.Is<TowerModel>((Il2CppObjectBase)(object)model, ref towerModel))
{
Apply(towerModel, __instance.overclockModel.rateModifier);
}
}
}
[HarmonyPatch(typeof(OverclockPermanentMutator), "Mutate")]
internal static class OverclockPermanentModel_Mutate
{
[HarmonyPostfix]
internal static void Postfix(OverclockPermanentMutator __instance, Model model)
{
TowerModel towerModel = default(TowerModel);
if (ModContent.GetInstance<OverclockMonkeyopolis>().Enabled && Il2CppSystemObjectExt.Is<TowerModel>((Il2CppObjectBase)(object)model, ref towerModel))
{
float rateModifier = 1f - (float)__instance.stacks * (1f - __instance.overclockPermanentModel.rateModifier);
Apply(towerModel, rateModifier);
}
}
}
protected override bool DefaultEnabled => true;
public override string Description => "Makes the Overclock buff affect the interest rates of Monkey Banks.";
protected override string Icon => "01a32a1a35c684d6a8d137b62d3a7f1b";
protected override ModSettingCategory Category => TacticalTweaksMod.Overclock;
public static void Apply(TowerModel towerModel, float rateModifier)
{
foreach (BankModel item in Il2CppGenericIEnumerable.AsIEnumerable<BankModel>(((Model)towerModel).GetDescendants<BankModel>()))
{
item.interest /= rateModifier;
}
}
}
public class OverclockMonkeyopolis : ToggleableTweak
{
[HarmonyPatch(typeof(OverclockMutator), "Mutate")]
internal static class OverclockMutator_Mutate
{
[HarmonyPostfix]
internal static void Postfix(OverclockMutator __instance, Model model)
{
TowerModel towerModel = default(TowerModel);
if (ModContent.GetInstance<OverclockMonkeyopolis>().Enabled && Il2CppSystemObjectExt.Is<TowerModel>((Il2CppObjectBase)(object)model, ref towerModel) && !(((EntityModel)towerModel).baseId == TowerType.BananaFarm))
{
Il2CppGenericIEnumerable.ForEach<EmissionsPerRoundFilterModel>(model.GetDescendants<EmissionsPerRoundFilterModel>(), (Action<EmissionsPerRoundFilterModel>)delegate(EmissionsPerRoundFilterModel filter)
{
MonkeyopolisModel val = default(MonkeyopolisModel);
int num = (TowerModelBehaviorExt.HasBehavior<MonkeyopolisModel>(towerModel, ref val) ? val.cratesPerRound : filter.count);
filter.count = Math.CeilToInt((float)num / __instance.overclockModel.rateModifier);
});
}
}
}
[HarmonyPatch(typeof(OverclockPermanentMutator), "Mutate")]
internal static class OverclockPermanentModel_Mutate
{
[HarmonyPostfix]
internal static void Postfix(OverclockPermanentMutator __instance, Model model)
{
TowerModel towerModel = default(TowerModel);
if (ModContent.GetInstance<OverclockMonkeyopolis>().Enabled && Il2CppSystemObjectExt.Is<TowerModel>((Il2CppObjectBase)(object)model, ref towerModel) && !(((EntityModel)towerModel).baseId == TowerType.BananaFarm))
{
float rateModifier = 1f - (float)__instance.stacks * (1f - __instance.overclockPermanentModel.rateModifier);
Il2CppGenericIEnumerable.ForEach<EmissionsPerRoundFilterModel>(model.GetDescendants<EmissionsPerRoundFilterModel>(), (Action<EmissionsPerRoundFilterModel>)delegate(EmissionsPerRoundFilterModel filter)
{
MonkeyopolisModel val = default(MonkeyopolisModel);
int num = (TowerModelBehaviorExt.HasBehavior<MonkeyopolisModel>(towerModel, ref val) ? val.cratesPerRound : filter.count);
filter.count = Math.CeilToInt((float)num / rateModifier);
});
}
}
}
[HarmonyPatch(typeof(EmissionMutator), "Mutate")]
internal static class EmissionMutator_Mutate
{
[HarmonyPrefix]
internal static void Prefix(EmissionMutator __instance, Model model, ref List<int> __state)
{
__state = ((IEnumerable<EmissionsPerRoundFilterModel>)Enumerable.ToArray<EmissionsPerRoundFilterModel>(model.GetDescendants<EmissionsPerRoundFilterModel>())).Select((EmissionsPerRoundFilterModel filter) => filter.count).ToList();
}
[HarmonyPostfix]
internal static void Postfix(EmissionMutator __instance, Model model, ref List<int> __state)
{
foreach (var (val, num) in ((IEnumerable<EmissionsPerRoundFilterModel>)Enumerable.ToArray<EmissionsPerRoundFilterModel>(model.GetDescendants<EmissionsPerRoundFilterModel>())).Zip(__state))
{
val.count = Math.Max(num, val.count);
}
}
}
protected override bool DefaultEnabled => true;
public override string Description => "Makes the Overclock buff affect Monkeyopolis income in the same way it affects Banana Farms.";
protected override string Icon => "6bcf8dc34ff294fe5bdf6f358a6eb62f";
protected override ModSettingCategory Category => TacticalTweaksMod.Overclock;
}
public class OverclockPeriodicAbilities : ToggleableTweak
{
[HarmonyPatch(typeof(OverclockMutator), "Mutate")]
internal static class OverclockMutator_Mutate
{
[HarmonyPostfix]
internal static void Postfix(OverclockMutator __instance, Model model)
{
if (!ModContent.GetInstance<OverclockPeriodicAbilities>().Enabled)
{
return;
}
float rateModifier = __instance.overclockModel.rateModifier;
Il2CppGenericIEnumerable.ForEach<ActivateAbilityAfterIntervalModel>(model.GetDescendants<ActivateAbilityAfterIntervalModel>(), (Action<ActivateAbilityAfterIntervalModel>)delegate(ActivateAbilityAfterIntervalModel i)
{
if (!((Model)i).name.Contains("TechBotify"))
{
i.interval *= rateModifier;
i.intervalFrames = Math.CeilToInt((float)i.intervalFrames * rateModifier);
}
});
}
}
[HarmonyPatch(typeof(OverclockPermanentMutator), "Mutate")]
internal static class OverclockPermanentModel_Mutate
{
[HarmonyPostfix]
internal static void Postfix(OverclockPermanentMutator __instance, Model model)
{
if (!ModContent.GetInstance<OverclockPeriodicAbilities>().Enabled)
{
return;
}
float rateModifier = 1f - (float)__instance.stacks * (1f - __instance.overclockPermanentModel.rateModifier);
Il2CppGenericIEnumerable.ForEach<ActivateAbilityAfterIntervalModel>(model.GetDescendants<ActivateAbilityAfterIntervalModel>(), (Action<ActivateAbilityAfterIntervalModel>)delegate(ActivateAbilityAfterIntervalModel i)
{
if (!((Model)i).name.Contains("TechBotify"))
{
i.interval *= rateModifier;
i.intervalFrames = Math.CeilToInt((float)i.intervalFrames * rateModifier);
}
});
}
}
protected override bool DefaultEnabled => true;
public override string Description => "Makes the Overclock buff affect the frequency of periodic ability activations like Carpet of Spikes.";
protected override string Icon => "beca93cfa6584443081618415fec9cb0";
protected override ModSettingCategory Category => TacticalTweaksMod.Overclock;
}
public class OverlockCash : ToggleableTweak
{
[HarmonyPatch(typeof(OverclockMutator), "Mutate")]
internal static class OverclockMutator_Mutate
{
[HarmonyPostfix]
internal static void Postfix(OverclockMutator __instance, Model model)
{
TowerModel towerModel = default(TowerModel);
if (ModContent.GetInstance<OverlockCash>().Enabled && Il2CppSystemObjectExt.Is<TowerModel>((Il2CppObjectBase)(object)model, ref towerModel))
{
float rateModifier = __instance.overclockModel.rateModifier;
Apply(towerModel, rateModifier);
}
}
}
[HarmonyPatch(typeof(OverclockPermanentMutator), "Mutate")]
internal static class OverclockPermanentModel_Mutate
{
[HarmonyPostfix]
internal static void Postfix(OverclockPermanentMutator __instance, Model model)
{
TowerModel towerModel = default(TowerModel);
if (ModContent.GetInstance<OverlockCash>().Enabled && Il2CppSystemObjectExt.Is<TowerModel>((Il2CppObjectBase)(object)model, ref towerModel))
{
float rateModifier = 1f - (float)__instance.stacks * (1f - __instance.overclockPermanentModel.rateModifier);
Apply(towerModel, rateModifier);
}
}
}
protected override bool DefaultEnabled => true;
public override string Description => "Makes the Overclock buff increase other forms of cash generation for towers such as from end of round or from abilities.";
protected override string Icon => "a5a03704d4accd542a39454eba688fb5";
protected override ModSettingCategory Category => TacticalTweaksMod.Overclock;
public static void Apply(TowerModel towerModel, float rateModifier)
{
foreach (PerRoundCashBonusTowerModel item in Il2CppGenericIEnumerable.AsIEnumerable<PerRoundCashBonusTowerModel>(((Model)towerModel).GetDescendants<PerRoundCashBonusTowerModel>()))
{
item.cashPerRound /= rateModifier;
item.cashRoundBonusMultiplier /= rateModifier;
}
foreach (ImfLoanModel item2 in Il2CppGenericIEnumerable.AsIEnumerable<ImfLoanModel>(((Model)towerModel).GetDescendants<ImfLoanModel>()))
{
item2.amount /= rateModifier;
}
foreach (CashPerTowerInRangeModel item3 in Il2CppGenericIEnumerable.AsIEnumerable<CashPerTowerInRangeModel>(((Model)towerModel).GetDescendants<CashPerTowerInRangeModel>()))
{
item3.baseCash /= rateModifier;
for (int i = 0; i < ((Il2CppArrayBase<float>)(object)item3.extraCashPerTier).Count; i++)
{
Il2CppStructArray<float> extraCashPerTier = item3.extraCashPerTier;
int num = i;
((Il2CppArrayBase<float>)(object)extraCashPerTier)[num] = ((Il2CppArrayBase<float>)(object)extraCashPerTier)[num] / rateModifier;
}
}
if (!(((EntityModel)towerModel).baseId != TowerType.BananaFarm) || !(((EntityModel)towerModel).baseId != TowerType.MonkeyVillage))
{
return;
}
foreach (CashModel item4 in Il2CppGenericIEnumerable.AsIEnumerable<CashModel>(((Model)towerModel).GetDescendants<CashModel>()))
{
item4.bonusMultiplier += 1f / rateModifier - 1f;
}
}
}
public class ParagonSentryTargeting : ToggleableTweak
{
protected override bool DefaultEnabled => true;
public override string Description => "Gives the Master Builder's Green Sentry First/Last/Close/Strong/Locked targeting.";
protected override ModSettingCategory Category => TacticalTweaksMod.Targeting;
protected override string Icon => "b22553f1b304d274d9ea350eece10cce";
public override void OnNewGameModel(GameModel gameModel)
{
if (base.Enabled)
{
TowerModel paragonTower = gameModel.GetParagonTower(TowerType.EngineerMonkey);
TowerModel val = ModelExt.FindDescendant<TowerModel>((Model)(object)paragonTower, TowerType.SentryParagonGreen);
AttackModel attackModel = TowerModelExt.GetAttackModel(val);
TacticalTweaksMod.UpdatePointer(attackModel, false);
TacticalTweaksMod.AddAllTargets(attackModel);
val.UpdateTargetProviders();
}
}
}
public class PeriodicCooldownReduction : ToggleableTweak
{
[HarmonyPatch(typeof(MutatorTower), "BuffTowerModel")]
internal static class AbilityCooldownScaleSupport_BuffTowerModel
{
[HarmonyPostfix]
internal static void Postfix(MutatorTower __instance, TowerModel towerModel)
{
if (ModContent.GetInstance<PeriodicCooldownReduction>().Enabled)
{
Il2CppGenericIEnumerable.ForEach<ActivateAbilityAfterIntervalModel>(((Model)towerModel).GetDescendants<ActivateAbilityAfterIntervalModel>(), (Action<ActivateAbilityAfterIntervalModel>)delegate(ActivateAbilityAfterIntervalModel i)
{
i.interval /= __instance.abilityCooldownSpeedScale;
i.intervalFrames = Math.CeilToInt((float)i.intervalFrames / __instance.abilityCooldownSpeedScale);
});
}
}
}
protected override bool DefaultEnabled => true;
public override string Description => "Makes ability cooldown reduction effects also apply to periodically activated abilities like Carpet of Spikes.";
protected override string Icon => "beca93cfa6584443081618415fec9cb0";
}
public class PursuitPathPrioritization : ToggleableTweak
{
[HarmonyPatch(typeof(PursuitSetting), "GetPursuitTarget")]
internal static class PursuitSetting_GetPursuitTarget
{
[HarmonyPrefix]
internal static bool Prefix(PursuitSetting __instance, ref Target? __result)
{
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_00ea: Expected O, but got Unknown
HeliMovement heliMovement = __instance.heliMovement;
if (((heliMovement != null) ? ((TowerBehavior)heliMovement).tower : null) == null || !PathSelections.TryGetValue(((RootObject)((TowerBehavior)__instance.heliMovement).tower).Id, out List<string> value))
{
return true;
}
Path[] currentPaths = (from p in value
select ((RootObject)__instance).Sim.Map.pathManager.GetPath(p) into p
where p.hasBloons || p.hasOfftrackBloons
select p).ToArray();
if (!ArrayExt.Any<Path>(currentPaths))
{
return true;
}
__result = ((IEnumerable<Target>)MonoLinqHelper.ToArray<Target>(((Il2CppObjectBase)((PathSupplierHeli)__instance).Targets(99999f)).Cast<IEnumerable<Target>>())).FirstOrDefault((Func<Target, bool>)delegate(Target target)
{
PathSegment pathSegment = target.pathSegment;
object obj = ((pathSegment != null) ? pathSegment.path : null);
if (obj == null)
{
Bloon bloon = target.bloon;
obj = ((bloon != null) ? bloon.path : null);
}
Path val = (Path)obj;
return val != null && (currentPaths.Contains(val) || val.def.pathId.Contains("Boss"));
});
if (__result == null)
{
__result = new Target();
}
return false;
}
}
public class PursuitTsmTheme : ModTsmTheme
{
private TSMButton button = null;
private static readonly Dictionary<Entity, string> Dots = new Dictionary<Entity, string>();
public override string BaseTheme => "HeliPilot";
public override void SetupTheme(BaseTSMTheme theme)
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
button = GameObjectExt.AddTSMButton(((Component)theme).gameObject, new Info("PursuitButton", 372f, -428f, 180f), "Ui[GreenBtnSquare]", "PursuitButton", ModContent.GetId<PursuitCustomInput>());
GameObjectExt.AddImage(((Component)button).gameObject, new Info("Icon", 128f), "3d08be8876462204d9702b4259d9828e");
}
public override void TowerChanged(BaseTSMTheme theme, TowerToSimulation tower)
{
PursuitSetting behaviorInDependants = ((RootBehavior)tower.tower).Entity.GetBehaviorInDependants<PursuitSetting>();
if (behaviorInDependants == null)
{
((Component)button).gameObject.SetActive(false);
return;
}
((Component)button).gameObject.SetActive(true);
if (!Dots.Any())
{
StartDrawing();
}
}
public override void OnDisable(BaseTSMTheme theme)
{
StopDrawing();
}
private static void StartDrawing()
{
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Expected O, but got Unknown
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
Simulation current = SimulationExt.Current;
Enumerator<Path> enumerator = current.Map.pathManager.paths.GetEnumerator();
while (enumerator.MoveNext())
{
Path current2 = enumerator.Current;
if (!current2.isActive || current2.def.pathId.Contains("Boss"))
{
continue;
}
foreach (PathSegment item in (Il2CppArrayBase<PathSegment>)(object)current2.segments)
{
Entity val = current.factory.Create<Entity>();
val.AddBehaviorFromModel((Model)(object)CreateTransformModelExt.Create(new Args
{
position = new Vector3(item.point.x, item.point.y, item.pointHeight)
}), false);
DisplayBehavior val2 = ((Il2CppObjectBase)val.AddBehaviorFromModel((Model)(object)CreateDisplayModelExt.Create(), false)).Cast<DisplayBehavior>();
val2.SetScaleOffset(Vector3.zero);
Dots[val] = current2.def.pathId;
}
}
}
private static void StopDrawing()
{
foreach (Entity key in Dots.Keys)
{
((RootObject)key).Destroy();
}
Dots.Clear();
}
public override void Update(BaseTSMTheme theme)
{
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_00df: Unknown result type (might be due to invalid IL or missing references)
//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
//IL_0189: Unknown result type (might be due to invalid IL or missing references)
//IL_0193: Expected O, but got Unknown
if (!Dots.Any())
{
return;
}
InputManager val = InGameExt[InGame.instance];
bool flag = ModCustomInput.ActiveInput is PursuitCustomInput;
object obj;
if (!flag)
{
obj = TowerSelectionMenuExt.instance.selectedTower;
}
else
{
CustomInput customInput = val.customInput;
obj = ((customInput != null) ? customInput.tower : null);
}
TowerToSimulation val2 = (TowerToSimulation)obj;
object obj2;
if (!flag)
{
obj2 = null;
}
else
{
PathSegment? path = PursuitCustomInput.GetPath(val.CursorPositionWorld);
if (path == null)
{
obj2 = null;
}
else
{
Path path2 = path.path;
obj2 = ((path2 != null) ? path2.def.pathId : null);
}
}
string text = (string)obj2;
List<string> list = ((val2 == null) ? new List<string>() : PathSelections.GetValueOrDefault(val2.Id, new List<string>()));
foreach (KeyValuePair<Entity, string> dot in Dots)
{
dot.Deconstruct(out var key, out var value);
Entity val3 = key;
string text2 = value;
DisplayBehavior displayBehavior = val3.GetDisplayBehavior();
displayBehavior.SetScaleOffset(Vector3.one * (float)((val2 != null && (list.Contains(text2) || flag)) ? 1 : 0));
PrefabReference display = displayBehavior.displayModel.display;
string text3 = ((display != null) ? display.AssetGUID : null);
string text4 = "f6e4526492bc9164baac0dd1058077f2";
if (flag)
{
bool flag2 = text == text2;
bool flag3 = list.Contains(text2);
if (flag2 && flag3)
{
text4 = "15a96ce311133ec46b824e88f291a255";
}
else if (!flag2 && !flag3)
{
text4 = "505654c2ff7054e49900a08b16f67bde";
}
}
if (text3 != text4)
{
displayBehavior.displayModel.display = new PrefabReference(text4);
((RootBehavior)displayBehavior).UpdatedModel((Model)(object)displayBehavior.displayModel);
}
}
}
}
public class PursuitCustomInput : ModCustomInput
{
public override string GetHelperMessage(CustomInput customInput)
{
return "Prioritize pursuing specific path(s)";
}
public static PathSegment? GetPath(Vector2 cursorPosWorld)
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
return SimulationExt.Current.map.pathManager.FirstPathSegmentInRangeOrDefault(new Vector2(cursorPosWorld), 10f, false, false, false);
}
public override bool IsPositionValid(CustomInput customInput, Vector2 cursorPosWorld, bool isCursorInWorld)
{
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
return isCursorInWorld && GetPath(cursorPosWorld) != null;
}
public override void OnValidPositionCursorUp(CustomInput customInput, Vector2 cursorPosWorld, bool isCursorInWorld)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
string pathId = GetPath(cursorPosWorld).path.def.pathId;
if (!PathSelections.TryGetValue(customInput.tower.Id, out List<string> value))
{
value = new List<string>();
PathSelections.Add(customInput.tower.Id, value);
}
if (value.Contains(pathId))
{
value.Remove(pathId);
}
else
{
value.Add(pathId);
}
((ModCustomInput)this).OnValidPositionCursorUp(customInput, cursorPosWorld, isCursorInWorld);
}
public override void Update(CustomInput customInput, Vector3 cursorPosUnityWorld, Vector2 cursorPosWorld, bool isCursorActive)
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
if (isCursorActive)
{
PathSegment? path = GetPath(cursorPosWorld);
string text = ((path != null) ? path.path.def.pathId : null);
string text2 = ((ModCustomInput)this).GetHelperMessage(customInput);
List<string> valueOrDefault = PathSelections.GetValueOrDefault(customInput.tower.Id, new List<string>());
if (text != null)
{
text2 = (valueOrDefault.Contains(text) ? ("Stop prioritizing " + text) : ("Start prioritizing " + text));
}
customInput.inputManager.SetHelperMessage(text2, -1f);
}
}
}
public static readonly Dictionary<ObjectId, List<string>> PathSelections = new Dictionary<ObjectId, List<string>>();
protected override bool DefaultEnabled => true;
protected override string Icon => "3d08be8876462204d9702b4259d9828e";
public override string Description => "Allows Heli Pilots to choose to prioritize Bloons on specific paths.";
public override void OnNewGameModel(GameModel gameModel)
{
if (!base.Enabled)
{
return;
}
foreach (TowerModel item in ((IEnumerable<TowerModel>)MonoLinqHelper.ToArray<TowerModel>(gameModel.GetTowersWithBaseId(TowerType.HeliPilot, false))).Where((TowerModel model) => ((Il2CppArrayBase<string>)(object)model.appliedUpgrades)?.Contains("Pursuit") ?? false))
{
item.towerSelectionMenuThemeId = ModContent.GetId<PursuitTsmTheme>();
}
}
public override void OnTowerSaved(Tower tower, TowerSaveDataModel saveData)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
if (PathSelections.TryGetValue(((RootObject)tower).Id, out List<string> value))
{
saveData.metaData[((ModContent)this).Id] = JsonConvert.SerializeObject((object)value);
}
}
public override void OnTowerLoaded(Tower tower, TowerSaveDataModel saveData)
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
string text = default(string);
if (saveData.metaData.TryGetValue(((ModContent)this).Id, ref text))
{
PathSelections[((RootObject)tower).Id] = JsonConvert.DeserializeObject<List<string>>(text) ?? new List<string>();
}
}
public override void OnGameObjectsReset()
{
PathSelections.Clear();
}
}
public class StickyBombAttackSpeed : ToggleableTweak
{
[HarmonyPatch(typeof(Tower), "OnUpgraded")]
internal static class Tower_OnUpgraded
{
[HarmonyPostfix]
internal static void Postfix(Tower __instance)
{
Apply(__instance);
}
}
[HarmonyPatch(typeof(Tower), "OnPlace")]
internal static class Tower_OnPlace
{
[HarmonyPostfix]
internal static void Postfix(Tower __instance)
{
Apply(__instance);
}
}
[HarmonyPatch(typeof(RateSupportMutator), "Mutate")]
internal static class RateSupportMutator_Mutate
{
[HarmonyPrefix]
internal static bool Prefix(RateSupportMutator __instance, Model baseModel, Model model, ref bool __result)
{
TowerModel val = default(TowerModel);
TowerModel val2 = default(TowerModel);
if (((BehaviorMutator)__instance).id != "StickyBombAttackSpeed" || !Il2CppSystemObjectExt.Is<TowerModel>((Il2CppObjectBase)(object)baseModel, ref val) || !Il2CppSystemObjectExt.Is<TowerModel>((Il2CppObjectBase)(object)model, ref val2) || !ModContent.GetInstance<StickyBombAttackSpeed>().Enabled)
{
return true;
}
IEnumerable<AddBehaviorToBloonModel> enumerable = Il2CppGenericIEnumerable.AsIEnumerable<AddBehaviorToBloonModel>(((Model)val2).GetDescendants<AddBehaviorToBloonModel>()).Where(delegate(AddBehaviorToBloonModel m)
{
switch (m.mutationId)
{
case "StickyBomb":
case "MasterSticky":
case "StickyBombSplash":
return true;
default:
return false;
}
});
float rate = ((Il2CppArrayBase<WeaponModel>)(object)TowerModelExt.GetAttackModel(val).weapons)[0].Rate;
float rate2 = ((Il2CppArrayBase<WeaponModel>)(object)TowerModelExt.GetAttackModel(val2).weapons)[0].Rate;
float num = rate2 / rate;
foreach (AddBehaviorToBloonModel item in enumerable)
{
item.lifespan *= num;
if (item.lifespan < 0.05f)
{
item.lifespan = 0.05f;
}
item.lifespanFrames = (int)(item.lifespan * 60f);
foreach (DamageOverTimeModel behavior in AddBehaviorToBloonModelBehaviorExt.GetBehaviors<DamageOverTimeModel>(item))
{
behavior.Interval = item.lifespan - 0.02f;
}
foreach (ProjectileOverTimeModel behavior2 in AddBehaviorToBloonModelBehaviorExt.GetBehaviors<ProjectileOverTimeModel>(item))
{
behavior2.Interval = item.lifespan - 0.02f;
}
}
__result = true;
return false;
}
}
protected override bool DefaultEnabled => false;
public override string Description => "Makes attack speed buffs cause Sticky Bombs to blow up quicker. (Also affects Master Bomber)";
protected override string Icon => "a61263630220b41b4a578114cc55cfe9";
public static void Apply(Tower? tower)
{
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_007e: Expected O, but got Unknown
if (((tower != null) ? tower.towerModel : null) != null && ModContent.GetInstance<StickyBombAttackSpeed>().Enabled)
{
Il2CppStringArray appliedUpgrades = tower.towerModel.appliedUpgrades;
if (appliedUpgrades != null && ((Il2CppArrayBase<string>)(object)appliedUpgrades).Contains("Sticky Bomb") && !((Mutable)tower).IsMutatedBy("StickyBombAttackSpeed"))
{
((Mutable)tower).AddMutator((BehaviorMutator)new RateSupportMutator(true, "StickyBombAttackSpeed", 1f, -100, (BuffIndicatorModel)null, false, (DisplayModel)null)
{
cantBeAbsorbed = true
}, -1, true, true, false, true, false, false, false, -1, false, false);
}
}
}
}
}