diff --git a/BloonsTD6 Mod Helper/Api/Helpers/Instances.cs b/BloonsTD6 Mod Helper/Api/Helpers/Instances.cs
new file mode 100644
index 000000000..81e5a1e24
--- /dev/null
+++ b/BloonsTD6 Mod Helper/Api/Helpers/Instances.cs
@@ -0,0 +1,182 @@
+using System;
+using Il2CppAssets.Scripts.Data;
+using Il2CppAssets.Scripts.Models;
+using Il2CppAssets.Scripts.Models.Profile;
+using Il2CppAssets.Scripts.Simulation;
+using Il2CppAssets.Scripts.Simulation.Factory;
+using Il2CppAssets.Scripts.Simulation.Towers;
+using Il2CppAssets.Scripts.Simulation.Track;
+using Il2CppAssets.Scripts.Unity;
+using Il2CppAssets.Scripts.Unity.Bridge;
+using Il2CppAssets.Scripts.Unity.Display;
+using Il2CppAssets.Scripts.Unity.Network;
+using Il2CppAssets.Scripts.Unity.Player;
+using Il2CppAssets.Scripts.Unity.UI_New.InGame;
+using Il2CppAssets.Scripts.Unity.UI_New.InGame.RightMenu;
+using Il2CppAssets.Scripts.Unity.UI_New.InGame.TowerSelectionMenu;
+using Il2CppAssets.Scripts.Unity.UI_New.Popups;
+using Il2CppNinjaKiwi.LiNK.Lobbies;
+using Il2CppNinjaKiwi.NKMulti;
+using UnityEngine;
+using InputManager = Il2CppAssets.Scripts.Simulation.Input.InputManager;
+using NKMultiConnection = Il2CppNinjaKiwi.LiNK.Lobbies.NKMultiConnection;
+
+// ReSharper disable Unity.NoNullPropagation
+namespace BTD_Mod_Helper.Api.Helpers;
+
+///
+/// Provides quick access to many major BTD6 singleton classes
+///
+[RegisterTypeInIl2Cpp(false)]
+public class Instances : MonoBehaviour
+{
+ ///
+ public Instances(IntPtr pointer) : base(pointer)
+ {
+ }
+
+ ///
+ /// The instance of the Game class
+ ///
+ public static Game Game => Game.instance;
+
+ ///
+ /// The instance of the GameData class
+ ///
+ public static GameData GameData => GameData.Instance;
+
+ ///
+ /// The base GameModel class
+ ///
+ public static GameModel BaseGameModel => Game.instance.model;
+
+ ///
+ /// The current instance of the InGame class. Will be null if not in a match.
+ ///
+ public static InGame InGame => InGame.instance;
+
+ ///
+ /// The instance of the InGameData class that will be used for the next match
+ ///
+ public static InGameData NextInGameData => InGameData.Editable;
+
+ ///
+ /// The instance of the InGameData class for the current match
+ ///
+ public static ReadonlyInGameData CurrentInGameData => InGameData.CurrentGame;
+
+ ///
+ /// The current UnityToSimulation bridge. Will be null if not in a game, or if the game isn't fully loaded in
+ ///
+ public static UnityToSimulation UnityToSimulation => InGame?.bridge;
+
+ ///
+ /// The current UnityToSimulation bridge. Will be null if not in a game, or if the game isn't fully loaded in
+ ///
+ public static UnityToSimulation Bridge => InGame?.bridge;
+
+ ///
+ /// The current game Simulation. Will be null if not in a game, or if the game isn't fully loaded in.
+ ///
+ public static Simulation Simulation => InGame?.bridge?.simulation;
+
+ ///
+ /// The modified GameModel that's being used for the current game. Will be null if not in a game, or if the game isn't fully loaded yet
+ ///
+ public static GameModel CurrentGameModel => UnityToSimulation?.Model;
+
+ ///
+ /// The TowerManger for the current game. Will be null if not in a game, or if the game isn't fully loaded yet
+ ///
+ public static TowerManager TowerManager => Simulation?.towerManager;
+
+ ///
+ /// The InputManager for the current player.
+ ///
+ public static InputManager InputManager => Simulation?.GetInputManager(Bridge.MyPlayerNumber);
+
+ ///
+ /// The CashManager for the current player.
+ ///
+ public static Simulation.CashManager CashManager => Simulation?.GetCashManager(Bridge.MyPlayerNumber);
+
+ ///
+ /// The current Btd6Player
+ ///
+ public static Btd6Player Btd6Player => Game.Player;
+
+ ///
+ /// The current player's profile
+ ///
+ public static ProfileModel Profile => Btd6Player?.Data;
+
+ ///
+ /// The current Display Factory
+ ///
+ public static Factory DisplayFactory => Game.scene?.factory;
+
+ ///
+ /// The current FactoryFactory (factory for in game factories), or null if not in game
+ ///
+ public static FactoryFactory FactoryFactory => Simulation?.factory;
+
+ ///
+ /// The current Map in simulation, or null if not in game
+ ///
+ public static Map Map => Simulation?.Map;
+
+ #region UI
+
+ ///
+ /// The current instance of the TowerSelectionMenu component, may be null
+ ///
+ public static TowerSelectionMenu TowerSelectionMenu => TowerSelectionMenu.instance;
+
+ ///
+ /// The current instance of the PopupScreen component
+ ///
+ public static PopupScreen PopupScreen => PopupScreen.instance;
+
+ ///
+ /// The current instance of the ShopMenu component, may be null
+ ///
+ public static ShopMenu ShopMenu => ShopMenu.instance;
+
+ // There's a bunch of other `.instance`s for other menus, but that's getting a bit niche to list them all
+
+ #endregion
+
+ #region Co-Op
+
+ ///
+ /// The current NetworkedUnityToSimulation bridge. Will be null if not in a coop game, or if the game isn't fully loaded in
+ ///
+ public static NetworkedUnityToSimulation CoOpUnityToSimulation => InGame?.bridge?.TryCast();
+
+ ///
+ /// The current NetworkedUnityToSimulation bridge. Will be null if not in a coop game, or if the game isn't fully loaded in
+ ///
+ public static UnityToSimulation CoOpBridge => InGame?.bridge?.TryCast();
+
+ ///
+ /// The instance of the Btd6CoopGameNetworked class. Will be null if not in a coop game
+ ///
+ public static Btd6CoopGameNetworked Btd6CoopGame => InGame?.coopGame?.TryCast();
+
+ ///
+ /// The instance of the GameConnection class. Will be null if not in a coop game
+ ///
+ public static GameConnection GameConnection => Btd6CoopGame?.Connection;
+
+ ///
+ /// The instance of the NKMultiConnection class. Will be null if not in a coop game
+ ///
+ public static NKMultiConnection NKMultiConnection => GameConnection?.Connection;
+
+ ///
+ /// The instance of the NKMultiGameInterface class. Will be null if not in a coop game
+ ///
+ public static NKMultiGameInterface NKGI => NKMultiConnection?.NKGI;
+
+ #endregion
+}
\ No newline at end of file
diff --git a/BloonsTD6 Mod Helper/Api/Helpers/Lists.cs b/BloonsTD6 Mod Helper/Api/Helpers/Lists.cs
new file mode 100644
index 000000000..480a68648
--- /dev/null
+++ b/BloonsTD6 Mod Helper/Api/Helpers/Lists.cs
@@ -0,0 +1,34 @@
+using System;
+using Il2CppAssets.Scripts.Simulation.Objects;
+using Il2CppAssets.Scripts.Simulation.Towers;
+using Il2CppAssets.Scripts.Unity.Bridge;
+using Il2CppSystem.IO;
+using UnityEngine;
+namespace BTD_Mod_Helper.Api.Helpers;
+
+///
+/// Provides quick access to many major BTD6 object lists
+///
+[RegisterTypeInIl2Cpp(false)]
+public class Lists : MonoBehaviour
+{
+ ///
+ public Lists(IntPtr pointer) : base(pointer)
+ {
+ }
+
+ ///
+ /// All towers currently placed in the game, or null if not in a game
+ ///
+ public static Tower[] AllTowers => Instances.TowerManager?.GetTowers().ToIl2CppList().ToArray();
+
+ ///
+ /// All TowerToSimulation objects currently placed in the game, or null if not in a game
+ ///
+ public static TowerToSimulation[] AllTTS => Instances.Bridge?.ttss.ToArray();
+
+ ///
+ /// All Entities in the current game, or null if not in a game
+ ///
+ public static Entity[] AllEntities => Instances.FactoryFactory?.GetUncast().ToArray();
+}
\ No newline at end of file
diff --git a/BloonsTD6 Mod Helper/LATEST.md b/BloonsTD6 Mod Helper/LATEST.md
index 08f1b19f8..d8b852172 100644
--- a/BloonsTD6 Mod Helper/LATEST.md
+++ b/BloonsTD6 Mod Helper/LATEST.md
@@ -1,3 +1,6 @@
- Added setting to toggle Mod Browser Populating on Startup
- From my personal testing, this leads to ~1s faster startup on average, in exchange for waiting 5s - 10s when you
- first open the browser
\ No newline at end of file
+ first open the browser
+- Added `Instances` and `Lists` classes for modders that have getters for commonly used BTD6 singleton classes and game objects
+ - eg `InGame.instance.coopGame.Cast().Connection.Connection.NKGI` can instead be `Instances.NKGI`
+ - Also gets added as a component to a Game Object at the root of a global scene, so you can easily access fields with Unity Explorer
\ No newline at end of file
diff --git a/BloonsTD6 Mod Helper/MelonMain.cs b/BloonsTD6 Mod Helper/MelonMain.cs
index a7ff2e620..fafddb1f3 100644
--- a/BloonsTD6 Mod Helper/MelonMain.cs
+++ b/BloonsTD6 Mod Helper/MelonMain.cs
@@ -126,6 +126,11 @@ public void Schedule_GameData_Loaded()
() => GameData.Instance != null);
}
+ public override void OnInGameLoaded(InGame inGame)
+ {
+ inGame.gameObject.AddComponent();
+ }
+
public override void OnLoadSettings(JObject settings)
{
var version = settings["Version"];
diff --git a/BloonsTD6 Mod Helper/Patches/UI/TitleScreen_Start.cs b/BloonsTD6 Mod Helper/Patches/UI/TitleScreen_Start.cs
index f7453600c..44b1cadac 100644
--- a/BloonsTD6 Mod Helper/Patches/UI/TitleScreen_Start.cs
+++ b/BloonsTD6 Mod Helper/Patches/UI/TitleScreen_Start.cs
@@ -1,11 +1,15 @@
using System.Linq;
using BTD_Mod_Helper.Api;
using BTD_Mod_Helper.Api.Data;
+using BTD_Mod_Helper.Api.Helpers;
using BTD_Mod_Helper.Api.Internal;
using BTD_Mod_Helper.Api.ModOptions;
using BTD_Mod_Helper.Api.Scenarios;
using Il2CppAssets.Scripts.Data;
+using Il2CppAssets.Scripts.Unity;
using Il2CppAssets.Scripts.Unity.Scenes;
+using UnityEngine;
+using UnityEngine.SceneManagement;
namespace BTD_Mod_Helper.Patches.UI;
[HarmonyPatch(typeof(TitleScreen), nameof(TitleScreen.Start))]
@@ -32,6 +36,12 @@ internal static void Postfix()
ModSettingsHandler.SaveModSettings(true);
ModHelperData.SaveAll();
ModGameMode.ModifyDefaultGameModes(GameData.Instance);
+
+
+ var gameObject = new GameObject("ModHelperQuickAccess");
+ SceneManager.MoveGameObjectToScene(gameObject, Game.instance.gameObject.scene);
+ gameObject.AddComponent();
+ gameObject.AddComponent();
// Tests.ModelSerializationTests.TestSerialization(Game.instance.model);