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";
}
}