Decompiled source of InGameHeroSwitch v1.1.7

InGameHeroSwitch.dll

Decompiled 2 weeks ago
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.ModOptions;
using BTD_Mod_Helper.Extensions;
using HarmonyLib;
using Il2CppAssets.Scripts.Models.TowerSets;
using Il2CppAssets.Scripts.Models.Towers;
using Il2CppAssets.Scripts.Simulation.Input;
using Il2CppAssets.Scripts.Unity;
using Il2CppAssets.Scripts.Unity.Bridge;
using Il2CppAssets.Scripts.Unity.UI_New.InGame;
using Il2CppAssets.Scripts.Unity.UI_New.InGame.StoreMenu;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem.Collections.Generic;
using InGameHeroSwitch;
using MelonLoader;
using Microsoft.CodeAnalysis;
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(InGameHeroSwitchMod), "In-Game Hero Switch", "1.1.7", "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("InGameHeroSwitch")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+c355a042dea528d33be8a455c600de9a65d65280")]
[assembly: AssemblyProduct("InGameHeroSwitch")]
[assembly: AssemblyTitle("InGameHeroSwitch")]
[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 InGameHeroSwitch
{
	public class InGameHeroSwitchMod : BloonsTD6Mod
	{
		public static readonly ModSettingBool CycleIfPlaced = new ModSettingBool(false)
		{
			description = "Whether to still allow cycling to different heroes if one is already placed down.",
			button = true
		};

		public static readonly ModSettingHotkey CycleUp = new ModSettingHotkey((KeyCode)280, (HotkeyModifier)0);

		public static readonly ModSettingHotkey CycleDown = new ModSettingHotkey((KeyCode)281, (HotkeyModifier)0);

		public override void OnUpdate()
		{
			InGameHeroSwitchUtility.Update();
		}
	}
	public class InGameHeroSwitchUtility
	{
		[HarmonyPatch(typeof(UnityToSimulation), "MatchReady")]
		internal static class UnityToSimulation_MatchReady
		{
			[HarmonyPostfix]
			internal static void Postfix()
			{
				RefreshShop(playSound: false);
			}
		}

		private static bool cycleDown;

		private static bool cycleUp;

		private static string CurrentHero
		{
			get
			{
				return InGame.Bridge.players[InGame.Bridge.GetInputId()].hero;
			}
			set
			{
				InGame.Bridge.players[InGame.Bridge.GetInputId()].hero = value;
			}
		}

		public static void Update()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Invalid comparison between Unknown and I4
			if (Object.op_Implicit((Object)(object)InGame.instance) && InGame.Bridge != null && !InGame.instance.ReviewMapMode && !InGame.Bridge.IsSpectatorMode && (int)InGame.instance.GameType != 13)
			{
				if (InGameHeroSwitchMod.CycleDown.JustPressed())
				{
					cycleDown = true;
				}
				if (InGameHeroSwitchMod.CycleUp.JustPressed())
				{
					cycleUp = true;
				}
				if (cycleDown && cycleUp)
				{
					ChangeHero(Random.RandomRangeInt(1, ((Il2CppArrayBase<TowerDetailsModel>)(object)Game.instance.model.heroSet).Length));
				}
				else if (InGameHeroSwitchMod.CycleUp.JustReleased() && cycleUp)
				{
					ChangeHero(-1);
				}
				else if (InGameHeroSwitchMod.CycleDown.JustReleased() && cycleDown)
				{
					ChangeHero(1);
				}
			}
		}

		private static void ChangeHero(int delta)
		{
			cycleDown = (cycleUp = false);
			TowerModel val = default(TowerModel);
			if (string.IsNullOrEmpty(CurrentHero) || !Il2CppSystemObjectExt.Is<TowerModel>(InGame.Bridge.Model.GetTowerWithName(CurrentHero), ref val) || (InGameExt.GetTowerInventory(InGame.instance).GetTowerInventoryRemaining(val) == 0 && !ModSettingBool.op_Implicit(InGameHeroSwitchMod.CycleIfPlaced)))
			{
				return;
			}
			HashSet<string> unlockedHeroes = GameExt.GetPlayerProfile(Game.instance).unlockedHeroes;
			IEnumerable<HeroDetailsModel> enumerable = ((IEnumerable<TowerDetailsModel>)InGameExt.GetGameModel(InGame.instance).heroSet).Select((TowerDetailsModel tdm) => ((Il2CppObjectBase)tdm).Cast<HeroDetailsModel>());
			HeroDetailsModel[] array = (enumerable as HeroDetailsModel[]) ?? enumerable.ToArray();
			int index = ((TowerDetailsModel)array.First((HeroDetailsModel hdm) => ((TowerDetailsModel)hdm).towerId == CurrentHero)).towerIndex;
			string text = "";
			while (!unlockedHeroes.Contains(text))
			{
				index += delta;
				index = (index + array.Length) % array.Length;
				text = ((TowerDetailsModel)array.First((HeroDetailsModel hdm) => ((TowerDetailsModel)hdm).towerIndex == index)).towerId;
			}
			ResetInventory(text);
			CurrentHero = text;
			InGameExt[InGame.instance].SetSelected((Selectable)null);
		}

		private static void ResetInventory(string newHero)
		{
			TowerInventory towerInventory = InGameExt.GetTowerInventory(InGame.instance);
			HashSet<string> unlockedHeroes = GameExt.GetPlayerProfile(Game.instance).unlockedHeroes;
			Enumerator<string> enumerator = unlockedHeroes.GetEnumerator();
			while (enumerator.MoveNext())
			{
				string current = enumerator.Current;
				towerInventory.towerMaxes[current] = 0;
			}
			towerInventory.towerMaxes[newHero] = 1;
			RefreshShop(playSound: true);
		}

		private static void RefreshShop(bool playSound)
		{
			bool disallowSelectingDifferentTowers = ShopMenuExt.instance.disallowSelectingDifferentTowers;
			ShopMenuExt.instance.disallowSelectingDifferentTowers = !playSound;
			ShopMenuExt.instance.RebuildTowerSet();
			ShopMenuExt.instance.disallowSelectingDifferentTowers = disallowSelectingDifferentTowers;
			Enumerator<ITowerPurchaseButton> enumerator = ShopMenuExt.instance.ActiveTowerButtons.GetEnumerator();
			while (enumerator.MoveNext())
			{
				ITowerPurchaseButton current = enumerator.Current;
				((ItemPurchaseButton)((Il2CppObjectBase)current).Cast<TowerPurchaseButton>()).Update();
			}
		}
	}
	public static class ModHelperData
	{
		public const string WorksOnVersion = "56.0";

		public const string Version = "1.1.7";

		public const string Name = "In-Game Hero Switch";

		public const string Description = "Lets you press the PageUp and PageDown keys (configurable) to cycle your hero while in a game.";

		public const string RepoOwner = "doombubbles";

		public const string PrevRepoName = "in-game-hero-switch";

		public const string RepoName = "InGameHeroSwitch";
	}
}