Creating your first mod
Requirements
Section titled “Requirements”You’ll need the latest BmSDK version and a development environment set up per the README.
Step 1: Creating your mod folder
Section titled “Step 1: Creating your mod folder”Every mod lives in its own folder under %GameDir%\BmGame\Mods:
BmGame\Mods\ MyFirstMod\ mod.toml scripts\ MyFirstModScript.csmod.toml marks the folder as a mod. BmSDK skips any folder without one. To start, it only needs a name:
name = "MyFirstMod"Sub-folders under scripts are picked up too. Each mod compiles and hot-reloads on its own, so a broken mod won’t take yours down with it.
Step 2: Writing the main file
Section titled “Step 2: Writing the main file”A script is a class marked with [Script] that inherits from Script:
using BmSDK;
namespace Example; // optional but recommended
[Script]public class ExampleScript : Script{ // Main() is optional public override void Main() { Debug.Log("Hello world!"); }}Main() runs once when the engine first becomes ready. Script.cs lists the other entry points with inline docs.
Step 3: Adding logic to your script
Section titled “Step 3: Adding logic to your script”// This is inside the classpublic override void OnKeyDown(Keys key){ switch (key) { case Keys.J: // Get the pawn that the player is possesing (Batman) var rpp = Game.GetPlayerPawn();
// Load package we need for RCharacter_Joker Game.LoadPackage("FunFair");
// Spawn in a pawn var enemy = Game.SpawnCharacter<RPawnVillainThug, RCharacter_Joker>(rpp.Location, rpp.Rotation);
// Now we can call methods on the created Pawn enemy.bArmoured = true; break; }}Game.GetPlayerPawn() returns Batman himself (RPawnPlayer), which is what you want for anything physical like health or position. Game.GetPlayerController() returns the player (RPlayerController), which drives movement and sits at the camera rather than at Batman.
Game.LoadPackage() pulls a package into memory so you can use what’s inside it. The game only keeps what the current level needs, so any time you reference an asset or class from elsewhere, load its package first. Here that’s FunFair, which owns RCharacter_Joker. Packages live in %GameDir%\BmGame\CookedPCConsole and can be browsed with UPK Explorer to find which one holds what you need. Pass just the name, no .upk and no path.
Preloading packages
Section titled “Preloading packages”Game.LoadPackage() loads on the spot. If your mod always needs the same packages, declare them in mod.toml and BmSDK loads them once at startup, before any level:
name = "MyFirstMod"
[preload]packages = ["FunFair"]keep_alive = ["FunFair.SomeObjectName"]keep_alive takes full object paths (Package.ObjectName, the same ones Game.FindObject() takes) and roots those objects so the garbage collector won’t drop them between levels. Loading a package doesn’t by itself keep its contents alive.
Step 4: Test your mod
Section titled “Step 4: Test your mod”Press F5 in Visual Studio to launch the game. “Hello world!” should show up in the Output window, and pressing J in story mode spawns an armoured Joker at Batman’s location.
Next steps
Section titled “Next steps”Entry points only get you so far. Two guides cover the APIs you’ll reach for next:
- Redirecting functions, to override in-game behavior rather than react to it
- Extending classes with Script Components, to attach your own behavior to existing actors
Beyond that, the Game utility class is the best overview of what BmSDK exposes, with worked examples in DemoScript.cs and IceMage’s Chaos Mod.
Expect some trial and error, since plenty of the game’s internal methods don’t work or have side effects. UE Explorer helps make sense of the quirks, and the Arkham Workshop Discord is the place to ask for help.