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.Display; using BTD_Mod_Helper.Extensions; using HarmonyLib; using Il2Cpp; using Il2CppAssets.Scripts.Models; using Il2CppAssets.Scripts.Models.Bloons.Behaviors; using Il2CppAssets.Scripts.Models.Entities; using Il2CppAssets.Scripts.Models.GenericBehaviors; using Il2CppAssets.Scripts.Models.Towers; using Il2CppAssets.Scripts.Models.Towers.Behaviors; 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.Filters; using Il2CppAssets.Scripts.Models.Towers.Projectiles; using Il2CppAssets.Scripts.Models.Towers.Projectiles.Behaviors; using Il2CppAssets.Scripts.Models.Towers.Weapons; using Il2CppAssets.Scripts.Models.Towers.Weapons.Behaviors; using Il2CppAssets.Scripts.Simulation.Bloons; using Il2CppAssets.Scripts.Simulation.SMath; using Il2CppAssets.Scripts.Simulation.SimulationBehaviors; using Il2CppAssets.Scripts.Simulation.Towers; using Il2CppAssets.Scripts.Simulation.Towers.Projectiles; using Il2CppAssets.Scripts.Simulation.Towers.Projectiles.Behaviors; using Il2CppAssets.Scripts.Unity; using Il2CppAssets.Scripts.Unity.Display; using Il2CppAssets.Scripts.Unity.Display.Animation; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppNinjaKiwi.Common; using Il2CppNinjaKiwi.Common.ResourceUtils; using MelonLoader; using Microsoft.CodeAnalysis; using MirrorUniversePaths; using PathsPlusPlus; 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(MirrorUniversePathsMod), "Mirror Universe Paths", "1.0.2", "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("MirrorUniversePaths")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+9365f45d62d86225f7e885a36651e6162ce24af0")] [assembly: AssemblyProduct("MirrorUniversePaths")] [assembly: AssemblyTitle("MirrorUniversePaths")] [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 MirrorUniversePaths { public class MirrorUniversePathsMod : BloonsTD6Mod { } public static class ModHelperData { public const string WorksOnVersion = "55.2"; public const string Version = "1.0.2"; public const string Name = "Mirror Universe Paths"; public const string Description = "Adds a number of alternate tower path branches using Paths++.\nMany paths are inspired by features of tier 3 towers that get overlooked/overwritten by the tier 4 and 5 upgrades in their path, but now have a new chance to shine with reimagined upgrades."; public const string RepoOwner = "doombubbles"; public const string PrevRepoName = "mirror-universe-paths"; public const string RepoName = "MirrorUniversePaths"; public const string Dependencies = "doombubbles/PathsPlusPlus"; } } namespace MirrorUniversePaths.TackShooter { public class CompleteCombustion : UpgradePlusPlus { public override int Cost => 45000; public override int Tier => 5; public override string Portrait => "446b34124f7085149b719079c0d7993b"; public override string Description => "Impossibly hot tacks roast Bloons with blazing efficiency."; public override string DetailedDescription => "Same meteor attack as base 5xx. Tack damage increased to 8 with +4 to MOABs, ranged increased by 11.5, pierce increased by 2x then +3, attack speed is tripled."; public override void ApplyUpgrade(TowerModel towerModel, int tier) { TowerModel tower = GameModelExt.Current.GetTower(TowerType.TackShooter, Math.Clamp(tier, 4, 5), Math.Clamp(((Il2CppArrayBase)(object)towerModel.tiers)[1], 0, 2), Math.Clamp(((Il2CppArrayBase)(object)towerModel.tiers)[2], 0, 2)); towerModel.range = tower.range; TowerModelExt.GetAttackModel(towerModel).range = TowerModelExt.GetAttackModel(tower).range; ProjectileModel projectile = TowerModelExt.GetWeapon(towerModel).projectile; projectile.pierce *= 2f; ProjectileModel projectile2 = TowerModelExt.GetWeapon(towerModel).projectile; projectile2.pierce += 3f; WeaponModel obj = ((Il2CppArrayBase)(object)TowerModelExt.GetAttackModel(towerModel).weapons)[0]; obj.Rate /= 3f; TowerModelBehaviorExt.AddBehavior(towerModel, ModelExt.Duplicate(TowerModelExt.GetAttackModel(tower, "Meteor"))); } } public class SuperheatedTacks : UpgradePlusPlus { public override int Cost => 3500; public override int Tier => 4; public override string? Portrait => "95777a58654f7ee428f180492731dd90"; public override string Description => "Shoots superheated tacks that deal immense damage with slightly more pierce."; public override string DetailedDescription => "Tacks damage is increase to 5, and they have +2 pierce and +2 radius."; public override void ApplyUpgrade(TowerModel towerModel, int tier) { //IL_0114: Unknown result type (might be due to invalid IL or missing references) TowerModel tower = GameModelExt.Current.GetTower(TowerType.TackShooter, Math.Clamp(tier, 4, 5), Math.Clamp(((Il2CppArrayBase)(object)towerModel.tiers)[1], 0, 2), Math.Clamp(((Il2CppArrayBase)(object)towerModel.tiers)[2], 0, 2)); WeaponModel weapon = TowerModelExt.GetWeapon(tower); WeaponModel weapon2 = TowerModelExt.GetWeapon(towerModel); ProjectileModel projectile = weapon2.projectile; projectile.pierce += 2f; projectile.radius = 2f; TowerModel tower2 = GameModelExt.Current.GetTower(TowerType.TackShooter, Math.Clamp(tier, 4, 5), 0, 0); ProjectileModel descendant = ((Model)tower2).GetDescendant(); ProjectileModelBehaviorExt.GetBehavior(projectile).damage = ProjectileModelBehaviorExt.GetBehavior(descendant).damage; foreach (DamageModifierForTagModel behavior in ProjectileModelBehaviorExt.GetBehaviors(descendant)) { ProjectileModelBehaviorExt.AddBehavior(projectile, ModelExt.Duplicate(behavior)); projectile.hasDamageModifiers = true; } ProjectileModelExt.ApplyDisplay(projectile); if (((UpgradePlusPlus)this).Tier == tier) { WeaponModelExt.SetEject(weapon2, WeaponModelExt.GetEject(weapon), false, false, false); } TowerModelExt.SetDisplay(towerModel, ((EntityModel)tower).display); } } public class SuperHotTack : ModDisplay { public override PrefabReference BaseDisplayReference => ((Model)Game.instance.model.GetTower(TowerType.TackShooter, 3, 0, 0)).GetDescendant().display; public override void ModifyDisplayNodeAsync(UnityDisplayNode node, Action onComplete) { ((ModDisplay)this).UseNode(((Model)TowerModelExt.GetAttackModel(Game.instance.model.GetTower(TowerType.TackShooter, 5, 0, 0), "Meteor")).GetDescendant().display.AssetGUID, (Action)delegate(UnityDisplayNode meteor) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) Transform val = Object.Instantiate(((Component)meteor).transform.GetChild(0), ((Component)node).transform, false); OffsetTowardsCamera component = ((Component)val).gameObject.GetComponent(); component.offset = 0f; component.Start(); ((Behaviour)component).enabled = false; val.localPosition = new Vector3(0f, 0f, -5f); ((Component)val.GetChild(0)).gameObject.SetActive(false); ((Component)val.GetChild(1)).gameObject.SetActive(false); ParticleSystem componentInChildren = ((Component)val.GetChild(2)).GetComponentInChildren(); componentInChildren.emissionRate *= 3f; componentInChildren.maxParticles *= 3; onComplete(); }); } } public class TackFireNonRingPath : PathPlusPlus { public override string Tower => TowerType.TackShooter; public override int ExtendVanillaPath => 0; public override bool UseUpgradedTowerModels => false; public override string DisplayName => "Fiery Tacks"; public override string Description => "Continues shooting tacks instead of replacing them with the ring of fire."; } } namespace MirrorUniversePaths.SuperMonkey { public class SunDemigod : UpgradePlusPlus { public override int Cost => 50000; public override int Tier => 4; public override string Description => "Ascends further along the path of solar divinity."; public override string DetailedDescription => "Attack speed is halved, shoots 3 Sun Temple projectiles at 80% scale that have 5 damage and 20 pierce, range increased by +15."; public override void ApplyUpgrade(TowerModel towerModel, int tier) { WeaponModel weapon = TowerModelExt.GetWeapon(towerModel); TowerModel tower = Game.instance.model.GetTower(TowerType.SuperMonkey, Math.Clamp(tier, 4, 5), Math.Clamp(((Il2CppArrayBase)(object)towerModel.tiers)[1], 0, 2), Math.Clamp(((Il2CppArrayBase)(object)towerModel.tiers)[2], 0, 2)); if (tier == ((UpgradePlusPlus)this).Tier) { weapon.Rate *= 2f; SunDemigodDisplay sunDemigodDisplay = ModContent.GetInstances().FirstOrDefault((SunDemigodDisplay d) => d.Bot == ((Il2CppArrayBase)(object)towerModel.tiers)[2] && d.Mid == ((Il2CppArrayBase)(object)towerModel.tiers)[1]); if (sunDemigodDisplay != null) { ((ModDisplay)sunDemigodDisplay).Apply(towerModel); } } towerModel.range = tower.range; TowerModelExt.GetAttackModel(towerModel).range = TowerModelExt.GetAttackModel(tower).range; ProjectileModel val = (weapon.projectile = ModelExt.Duplicate(TowerModelExt.GetWeapon(tower).projectile)); ProjectileModel val3 = val; val3.scale = 0.8f; val3.radius *= 0.8f; ProjectileModelExt.SetDisplay(val3); ModelExt.SetName(TowerModelBehaviorExt.GetBehavior(towerModel), ((ModContent)this).Name); } } public class SunDemigodDisplay : ModDisplay { public override PrefabReference BaseDisplayReference => ((EntityModel)Game.instance.model.GetTower(TowerType.SuperMonkey, 3, Mid, Bot)).display; public int Mid { get; init; } public int Bot { get; init; } public override string Name => $"{((ModContent)this).Name}4{Mid}{Bot}"; public override IEnumerable Load() { yield return (ModContent)(object)this; yield return (ModContent)(object)new SunDemigodDisplay { Mid = 1 }; yield return (ModContent)(object)new SunDemigodDisplay { Mid = 2 }; yield return (ModContent)(object)new SunDemigodDisplay { Bot = 1 }; yield return (ModContent)(object)new SunDemigodDisplay { Bot = 2 }; } public override void ModifyDisplayNodeAsync(UnityDisplayNode node, Action onComplete) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) RendererExt.AdjustHSV(UnityDisplayNodeExt.GetMeshRenderer(node, 0, true), 0f, -0.5f, 0f, (Color?)new Color(1f, 73f / 85f, 0f), 0.1f); ((ModDisplay)this).UseNode(AttackModelBehaviorExt.GetBehavior(TowerModelExt.GetAttackModel(Game.instance.model.GetTower(TowerType.SuperMonkey, 4, Mid, Bot))).display.AssetGUID, (Action)delegate(UnityDisplayNode head) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) Transform val = Object.Instantiate(((Component)head).transform.GetChild(0), UnityDisplayNodeExt.GetBone(node, "SuperMonkeyRig:MonkeyJnt_Head"), false); GameObjectExt.RemoveComponent(((Component)val).gameObject); GameObjectExt.RemoveComponent(((Component)val).gameObject); GameObjectExt.RemoveComponent(((Component)val).gameObject); val.localPosition = new Vector3(10f, 0f, 0.15f); val.localRotation = Quaternion.Euler(0f, 180f, 270f); val.localScale = new Vector3(0.6f, 0.6f, 0.6f); RendererExt.AdjustHSV((Renderer)(object)((Component)val).GetComponentInChildren(), 0f, -0.5f, 0f, (Color?)new Color(1f, 73f / 85f, 0f), 0.1f); onComplete(); }); } } public class TempleBlastDisplay : ModDisplay { public override PrefabReference BaseDisplayReference => TowerModelExt.GetWeapon(Game.instance.model.GetTower(TowerType.SuperMonkey, 4, 0, 0)).projectile.display; public override void ModifyDisplayNode(UnityDisplayNode node) { foreach (OffsetTowardsCamera componentsInChild in ((Component)node).gameObject.GetComponentsInChildren(true)) { componentsInChild.offset = 0f; componentsInChild.Start(); } } } public class SunGod : UpgradePlusPlus { public override int Cost => 100000; public override int Tier => 5; public override string Icon => "a04463dfa8e4c704c8b660dd6e5d64b4"; public override string? Portrait => "df307dbea1cab0e4285be3949c4d949a"; public override string Description => "Tremble before the AWESOME power of the Sun God!! *trueness not guaranteed*"; public override string DetailedDescription => "Attack speed is doubled, shoots 5 True Sun God projectiles at 80% scale that have 15 damage and 20 pierce."; public override void ApplyUpgrade(TowerModel towerModel) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) TowerModelExt.SetDisplay(towerModel); WeaponModel weapon = TowerModelExt.GetWeapon(towerModel); ProjectileModelExt.SetDisplay(weapon.projectile); WeaponModelExt.SetEject(weapon, new Vector3(2f, 5f, 42f), false, false, false); ((ArcEmissionModel)((Model)weapon).GetDescendant()).Count = 5; } } public class SunGodDisplay : ModDisplay { public override PrefabReference BaseDisplayReference => AttackModelBehaviorExt.GetBehavior(TowerModelExt.GetAttackModel(Game.instance.model.GetTower(TowerType.SuperMonkey, 5, 0, 0))).display; public override float Scale => 0.75f; } public class GodBlastDisplay : ModDisplay { public override PrefabReference BaseDisplayReference => TowerModelExt.GetWeapon(Game.instance.model.GetTower(TowerType.SuperMonkey, 5, 0, 0)).projectile.display; public override void ModifyDisplayNode(UnityDisplayNode node) { foreach (OffsetTowardsCamera componentsInChild in ((Component)node).gameObject.GetComponentsInChildren(true)) { componentsInChild.offset = 0f; componentsInChild.Start(); } } } public class SunNonTemplePath : PathPlusPlus { public override string Tower => TowerType.SuperMonkey; public override int ExtendVanillaPath => 0; public override bool UseUpgradedTowerModels => false; public override string DisplayName => "Non-Temple"; public override string Description => "Doesn't become a Temple or enact sacrifices."; } public class VengefulAvatar : UpgradePlusPlus { public override int Cost => 100000; public override int Tier => 4; public override string Portrait => "de6fb5caa564ca44eb80cfcbb936554a"; public override string Description => "Walks the path of vengeance to enact untold ruin onto Bloons."; public override string DetailedDescription => "Projectile damage increased to 13, can hit Purple Bloons, range increased by +15"; public override void ApplyUpgrade(TowerModel towerModel) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) TowerModelExt.SetDisplay(towerModel); towerModel.range += 15f; AttackModel attackModel = TowerModelExt.GetAttackModel(towerModel); attackModel.range += 15f; ProjectileModel projectile = TowerModelExt.GetWeapon(towerModel).projectile; ProjectileModelExt.SetDisplay(projectile, "e4abb3d789fca4747a7459d21c835472"); DamageModel damageModel = ProjectileModelExt.GetDamageModel(projectile); damageModel.immuneBloonProperties = (BloonProperties)(damageModel.immuneBloonProperties & -9); damageModel.immuneBloonPropertiesOriginal = (BloonProperties)(damageModel.immuneBloonPropertiesOriginal & -9); damageModel.damage = 13f; ModelExt.SetName(TowerModelBehaviorExt.GetBehavior(towerModel), ((ModContent)this).Name); } } public class VengefulAvatarDisplay : ModDisplay { public override string BaseDisplay => "36d3f05381187cf4da168f4676076159"; public override float Scale => 1.75f; } public class VengefulGod : UpgradePlusPlus { public override int Cost => 500000; public override int Tier => 5; public override string Portrait => "afd7922791d61014ca6d601526f94c1e"; public override string Description => "There can be only one."; public override string DetailedDescription => "Attack speed is doubled, shoots 5 Vengeful True Sun God projectiles at 80% scale that have 30 damage and 30 pierce, range increased by +15."; public override void ApplyUpgrade(TowerModel towerModel) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) TowerModelExt.SetDisplay(towerModel); WeaponModel weapon = TowerModelExt.GetWeapon(towerModel); ProjectileModelExt.SetDisplay(weapon.projectile); WeaponModelExt.SetEject(weapon, new Vector3(2f, 5f, 42f), false, false, false); ((ArcEmissionModel)((Il2CppObjectBase)weapon.emission).Cast()).Count = 5; weapon.Rate /= 2f; ProjectileModel projectile = weapon.projectile; projectile.pierce += 24f; weapon.projectile.radius = 8f; weapon.projectile.scale = 0.8f; DamageModel damageModel = ProjectileModelExt.GetDamageModel(weapon.projectile); damageModel.damage += 17f; BloonProperties immuneBloonProperties = (BloonProperties)0; damageModel.immuneBloonPropertiesOriginal = (BloonProperties)0; damageModel.immuneBloonProperties = immuneBloonProperties; } } public class VengefulGodDisplay : ModDisplay { public override string BaseDisplay => "45d40b8795fd36c4eadb7856f96a180c"; public override float Scale => 0.75f; } public class VengefulGodBlastDisplay : ModDisplay { public override string BaseDisplay => "4fb0baaa656410f4ba1f2fd07b37eda4"; public override void ModifyDisplayNode(UnityDisplayNode node) { foreach (OffsetTowardsCamera componentsInChild in ((Component)node).gameObject.GetComponentsInChildren(true)) { componentsInChild.offset = 0f; componentsInChild.Start(); } } } public class VengefulNonTemplePath : PathPlusPlus { public override string Tower => TowerType.SuperMonkey; public override int ExtendVanillaPath => 0; public override bool UseUpgradedTowerModels => false; public override string DisplayName => "Vengeful Non-Temple"; public override string Description => "Doesn't become a Temple or enact sacrifices, but is vengeful about it."; } } namespace MirrorUniversePaths.SniperMonkey { public class AssaultMOAB : UpgradePlusPlus { public override int Cost => 6300; public override int Tier => 4; public override string DisplayName => "Assault MOAB"; public override string Description => "Deadly Precision's +50 Ceramic damage bonus now also applies to MOAB-class Bloons."; public override void ApplyUpgrade(TowerModel towerModel, int tier) { Il2CppGenericIEnumerable.ForEach(((Model)towerModel).GetDescendants(), (Action)delegate(ProjectileModel proj) { if (!ProjectileModelBehaviorExt.HasBehavior(proj)) { return; } ProjectileModelBehaviorExt.RemoveBehaviors(proj); foreach (DamageModifierForTagModel item in from damageModifier in ProjectileModelBehaviorExt.GetBehaviors(proj) where damageModifier.tag == "Ceramic" select damageModifier) { item.tag += ",Moabs"; item.tags = StringExtensions.CommaSeperatedListToStringArray(item.tag, true, true); } }); if (tier == ((UpgradePlusPlus)this).Tier) { AssaultMOABDisplay assaultMOABDisplay = ModContent.GetInstances().FirstOrDefault((AssaultMOABDisplay d) => d.Bot == ((Il2CppArrayBase)(object)towerModel.tiers)[2] && d.Mid == ((Il2CppArrayBase)(object)towerModel.tiers)[1]); if (assaultMOABDisplay != null) { ((ModDisplay)assaultMOABDisplay).Apply(towerModel); } } } } public class AssaultMOABDisplay : ModDisplay { public override PrefabReference BaseDisplayReference => ((EntityModel)Game.instance.model.GetTower(TowerType.SniperMonkey, 4, Mid, Bot)).display; public int Mid { get; init; } public int Bot { get; init; } public override string Name => $"{((ModContent)this).Name}4{Mid}{Bot}"; public override IEnumerable Load() { yield return (ModContent)(object)this; yield return (ModContent)(object)new AssaultMOABDisplay { Mid = 1 }; yield return (ModContent)(object)new AssaultMOABDisplay { Mid = 2 }; yield return (ModContent)(object)new AssaultMOABDisplay { Bot = 1 }; yield return (ModContent)(object)new AssaultMOABDisplay { Bot = 2 }; } public override void ModifyDisplayNode(UnityDisplayNode node) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) Renderer meshRenderer = UnityDisplayNodeExt.GetMeshRenderer(node, 0, true); RendererExt.AdjustHSV(meshRenderer, 0f, -1f, 0f, (Color?)new Color(4f / 15f, 0.34901962f, 11f / 85f), 0.25f); RendererExt.AdjustHSV(meshRenderer, 0f, -1f, 0f, (Color?)new Color(0.16078432f, 0.2f, 0.0627451f), 0.25f); RendererExt.AdjustHSV(meshRenderer, 0f, -1f, 0f, (Color?)new Color(0.41960785f, 0.49803922f, 0.16078432f), 0.25f); RendererExt.AdjustHSV(meshRenderer, 0f, -1f, 0f, (Color?)new Color(0.64705884f, 0.75686276f, 0.050980393f), 0.25f); RendererExt.SetOutlineColor(meshRenderer, new Color(0.24313726f, 0.24313726f, 0.24313726f)); } } public class ExecuteMOAB : UpgradePlusPlus { public override int Cost => 32000; public override int Tier => 5; public override string DisplayName => "Execute MOAB"; public override string Description => "Deals 10x damage to MOAB-class Bloons that are below 25% health."; public override void ApplyUpgrade(TowerModel towerModel) { Il2CppGenericIEnumerable.ForEach(((Model)towerModel).GetDescendants(), (Action)delegate(ProjectileModel proj) { //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_0041: Expected O, but got Unknown //IL_0047: Expected O, but got Unknown if (ProjectileModelBehaviorExt.HasBehavior(proj)) { proj.hasDamageModifiers = true; Args val = new Args { tag = "Moabs", damageMultiplier = 10f }; ((ModelArgs)val).name = "EXECUTE_25"; ProjectileModelBehaviorExt.AddBehavior(proj, CreateDamageModifierForTagModelExt.Create(val)); } }); TowerModelExt.SetDisplay(towerModel); } } [HarmonyPatch(typeof(DamageModifierForTagModel), "DoesApplyBonus")] internal static class DamageModifierForTagModel_DoesApplyBonus { [HarmonyPostfix] internal static void Postfix(DamageModifierForTagModel __instance, Bloon bloon, ref bool __result) { if (((Model)__instance).name.Contains("EXECUTE") && int.TryParse(((Model)__instance).name.Split('_')[^1], out var result) && bloon.Health * 100 > bloon.bloonModel.maxHealth * result) { __result = false; } } } public class ExecuteMOABDisplay : ModDisplay { public override PrefabReference BaseDisplayReference => ((EntityModel)Game.instance.model.GetTower(TowerType.SniperMonkey, 5, 0, 0)).display; public override void ModifyDisplayNode(UnityDisplayNode node) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) Renderer meshRenderer = UnityDisplayNodeExt.GetMeshRenderer(node, 1, true); RendererExt.AdjustHSV(meshRenderer, 0f, -1f, 0f, (Color?)new Color(4f / 15f, 0.34901962f, 11f / 85f), 0.25f); RendererExt.AdjustHSV(meshRenderer, 0f, -1f, 0f, (Color?)new Color(0.16078432f, 0.2f, 0.0627451f), 0.25f); RendererExt.AdjustHSV(meshRenderer, 0f, -1f, 0f, (Color?)new Color(0.41960785f, 0.49803922f, 0.16078432f), 0.25f); RendererExt.AdjustHSV(meshRenderer, 0f, -1f, 0f, (Color?)new Color(0.64705884f, 0.75686276f, 0.050980393f), 0.25f); RendererExt.SetOutlineColor(meshRenderer, new Color(0.24313726f, 0.24313726f, 0.24313726f)); } } public class SniperNonMaimPath : PathPlusPlus { public override string Tower => TowerType.SniperMonkey; public override int ExtendVanillaPath => 0; public override bool UseUpgradedTowerModels => true; public override string DisplayName => "MOAB DPS"; public override string Description => "Focuses on pure MOAB damage rather than stall/support."; } } namespace MirrorUniversePaths.NinjaMonkey { public class Boomjitsu : UpgradePlusPlus { public override int Cost => 5000; public override int Tier => 4; public override string Description => "All shurikens are now replaced with flash bombs which deal bonus damage to MOAB-Class Bloons. Caltrops explode too."; public override string DetailedDescription => "Flash bombs are every attack instead of every 4th. Flash bombs deal +4 damage to MOABs. Caltrops create a flash bomb explosion on exhaust."; public override void ApplyUpgrade(TowerModel towerModel, int tier) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Expected O, but got Unknown //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Expected O, but got Unknown //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Expected O, but got Unknown TowerModelBehaviorExt.RemoveBehavior(towerModel, "StickyBomb"); WeaponModel val = ((Il2CppArrayBase)(object)TowerModelExt.GetAttackModel(towerModel).weapons)[0]; ProjectileModel projectile = val.projectile; ProjectileModel projectile2 = WeaponModelBehaviorExt.GetBehavior(val).projectile; ProjectileModel descendant = ((Model)projectile2).GetDescendant(); DamageModifierForBloonStateModel behavior = ProjectileModelBehaviorExt.GetBehavior(projectile); ProjectileModelBehaviorExt.AddBehavior(descendant, CreateDamageModifierForTagModelExt.Create(new Args { tag = "Moabs", damageMultiplier = behavior.damageMultiplier, damageAddative = behavior.damageAdditive })); ProjectileModelBehaviorExt.GetBehavior(descendant).dontRefreshDuration = true; WeaponModelBehaviorExt.RemoveBehavior(val); WeaponModelExt.SetProjectile(val, projectile2); ProjectileModel descendant2 = ((Model)TowerModelExt.GetAttackModel(towerModel, "Caltrops")).GetDescendant(); ProjectileModelBehaviorExt.AddBehavior(descendant2, CreateCreateProjectileOnExhaustFractionModelExt.Create(new Args { projectile = ModelExt.Duplicate(descendant), fraction = 1f, durationfraction = -1f, emission = (EmissionModel)(object)CreateSingleEmissionModelExt.Create() })); ProjectileModelBehaviorExt.AddBehavior(descendant2, CreateCreateEffectOnExhaustFractionModelExt.Create(new Args { effectModel = ProjectileModelBehaviorExt.GetBehavior(projectile2).effectModel, fraction = 1f, durationFraction = -1f })); CreateSoundOnProjectileCollisionModel behavior2 = ProjectileModelBehaviorExt.GetBehavior(projectile2); ProjectileModelBehaviorExt.AddBehavior(descendant2, CreateCreateSoundOnProjectileExhaustModelExt.Create(new Args { sound1 = behavior2.sound1, sound2 = behavior2.sound2, sound3 = behavior2.sound3, sound4 = behavior2.sound4, sound5 = behavior2.sound5 })); if (tier == ((UpgradePlusPlus)this).Tier) { BoomjitsuDisplay boomjitsuDisplay = ModContent.GetInstances().FirstOrDefault((BoomjitsuDisplay d) => d.Top == ((Il2CppArrayBase)(object)towerModel.tiers)[0] && d.Mid == ((Il2CppArrayBase)(object)towerModel.tiers)[1]); if (boomjitsuDisplay != null) { ((ModDisplay)boomjitsuDisplay).Apply(towerModel); } } } } public class BoomjitsuDisplay : ModDisplay { public override PrefabReference BaseDisplayReference => ((EntityModel)Game.instance.model.GetTower(TowerType.NinjaMonkey, Top, Mid, 4)).display; public int Top { get; init; } public int Mid { get; init; } public override string Name => $"{((ModContent)this).Name}{Top}{Mid}{4}"; public override IEnumerable Load() { yield return (ModContent)(object)this; yield return (ModContent)(object)new BoomjitsuDisplay { Top = 1 }; yield return (ModContent)(object)new BoomjitsuDisplay { Top = 2 }; yield return (ModContent)(object)new BoomjitsuDisplay { Mid = 1 }; yield return (ModContent)(object)new BoomjitsuDisplay { Mid = 2 }; } public override void ModifyDisplayNode(UnityDisplayNode node) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) UnityDisplayNodeExt.RemoveBone(node, "NinjaMonkeyRig:Dart", false); int num = -155; float num2 = -0.57f; float num3 = -0.44f; RendererExt.AdjustHSV(UnityDisplayNodeExt.GetMeshRenderer(node, 0, true), (float)num, num2, num3, (Color?)new Color(1f, 0.21960784f, 0f), 0.3f); RendererExt.AdjustHSV(UnityDisplayNodeExt.GetMeshRenderer(node, 0, true), (float)num, num2, num3, (Color?)new Color(0.5803922f, 0.21960784f, 0f), 0.3f); RendererExt.AdjustHSV(UnityDisplayNodeExt.GetMeshRenderer(node, 0, true), (float)num, num2, num3, (Color?)new Color(0.32156864f, 0.21960784f, 0f), 0.3f); } } public class GrandBlasterNinja : UpgradePlusPlus { public override int Cost => 40000; public override int Tier => 5; public override string DisplayName => "Grand-Blaster Ninja"; public override string Description => "Explosions now stun MOAB-class Bloons and deal way more damage."; public override string DetailedDescription => "Applies the base xx5 effects of flash bombs stunning MOABs for .325s, flash bombs having 10 base damage, and caltrops having 5 base damage with +5 to ceramic. Flash bomb bonus MOAB damage is now +19."; public override void ApplyUpgrade(TowerModel towerModel, int tier) { if (tier == ((UpgradePlusPlus)this).Tier) { ((ModDisplay)ModContent.GetInstance()).Apply(towerModel); } } } public class GrandBlasterNinjaDisplay : ModDisplay { public override PrefabReference BaseDisplayReference => ((EntityModel)Game.instance.model.GetTower(TowerType.NinjaMonkey, 0, 0, 5)).display; public override void ModifyDisplayNode(UnityDisplayNode node) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) UnityDisplayNodeExt.RemoveBone(node, "Dart", false); RendererExt.AdjustHSV(UnityDisplayNodeExt.GetMeshRenderer(node, 0, true), -157f, 0.88f, 0.32f, (Color?)new Color(0.96862745f, 0.21960784f, 0f), 0.5f); RendererExt.AdjustHSV(UnityDisplayNodeExt.GetMeshRenderer(node, 0, true), -157f, 0.88f, 0.32f, (Color?)new Color(63f / 85f, 14f / 85f, 0f), 0.5f); } } public class NinjaBombPath : PathPlusPlus { public override string Tower => TowerType.NinjaMonkey; public override int ExtendVanillaPath => 2; public override bool UseUpgradedTowerModels => true; public override string DisplayName => "Bomb"; public override string Description => "Amplifies Flash Bombs instead of getting Sticky Bombs."; } } namespace MirrorUniversePaths.MonkeySub { public class BloontoniumDarts : UpgradePlusPlus { public override int Cost => 2400; public override int Tier => 4; public override string Description => "Darts do more damage and leave behind radioactive fallout that irradiates Bloons. Twin Guns makes radiation damage faster, Barbed Darts makes it last longer."; public override string DetailedDescription => "Dart damage increased to 2 like base 4xx, creates Fallout projectiles on first hitting a Bloon that have the same pierce, damage, and damage interval as the base 4xx attack. Lifespan is 2s, or 5s with Barbed Darts."; public override string Portrait => "dc8d549c38103f54a82f4682608b252a"; public override void ApplyUpgrade(TowerModel towerModel, int tier) { //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Expected O, but got Unknown //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Expected O, but got Unknown //IL_0219: Expected O, but got Unknown TowerModel paragonTower = Game.instance.model.GetParagonTower(TowerType.MonkeySub); AttackModel attackModel = TowerModelExt.GetAttackModel(GameModelExt.Current.GetTower(TowerType.MonkeySub, Math.Clamp(tier, 4, 5), Math.Clamp(((Il2CppArrayBase)(object)towerModel.tiers)[1], 0, 2), Math.Clamp(((Il2CppArrayBase)(object)towerModel.tiers)[2], 0, 2)), "Submerge"); WeaponModel val = ((Il2CppArrayBase)(object)attackModel.weapons)[1]; ProjectileModel val2 = ModelExt.Duplicate(((Model)((Model)paragonTower).GetDescendant()).GetDescendant().projectile); val2.pierce = val.projectile.pierce; ProjectileModelBehaviorExt.RemoveBehavior(val2); ProjectileModelBehaviorExt.GetBehavior(val2).Lifespan = (((Il2CppArrayBase)(object)towerModel.appliedUpgrades).Contains("Barbed Darts") ? 5 : 2); ProjectileModelBehaviorExt.GetBehavior(val2).damage = ((Model)val).GetDescendant().damage; ProjectileModelBehaviorExt.RemoveBehaviors(val2); ProjectileModelBehaviorExt.AddBehavior(val2, ModelExt.Duplicate(((Model)val).GetDescendant())); foreach (DamageModifierForTagModel behavior2 in ProjectileModelBehaviorExt.GetBehaviors(val.projectile)) { ProjectileModelBehaviorExt.AddBehavior(val2, ModelExt.Duplicate(behavior2)); val2.hasDamageModifiers = true; } ClearHitBloonsModel behavior = ProjectileModelBehaviorExt.GetBehavior(val2); behavior.interval = val.rate; behavior.intervalFrames = (int)(behavior.interval / 60f); val2.UpdateCollisionPassList(); if (tier == ((UpgradePlusPlus)this).Tier) { val2.scale *= 0.75f; val2.radius *= 0.75f; } ProjectileModel projectile = TowerModelExt.GetWeapon(towerModel).projectile; Il2CppGenericIEnumerable.ForEach(((Model)projectile).GetDescendants(), (Action)delegate(ProjectileModel proj) { if (proj.id.Contains("Airburst")) { ProjectileModelExt.SetDisplay(proj); } }); Args val3 = new Args { projectile = val2 }; ((ModelArgs)val3).name = "FIRST_CONTACT"; val3.emission = (EmissionModel)(object)CreateEmissionAtClosestPathSegmentModelExt.Create(new Args { count = 1 }); ProjectileModelBehaviorExt.AddBehavior(projectile, CreateCreateProjectileOnContactModelExt.Create(val3)); } } public class GreenAirburstDart : ModDisplay { public override string BaseDisplay => "8ac212675d4760541a5f9bcccad5ccf7"; public override void ModifyDisplayNode(UnityDisplayNode node) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) ((Renderer)UnityDisplayNodeExt.GetRenderer(node, true)).material.color = new Color(0f, 1f, 0.5f, 1f); } } [HarmonyPatch] internal static class CreateProjectileOnContact_Collide { private static IEnumerable TargetMethods() { yield return AccessTools.Method(typeof(CreateProjectileOnContact), "Collide", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(CreateProjectileOnContact), "CollideMap", (Type[])null, (Type[])null); } [HarmonyPrefix] internal static bool Prefix(CreateProjectileOnContact __instance) { return ((ProjectileBehavior)__instance).projectile == null || !((Model)__instance.createProjectileOnContactModel).name.Contains("FIRST_CONTACT") || ((ProjectileBehavior)__instance).projectile.collidedWith.Count <= 1; } } public class PeriscopeTargeting : UpgradePlusPlus { public override int Cost => 700; public override int Tier => 3; public override string Description => "Allows Monkey Sub to detect and deal extra damage to Camo Bloons."; public override string DetailedDescription => "Grants camo detection, all projectiles deal bonus camo damage equal to their base damage."; public override string Portrait => "4f2d9eddfc769c4409550715b62adfe2"; public override void ApplyUpgrade(TowerModel towerModel) { TowerModelBehaviorExt.RemoveBehavior(towerModel); TowerModelBehaviorExt.RemoveBehavior(towerModel); TowerModelBehaviorExt.RemoveBehavior(towerModel); TowerModelBehaviorExt.RemoveBehavior(towerModel, "Submerge"); TowerModelBehaviorExt.RemoveBehavior(towerModel); AttackModelBehaviorExt.RemoveBehavior(TowerModelExt.GetAttackModel(towerModel)); } public override void LateApplyUpgrade(TowerModel towerModel) { Il2CppGenericIEnumerable.ForEach(((Model)towerModel).GetDescendants(), (Action)delegate(FilterInvisibleModel model) { model.isActive = false; }); Il2CppGenericIEnumerable.ForEach(((Model)towerModel).GetDescendants(), (Action)delegate(ProjectileModel model) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown DamageModel val = default(DamageModel); if (ProjectileModelBehaviorExt.HasBehavior(model, ref val)) { ProjectileModelBehaviorExt.AddBehavior(model, CreateDamageModifierForTagModelExt.Create(new Args { tag = "Camo", damageAddative = val.damage, damageMultiplier = 1f })); model.hasDamageModifiers = true; } }); } } public class RbmkFallout : UpgradePlusPlus { public override int Cost => 28000; public override int Tier => 5; public override string DisplayName => "RBMK Fallout"; public override string Description => "Radioactive Bloontonium Molecular Killzone. Darts and radiation tear apart Bloons at an atomic level, inflicting far more than 3.6 Roentgen."; public override string DetailedDescription => "Dart damage increased to 5 like base 5xx, Fallout projectiles are 33% larger, and have the same pierce, damage and damage interval as the base 5xx attack."; public override string Portrait => "934eeddc6fcfe8349afa34ad14ae3afc"; public override void ApplyUpgrade(TowerModel towerModel) { } } public class SubNonSubmergePath : PathPlusPlus { public override string Tower => TowerType.MonkeySub; public override int ExtendVanillaPath => 0; public override bool UseUpgradedTowerModels => true; public override string DisplayName => "Non-Submerge"; public override string Description => "Uses radioactive power for extra damage without submerging."; } } namespace MirrorUniversePaths.EngineerMonkey { public class EngineerNailPath : PathPlusPlus { public override string Tower => TowerType.EngineerMonkey; public override int ExtendVanillaPath => 2; public override bool UseUpgradedTowerModels => true; public override string DisplayName => "Nail Gun"; public override string Description => "Empowers Nail attacks instead of using Traps."; public static IEnumerable Attacks(TowerModel towerModel) { yield return TowerModelBehaviorExt.GetBehavior(towerModel); AttackModel sentrySpawner = default(AttackModel); if (!TowerModelBehaviorExt.HasBehavior(towerModel, "Spawner", ref sentrySpawner)) { yield break; } foreach (TowerModel sentry in Il2CppGenericIEnumerable.AsIEnumerable(((Model)sentrySpawner).GetDescendants())) { yield return TowerModelExt.GetAttackModel(sentry); } } public static IEnumerable Nails(TowerModel towerModel) { return Attacks(towerModel).SelectMany((AttackModel attack) => from projectileModel in Il2CppGenericIEnumerable.AsIEnumerable(((Model)attack).GetDescendants()) where ProjectileModelBehaviorExt.HasBehavior(projectileModel) && ProjectileModelBehaviorExt.HasBehavior(projectileModel) select projectileModel); } } public class GalvanizedNail : ModDisplay { public override PrefabReference BaseDisplayReference => ((Model)Game.instance.model.GetTower(TowerType.EngineerMonkey, 0, 0, 4)).GetDescendant().display; public override void ModifyDisplayNode(UnityDisplayNode node) { UnityDisplayNodeExt.GetRenderer(node, true).sprite = ((ModContent)this).GetSprite(((ModContent)this).Name, 10f); } } public class GalvanizedNails : UpgradePlusPlus { public override int Cost => 3600; public override int Tier => 4; public override string Description => "Nails deal significantly increased damage, can pop all Bloon types, and give increased cash per pop."; public override string DetailedDescription => "Nail damage increased by +2, pops all Bloon types, cash per pop is 2x, Deconstruction damage bonus increased by 4"; public override void ApplyUpgrade(TowerModel towerModel, int tier) { //IL_001d: 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_0034: Expected O, but got Unknown //IL_006f: 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) int num = 2; AttackModel val = default(AttackModel); if (TowerModelBehaviorExt.HasBehavior(towerModel, "BloonTrap", ref val)) { EatBloonModel descendant = ((Model)val).GetDescendant(); AttackModelBehaviorExt.AddBehavior(val, CreateCashIncreaseModelExt.Create(new Args { multiplier = descendant.rbeCashMultiplier })); TowerModelBehaviorExt.RemoveBehavior(towerModel, val); } foreach (ProjectileModel item in EngineerNailPath.Nails(towerModel)) { DamageModel damageModel = ProjectileModelExt.GetDamageModel(item); BloonProperties immuneBloonProperties = (BloonProperties)0; damageModel.immuneBloonPropertiesOriginal = (BloonProperties)0; damageModel.immuneBloonProperties = immuneBloonProperties; damageModel.damage += (float)num; ProjectileModelExt.SetDisplay(item, ModContent.CreatePrefabReference()); if (!((Il2CppArrayBase)(object)towerModel.appliedUpgrades).Contains("Deconstruction")) { continue; } foreach (DamageModifierForTagModel item2 in from damageModifier in ProjectileModelBehaviorExt.GetBehaviors(item) where ((Il2CppArrayBase)(object)damageModifier.tags).Contains("Moabs") || ((Il2CppArrayBase)(object)damageModifier.tags).Contains("Fortified") select damageModifier) { item2.damageAddative += (float)(num * 2); } } TowerModelBehaviorExt.RemoveBehavior(towerModel, val); } } internal class Nailstorm : UpgradePlusPlus { public override int Cost => 45000; public override int Tier => 5; public override string Description => "Unleashes bucket loads of nails at super speed!"; public override string DetailedDescription => "Shoots 3 nails at a time in a 30° cone, attack speed increased 3x, nail pierce increased by 2x, cash per pop now 3x"; public override void ApplyUpgrade(TowerModel towerModel) { AttackModel behavior = TowerModelBehaviorExt.GetBehavior(towerModel); WeaponModel val = ((Il2CppArrayBase)(object)behavior.weapons)[0]; EmissionWithOffsetsModel val2 = ((Il2CppObjectBase)val.emission).Cast(); val2.spreadProjectilesAcrossMarkers = false; val2.projectileCount = 3; val2.randomRotationCone = 30f; foreach (AttackModel item in EngineerNailPath.Attacks(towerModel)) { WeaponModel obj = ((Il2CppArrayBase)(object)item.weapons)[0]; obj.Rate /= 3f; } foreach (ProjectileModel item2 in EngineerNailPath.Nails(towerModel)) { item2.pierce *= 2f; } } } } namespace MirrorUniversePaths.DartlingGunner { public class DartlingCannonPath : PathPlusPlus { public override string Tower => TowerType.DartlingGunner; public override int ExtendVanillaPath => 0; public override bool UseUpgradedTowerModels => false; public override string DisplayName => "Cannon"; public override string Description => "Continues shooting upgraded laser projectiles rather than switching to solid beams."; } public class Plasma : ModDisplay { public override PrefabReference BaseDisplayReference => ((Il2CppArrayBase)(object)TowerModelExt.GetAttackModel(Game.instance.model.GetTower(TowerType.DartlingGunner, 3, 0, 0)).weapons)[0].projectile.display; public override void ModifyDisplayNode(UnityDisplayNode node) { UnityDisplayNodeExt.GetRenderer(node, true).sprite = ((ModContent)this).GetSprite(((ModContent)this).Name, 10f); } } public class PlasmaCannon : UpgradePlusPlus { public override int Tier => 4; public override int Cost => 10000; public override string Description => "Upgrades to Plasma beams which have extra pierce and even more bonus MOAB damage. Can pop Lead Bloons."; public override string DetailedDescription => "Pierce increased by 5x, projectile scaled 1.25x, can pop leads, bonus MOAB damage increased to +10, laser shock lifespan to 5s"; public override void ApplyUpgrade(TowerModel towerModel, int tier) { //IL_0075: 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_0085: 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_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) ProjectileModel projectile = ((Il2CppArrayBase)(object)TowerModelExt.GetAttackModel(towerModel).weapons)[0].projectile; ((ModDisplay)ModContent.GetInstance()).Apply(projectile); projectile.pierce *= 5f; float radius = projectile.radius; projectile.radius = radius + 1f; projectile.scale = 1.25f; DamageModel damageModel = ProjectileModelExt.GetDamageModel(projectile); damageModel.immuneBloonProperties = (BloonProperties)(damageModel.immuneBloonProperties & -2); damageModel.immuneBloonPropertiesOriginal = (BloonProperties)(damageModel.immuneBloonPropertiesOriginal & -2); ProjectileModelBehaviorExt.GetBehavior(projectile).damageAddative = 10f; AddBehaviorToBloonModel behavior = ProjectileModelBehaviorExt.GetBehavior(projectile); MiscModelExt.ApplyOverlay((ProjectileBehaviorWithOverlayModel)(object)behavior); behavior.mutationId = "LaserShock3"; behavior.lifespan = 5f; behavior.lifespanFrames = (int)(behavior.lifespan * 60f); DamageOverTimeModel behavior2 = AddBehaviorToBloonModelBehaviorExt.GetBehavior(behavior); behavior2.immuneBloonProperties = (BloonProperties)(behavior2.immuneBloonProperties & -2); behavior2.immuneBloonPropertiesOriginal = (BloonProperties)(behavior2.immuneBloonPropertiesOriginal & -2); if (tier == ((UpgradePlusPlus)this).Tier) { PlasmaCannonDisplay plasmaCannonDisplay = ModContent.GetInstances().FirstOrDefault((PlasmaCannonDisplay d) => d.Bot == ((Il2CppArrayBase)(object)towerModel.tiers)[2] && d.Mid == ((Il2CppArrayBase)(object)towerModel.tiers)[1]); if (plasmaCannonDisplay != null) { ((ModDisplay)plasmaCannonDisplay).Apply(towerModel); } } } } public class PlasmaCannonDisplay : ModDisplay { public override PrefabReference BaseDisplayReference => ((EntityModel)Game.instance.model.GetTower(TowerType.DartlingGunner, 4, Mid, Bot)).display; public int Mid { get; init; } public int Bot { get; init; } public override string Name => $"{((ModContent)this).Name}4{Mid}{Bot}"; public override IEnumerable Load() { yield return (ModContent)(object)this; yield return (ModContent)(object)new PlasmaCannonDisplay { Mid = 1 }; yield return (ModContent)(object)new PlasmaCannonDisplay { Mid = 2 }; yield return (ModContent)(object)new PlasmaCannonDisplay { Bot = 1 }; yield return (ModContent)(object)new PlasmaCannonDisplay { Bot = 2 }; } public override void ModifyDisplayNode(UnityDisplayNode node) { //IL_0029: 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) Renderer meshRenderer = UnityDisplayNodeExt.GetMeshRenderer(node, 0, true); RendererExt.AdjustHSV(meshRenderer, -80f, -0.46f, 0f, (Color?)new Color(0.80784315f, 0f, 0f), 0.5f); RendererExt.SetOutlineColor(meshRenderer, new Color(16f / 85f, 0f, 0.35686275f)); } } [HarmonyPatch(typeof(CrossTheStreamsSimBehavior), "GetLineStartAndEndPoints")] internal static class CrossTheStreamsSimBehavior_GetLineStartAndEndPoints { [HarmonyPrefix] internal static bool Prefix(Tower tower) { return !((Il2CppArrayBase)(object)tower.towerModel.appliedUpgrades).Contains(ModContent.GetId()); } } public class PlasmaShock : ModBloonOverlay { public override string BaseOverlay => "LaserShock"; public override void ModifyDisplayNode(UnityDisplayNode node) { SpriteRenderer val = default(SpriteRenderer); MeshRenderer val2 = default(MeshRenderer); foreach (Renderer item in (Il2CppArrayBase)(object)node.genericRenderers) { if (Il2CppSystemObjectExt.Is((Il2CppObjectBase)(object)item, ref val)) { CustomSpriteFrameAnimator component = ((Component)val).gameObject.GetComponent(); for (int i = 0; i < component.frames.Count; i++) { component.frames[i] = ((ModContent)this).GetSprite(((ModContent)this).Name + (i + 1), 10f); } } else if (Il2CppSystemObjectExt.Is((Il2CppObjectBase)(object)item, ref val2)) { RendererExt.SetMainTexture((Renderer)(object)val2, ((ModContent)this).GetTexture(((ModContent)this).Name)); } } } } public class Sun : ModDisplay { public override PrefabReference BaseDisplayReference => ((Il2CppArrayBase)(object)TowerModelExt.GetAttackModel(Game.instance.model.GetTower(TowerType.DartlingGunner, 3, 0, 0)).weapons)[0].projectile.display; public override void ModifyDisplayNode(UnityDisplayNode node) { UnityDisplayNodeExt.GetRenderer(node, true).sprite = ((ModContent)this).GetSprite(((ModContent)this).Name, 10f); } } public class SunCannon : UpgradePlusPlus { public override int Tier => 5; public override int Cost => 50000; public override string Description => "Now shoots 3 beams at once of pure solar energy, with massive pierce and damage."; public override string DetailedDescription => "Shoots 3 projectiles at a time, pierce increased a further 10x, scale now 1.5x total, damage is 30 total with no MOAB bonus, shock life span 30s dealing 20 damage per tick."; public override void ApplyUpgrade(TowerModel towerModel, int tier) { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Expected O, but got Unknown //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Expected O, but got Unknown //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Expected O, but got Unknown AttackModel attackModel = TowerModelExt.GetAttackModel(towerModel); ProjectileModel projectile = ((Il2CppArrayBase)(object)attackModel.weapons)[0].projectile; ((ModDisplay)ModContent.GetInstance()).Apply(projectile); ((Model)attackModel).GetDescendant().count = 3; attackModel.offsetZ += 5f; RotateToPointerModel behavior = AttackModelBehaviorExt.GetBehavior(attackModel); behavior.weaponEjectZ += 5f; projectile.pierce *= 10f; float radius = projectile.radius; projectile.radius = radius + 1f; projectile.scale = 1.5f; DamageModel damageModel = ProjectileModelExt.GetDamageModel(projectile); damageModel.damage = 30f; BloonProperties immuneBloonProperties = (BloonProperties)0; damageModel.immuneBloonPropertiesOriginal = (BloonProperties)0; damageModel.immuneBloonProperties = immuneBloonProperties; ProjectileModelBehaviorExt.RemoveBehavior(projectile); AddBehaviorToBloonModel behavior2 = ProjectileModelBehaviorExt.GetBehavior(projectile); MiscModelExt.ApplyOverlay((ProjectileBehaviorWithOverlayModel)(object)behavior2); behavior2.lifespan = 30f; behavior2.lifespanFrames = (int)(behavior2.lifespan * 60f); AddBehaviorToBloonModelBehaviorExt.GetBehavior(behavior2).damage = 20f; if (tier == ((UpgradePlusPlus)this).Tier) { ((EntityModel)towerModel).display = ModContent.CreatePrefabReference(); TowerModelBehaviorExt.RemoveBehavior(towerModel); TowerModelBehaviorExt.AddBehavior(towerModel, CreateDisplayModelExt.Create(new Args { display = ((EntityModel)towerModel).display, category = (DisplayCategory)4, layer = -1, ignoreRotation = true })); Args val = new Args(); ((ModelArgs)val).name = "AttackDisplay"; val.display = ModContent.CreatePrefabReference(); val.layer = -1; val.category = (DisplayCategory)4; AttackModelBehaviorExt.AddBehavior(attackModel, CreateDisplayModelExt.Create(val)); } } } public class SunCannonDisplay : ModDisplay { public override PrefabReference BaseDisplayReference => ((EntityModel)Game.instance.model.GetTower(TowerType.DartlingGunner, 4, 0, 0)).display; public override void ModifyDisplayNode(UnityDisplayNode node) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) foreach (Renderer meshRenderer in UnityDisplayNodeExt.GetMeshRenderers(node, true)) { RendererExt.AdjustHSV(meshRenderer, 60f, 0f, 0.2f, (Color?)new Color(0.80784315f, 0f, 0f), 0.3f); RendererExt.AdjustHSV(meshRenderer, -15f, 0f, 0.2f, (Color?)new Color(28f / 51f, 38f / 51f, 0f), 0.75f); } UnityDisplayNodeExt.GetBone(node, "LOD_1").localPosition = new Vector3(0f, 5f, -10f); UnityDisplayNodeExt.GetBone(node, "GunRig_Dartling").localScale = new Vector3(2f, 1f, 2f); } } public class SunCannonLegsDisplay : ModDisplay { public override PrefabReference BaseDisplayReference => ((EntityModel)Game.instance.model.GetTower(TowerType.DartlingGunner, 5, 0, 0)).display; public override void ModifyDisplayNode(UnityDisplayNode node) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) foreach (Renderer meshRenderer in UnityDisplayNodeExt.GetMeshRenderers(node, true)) { RendererExt.ReplaceColor(meshRenderer, new Color(77f / 85f, 0.8980392f, 77f / 85f), new Color(1f, 1f, 0.8235294f), 0.05f); RendererExt.ReplaceColor(meshRenderer, new Color(0.80784315f, 41f / 51f, 0.80784315f), new Color(0.99215686f, 1f, 33f / 85f), 0.05f); RendererExt.ReplaceColor(meshRenderer, new Color(0.69803923f, 0.69803923f, 0.69803923f), new Color(0.96862745f, 72f / 85f, 0.3529412f), 0.05f); RendererExt.ReplaceColor(meshRenderer, new Color(29f / 51f, 0.57254905f, 0.56078434f), new Color(0.9372549f, 63f / 85f, 7f / 51f), 0.05f); RendererExt.ReplaceColor(meshRenderer, new Color(41f / 85f, 41f / 85f, 41f / 85f), new Color(63f / 85f, 7f / 15f, 0f), 0.05f); RendererExt.ReplaceColor(meshRenderer, new Color(0.41960785f, 0.41960785f, 0.41960785f), new Color(63f / 85f, 0.38039216f, 0f), 0.05f); RendererExt.ReplaceColor(meshRenderer, new Color(31f / 85f, 31f / 85f, 31f / 85f), new Color(52f / 85f, 0.3019608f, 0f), 0.05f); } } } public class SunShock : ModBloonOverlay { public override string BaseOverlay => "LaserShock"; public override void ModifyDisplayNode(UnityDisplayNode node) { SpriteRenderer val = default(SpriteRenderer); MeshRenderer val2 = default(MeshRenderer); foreach (Renderer item in (Il2CppArrayBase)(object)node.genericRenderers) { if (Il2CppSystemObjectExt.Is((Il2CppObjectBase)(object)item, ref val)) { CustomSpriteFrameAnimator component = ((Component)val).gameObject.GetComponent(); for (int i = 0; i < component.frames.Count; i++) { component.frames[i] = ((ModContent)this).GetSprite(((ModContent)this).Name + (i + 1), 10f); } } else if (Il2CppSystemObjectExt.Is((Il2CppObjectBase)(object)item, ref val2)) { RendererExt.SetMainTexture((Renderer)(object)val2, ((ModContent)this).GetTexture(((ModContent)this).Name)); } } } } }