ModAPI Tutorial: Installation and basic mod

This tutorial will teach you how to:

  • Install the ModAPI Development Kit.
  • Create a basic mod.

Be warned though, this tutorial requires some minimum understanding of C++. Basically, knowing what methods, variables, classes and includes are.

Installing the Development Kit

Pre-requisites

You need a few programs in order to use the ModAPI Development Kit. These are:

Installing the ModAPI tools

Download the Development Kit from this page. You will see it’s a .zip file, unzip it. You can place the unzipped folder wherever you want; keep in mind that’s where your projects will go.

Inside the folder you will find a file called Spore ModAPI Templates.vsix. If you have installed Visual Studio correctly, you will be able to execute the file. Once the installer is open, press Install.

Finally, open Visual Studio. Go to Tools -> Code Snippets Manager… . In the dialog that opens, ensure that the Language: field is set to Visual C++. Press the button Add… and find the folder called ModAPISnippets, which is inside the ModAPI tools folder we unzipped before.

If you had already installed previous versions

For those that installed older versions of the ModAPI Development Kit, we need to take an extra step to get this working. If this is the first time you install it, you can skip this step.

  1. Open Visual Studio. Go to Tools -> Extensions and Updates… . There, find the item called Spore ModAPI Templates and uninstall it.Captura
  2. Go to the directory %APPDATA%\Microsoft\VisualStudio. There you will see multiple folders, it’s recommended that you do these steps for all of them. Inside each of these folders, you go to ProjectTemplatesCache\Visual C++ Project. If you see a folder called Spore ModAPI Template.zip, delete it.

Example Mod: Planet Buster Cheat

Now the ModAPI Development Kit is successfully installed! In order to show you the basics, following this tutorial we will teach you how to create a simple mod: it adds a cheat called planetBuster that, if called while in the space stage, will give you a certain amount of planet buster bombs. In order to follow this tutorial, basic C++ knowledge is required.

First, we will create our project. Go to File -> New -> Project… . A dialog will open; under the tab Visual C++, select the template called Spore ModAPI Template. Now in the bottom part of the dialog there are two fields you must modify:

  • Name: Insert the name of your mod; do not to use whitespaces. For example, I’ll call it “PlanetBusterMod“.
  • Location: Where your mod files will be saved. Use the button Browse… to navigate to the Projects folder inside the ModAPI directory you unzipped before.

Now, there is one more thing you might need to do. Open the project configuration, ensure the Configuration box is set to All Configurations like shown in the picture below. Now, in the General categories, there are two settings you must pay attention to.

  • Windows SDK Version: Ensure this setting is set to the latest SDK version.
  • Platform Toolset: Ensure this setting is set to Visual Studio 2017 (not necessarily v141)

b9lhk9y2

Time to start programming!

Once the project has been created, use the Solution Explorer (by default, the panel on the right side of the screen) to find a file called dllmain.cpp

Captura

Double-click the file, you will see its contents are shown in the editor. You will notice there are 3 methods:

  • Initialization: A method executed a moment after Spore is opened. When this method is called, most Spore systems are ready to use, but nothing has been shown to the player yet. Most of your mod will go in this method, including cheats, rendering functions, adding game modes,…
  • AttachDetouring: This method is for detouring, which is a way to redirect Spore functions, that is, to change their code. This is the most powerful tool in the ModAPI; we’ll explain how to use it in a future tutorial.
  • DllMain: The main method of the .dll. Most of the times you won’t have to touch anything.

Since we want to add a new cheat, we are interested in the Initialization method. One of the features the Development Kit includes is Code Snippets, autogenerated code for the main things you can do in the ModAPI. To use them, press Ctrl+Space and write their name; you will see a small pop-up, click on it and the code will autogenerate. In this case, we are interested in the ModAPICheat one, so press Ctrl+Space and type it.

Captura

All code snippets have editable fields, you can move between them pressing the Tab key; you can also hover the mouse over them to see a brief description of what they do. In this case, the first editable field that is selected by default is the name the player has to type to call our cheat. In our case, we will write planetBuster. Now press Tab to move to the next editable field, which is the description of the cheat (which is shown when calling the help cheat).

Captura

Once you are done editing the fields, press the Enter key. Now the cursor has moved to the function that contains the code that is called every time the cheat is executed. Here is when comes the real thing.

First we must know what classes and functions we are going to use; you can see all the classes available in the online documentation.We want to mess with the space stage; most of the things related with gameplay are in the Simulator namespace. So the first line we will write will be this:

using namespace Simulator;

If you don’t know what this line does, it’s basically to make things shorter. This way, instead of typing Simulator::cPlayerInventory, we can just use cPlayerInventory.

The cheat must only be executed if the player is in the space game, because otherwise the behaviour could be unexpected. Fortunately, we can check this with the Simulator::IsSpaceGame() method:

if (IsSpaceGame())
{
}

Now, inside the conditional, we must access the player inventory in order to add the planet buster. We can do this with this method:

auto inventory = SimulatorSpaceGame()->GetPlayerInventory();

Notice we have used the keyword auto. Most of the times, instead of writing the full type name (which in this case would be cPlayerInventory*) we can use auto and let Visual Studio guess it. However, this is only recommended when the returned type is clear by the context (in this case, it’s obvious the function returns the player inventory).

You will probably see that Visual Studio is detecting an error on that line. That is because it cannot find the SimulatorSpaceGame method, we haven’t included it. If we go to the online documentation and find the cSimulatorSpaceGame class (most Simulator classes are prefixed with a c), you will see it tells us which .h file contains that class. So now, we must insert the following line after the first line of our .cpp file (which must always be #include “stdafx.h”):

#include <Spore\Simulator\cSimulatorSpaceGame.h>

Going back to our cheat code, now we must load the planet buster bomb, which we can do using the cToolManager::LoadTool() method. By taking a look at the documentation, you will see the method takes an intrusive_ptr reference as destination. This means that we declare a variable with that type and the method will fill all the data we need.

intrusive_ptr<cSpaceToolData> tool;
ToolManager()->LoadTool(instance_id(id("PlanetBusterBomb")), tool);

As I explained before, the first line declared a variable which then the method will use. By looking at the documentation we will see that the method takes a ResourceKey object, which points to a file (that is, it has folder, instance and type ID). However, the method only cares about the instance ID, so we can use instance_id() to generate it. IDs are always of type uint32_t, that is, a 4-byte value such as 0x56D8F92A. We can use the method id() to calculate the hash ID of a certain string, in our case, the file name of the tool we want to load, PlanetBusterBomb.

We are almost done, we only need one more line. This will add the tool we loaded into the player inventory. Since the tool is wrapped in an intrusive_ptr, we use the method get() to get the actual tool pointer.

inventory->AddItem(tool.get());

This is all the code we’ve written so far:
Captura.PNG

There’s just one more thing left to do before compiling the mod: deciding the configuration. You can switch it in a combo box at the top part of the window; by default it’s set to Debug.

Captura

The Debug and Release versions themselves do NOT work. You must select one of the other versions:

  • Disk: People who got Spore on a DVD or pirated.
  • Steam Patched: People who got Spore on Steam, Origin or GoG.
  • Steam: This version is not supported anymore, so you can ignore it.

To test whether the mod works, compile it in the version you need; when distributing the mod, however, you should provide all the 2 functional versions (Disk and Steam Patched) so all players can use your mod. Debug should be used while developing the mod, and Release when the mod is ready to be released.

So we select one of the configurations and use Build -> Build Solution to compile our mod. The Output panel on the bottom part of the window will tell us if there were any errors and also where is the compiled .dll. Now just copy it to the folder where you have the ModAPI Launcher and try the mod: if you followed the tutorial correctly, calling the cheat “planetBuster” should give you some planet buster bombs.

We can even add another detail to our mod. We will allow the player to introduce the number of bombs it wants to receive. You will see there’s a parameter in the code executed when the cheat is called, named line. The cheat console, as many other Spore file formats, uses the ArgScript format; the line parameter contains information about the line the user just inputted. In this case, we want to know wheter the user inputte one extra argument (the number of bombs) or not; we can use the method Line::GetArgumentsRange() for that, with the range of expected arguments being 0 (none) to 1. We must also pass a reference to a variable as a destination parameter, dstCount, where the number of arguments written by the player will be output. So we will write this before adding the tool to the inventory:

size_t numArguments;
auto args = line.GetArgumentsRange(&numArguments, 0, 1);

Now we must check whether the user inputted 1 argument or not, and if that is the case, set the ammo to whatever number it gave. The returned variable args is an array of strings, which are the arguments the player wrote. In order to convert them to an integer value, we can use the other parameter of the cheat code, formatParser, and the FormatParser::ParseInt() method. To change the amount of ammo, we will have to take a look at the documentation of the Simulator::cSpaceToolData class, to see if there is any method or attribute (also called data members or fields) that controls the current ammount of ammo.

if (numArguments == 1) {
	tool->mCurrentAmmoCount = formatParser->ParseInt(args[0]);
}

And we’re done! Compile the .dll again and test the mod. This is the final code:

Captura

And for if have any doubt, here you have the complete .cpp code of this tutorial: https://pastebin.com/rT45X3v3

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Blog at WordPress.com.

Up ↑

%d bloggers like this: