Paper Mario Modding

This book is a collection of tutorials and documentation for modding Paper Mario.

Contributing

If you want to contribute to this book, you can do so by making a pull request to the GitHub repository

If you have any questions, feel free to ask in the Star Haven Discord.

Introduction to Star Rod

Star Rod is a collection of modding tools for Paper Mario 64 (US version 1.0). These tools allow modders to make sweeping changes to the game, from tweaking and rebalancing existing content to adding multiple chapters worth of new content. Paired with a basic text editor, you will be able to add or edit maps, battles, enemies, badges, items, strings, and more. The tools contain a map editor, sprite/animation editor, image editor, and compiler.

Text editor

Star Rod effectively dumps many game assets to text files, which you may edit and compile back into a playable ROM. For this reason, a large part of modding Paper Mario will involve editing text files. Context-sensitive color coding and highlighting help reading these files and prevent basic syntax errors.

We recommend using either Notepad++ or Visual Studio Code. Notepad++ user-defined language files are provided with Star Rod for script files and string files. For VSCode, install the Star Rod extension.

Image editor

Sprites and textures can be edited in your favorite image editor and converted to the proper format using Star Rod's image editor. Bear in mind that all sprites and most textures use a color-indexed image format with strict limits for the number of colors per image (16 for sprites, 16 or 256 for textures). Many artists prefer using aseprite or libresprite for creating pixel art which can be exported as a color-indexed PNG or imported directly into Star Rod's sprite editor.

BGM editor

Mamar lets you create and edit BGM files from MIDI files.

Setting up Star Rod and your modding folder

Requirements

  • Java Development Kit (JDK) version 12 or newer (JDK version 17 or 20 recommended) (OpenJDK works as well) (a "standard" installation of Java, like JRE, does not suffice!)
  • Star Rod modding tool (current version: 0.5.3) -> Download here: https://drive.google.com/file/d/1OUHnb9T7m_aVm-WJY3mmEgFS_DU0F2je/
  • A valid Paper Mario US v1.0 ROM (There are a variety of tools you can use to dump a backup from your own cartridge. Please ensure your cartridge matches the required version.)
    • MD5-Checksum (.z64): a722f8161ff489943191330bf8416496
    • If you do have a clean NTSC-U ROM, but it is in the .n64 or .v64 format, use the following website to fix your ROM: https://hack64.net/tools/swapper.php

Installation

  1. Check if you already have an up-to-date version of JDK installed.
    • If you know your way around a terminal, open one up and enter java --version.
    • To check using Windows menues: TODO
  2. If you do not have JDK version 12 or newer installed, get it here: https://www.oracle.com/java/technologies/downloads/
  3. Download the current version of Star Rod (see: Requirements), then extract the .zip file somewhere you can easily find it again. It's recommended to set up a folder for your modding and have the folder for Star Rod inside of that.

Preparing your mod folder

  1. If you're on Windows, launch StarRod.exe. MacOS and Linux users launch StarRod.jar instead (you may need to set the file to allow execution first).
  2. When asked to create a new Star Rod config, choose Yes.
  3. When asked to pick a directory for your mod, choose the folder you set up during step 3) of the Installation.
  4. When asked to create a new mod config, choose Yes.
  5. You'll now be prompted to pick a clean NTSC-U (that is the North American release) ROM of Paper Mario. Commonly the correct ROM file is in the .z64 format.
  6. Once Star Rod has verified that your ROM is the correct one, Star Rod's Mod Manager will open
  7. Select Dump ROM Assets. This will extract the game's data into a new folder called dump next to your ROM file. This may take a few minutes, but only needs to be done once.
  8. Select Copy Assets to Mod to copy the relevant data of the game's dump to your mod directory.
  9. You can close Star Rod for now.

Now you're ready to start modding!

How to Create Your Mod

Star Rod Tools

The next time you launch Star Rod, you'll be prompted to open the Map Editor, Sprite Editor, Mod Manager and several other tools.

Screenshot of the Star Rod Tools menu

Use the Mod Manager to compile and package your mod. This is required to turn the directories of files in you modding directory into a new ROM.

Use the Globals Editor to edit items, badges, images and more. To edit the scripting of items or badges you'll need to actually write scripts yourself though, this menu cannot be used for that.

Use the String Editor to preview, add, delete or edit ingame text.

Use the Level Editor to modify the way maps and battle maps are organized.

Use the Map Editor to view, create and modify the ingame maps.

Use the Sprite Editor to adjust sprites of characters and items, as well as view, create and edit animation loops.

Use the World Map Editor to change the world map displayed in the pause menu.

Use the Themes menu to change the look of Star Rod itself.

For changing the scripting of maps, battles, badges and more, please see: TODO link to yet non-existing guide TODO link the bold editor mentions above to respective tutorials

Note: Some of Star Rod's graphical editors, like the Map Editor or Sprite Editor, do require OpenGL to run. While OpenGL should be installed by any general graphics card driver installation, or come pre-installed on most operating systems, these editors are known to cause issues or not load at all on some MacOS or Linux setups. If you use MacOS or Linux, then some of Star Rod's editors may not load at all, instead freezing the program. Sadly, there is no known work-around at the moment. Using Windows however causes no known problems with OpenGL.

Debug Features

When compiling your mod in the Mod Manager, set the Enable Debug Information option in the Compile Mod options > Debug menu to display map names and battle IDs at the bottom of the screen. The player's current position will also be printed. This also enables the debug features, which can be accessed using the D-Pad buttons:

  • Dpad-Up toggles turbo speed and makes enemies unable to start combat with Mario on contact.
  • Dpad-Right opens the debug variable output and memory usage.
  • Dpad-Down toggles God Mode, which makes Mario invulnerable to most damage, and makes every attack by Mario or partner deal 99 damage per hit.
  • Dpad-Left toggles the debug menu, which can then be navigated using the Dpad, using R to enter menus / confirm choices, and L to cancel out of a menu. This menu allows for map warps, giving items and badges, unlocking partners and more.

How to Publish Your Mod

When you're satisfied with your romhack and it compiles successfully, click Package Modin the Mod Manager to create a binary diff file, also known as patch file (YourModName.mod). The player will need your .mod file (provided by you) and a clean copy of Paper Mario's NTSC-U ROM (provided by them). Do not distribute patched ROMs! The name of the resulting ROM will be identical to the name of your .mod file.

However, it is recommended to use external tools to create patch files for your mod, like Floating IPS (or FLIPS) (https://github.com/Alcaro/Flips). Creating a patch file using such a tool will likely create a smaller patch file (like a .bps file) than using Star Rod to package your mod would, while being faster at creating the patch file as well.

The Mod Directory Explained

The mod directory created and populated by Star Rod contains several folders you'll need for creating your romhack. For some of the files in here you can use the editors provided by Star Rod mentioned above. Scripts, which control how maps and battles behave, have no editor associated with them and have to be edited by hand. Those scripts are modified using patch files, and not by editing the source files of maps and battles directly. The files in the src directories are for quick reference only, instead create patch files in the respective patch directories. xml files and images are edited in-place however, instead of writing patch files for them.

The directories within the mod directory are the following:

/map/src/        Source files of maps scripts and editor map files
                 (copied from dump). For reference only, do not edit.
/map/patch/      Patch files for editing scripts or creating new ones.
/map/import/     Patch files here can be included in map scripts with
                 #import.
/map/save/       Save map files from the editor here to reference them
                 in scripts.
/map/build/      Binary map and collision data built from the editor.
/map/temp/       Patched map scripts are placed here during the patching
                 process. Just ignore this directory.

/world/          Scripting for the overworld behavior of partners.

/battle/formation/  Scripting of enemies in battle.
/battle/item/       Scripting of using items in battle.
/battle/move/       Scripting of Mario's attacks.
/battle/partner/    Scripting of partner attacks.
/battle/starpower/  Scripting of StarPower moves.

/image/texture/  General textures
/image/bg/       Map-Background images
/image/misc/     Edit title and pause screen images here.
/image/icon/*/   Icon images in color-indexed PNG format.

/sprite/         Player and NPC sprites.

/strings/        Edited strings and customs strings are added here.

/globals/        Various global data tables are built from files
                 here.
/globals/patch/  Global patch files are placed here.

/out/            Compiled and packaged mods will be placed here.

/mod.cfg         Star Rod's configuration file for handling the mod.
                 It's not required to manually edit this file, use
                 Star Rod instead.

Star Rod Mod Manager

Screenshot of the Star Rod Mod Manager menu

Overview

Within the Mod Manager menu you are able to configure Star Rod itself, dump data from a clean Paper Mario ROM into a folder structure with human-readable files, compile your modded files back into a ROM, and package the modded ROM into a patch file for distributing your mod.

  • Mod Folder: Path to the directory you want to use to store your files while modding.
  • Target ROM: Path to a clean Paper Mario US v1.0 ROM. Dumped data from the ROM will also be stored here.

Dumping

  • Dump ROM Assets: Extract data from the game ROM into a folder structure. Assets dumped include scripting for maps and battles, images like sprites and textures, and text used in dialogue boxes and item descriptions. Also converts these files into more readable formats, like script files into human-readable code, and image files into file types openable by most modern image editor software. This only needs to be done once.
  • Options: Modify Star Rod's settings for the dumping process. For the most part you won't ever need to touch this menu. One of the options in here allows you to choose between tabstop and space indentation within dumped script files, should you prefer one or the other.
  • Copy Assets to Mod: Copy relevant and previously dumped assets from the dump folder to your mod. This is required to be able to compile the ROM.

Building

  • Compile Mod: Attempts to compile the original sources copied to your mod folder together with your modded changes into a new ROM. If this step succeeds, then you can find the resulting ROM within the out subfolder within your Mod Folder. If Star Rod is unable to compile your mod for whatever reason, an error message will be shown which tries to explain the problem.
  • Options: Modify Star Rod's settings for the building process. Some interesting options in here include:
    • Properties
      • Mod Name: Your mod's title, displayed in the bottom left corner of the Save File Select screen.
      • Initial Map: The map to start a newly created save file on.
    • Options
      • Skip Intro Logos: Skips the intro logos when starting the ROM and instead loads into the intro story immediately.
      • Disable Intro Story: Skips the intro story and instead loads into the title screen immediately.
      • Disable Demo Reel: Removes the demo reel which usually play automatically when waiting on the title screen for a while.
    • Debug
      • Enable Debug Information: Shows some debug information during gameplay at the bottom of the screen: Mario's current coordinates, and the currently loaded overworld or battle map. Also enables the debug menu, which can be activated by pressing Dpad-Left.
      • Enable Variable Logging: Whenever a global variable changes, displays the name and new value of that variable on screen for a few seconds.
  • Package Mod: Create a patch file in the .mod format from the differences between the original Paper Mario US v1.0 ROM and your compiled mod within the out folder. This patch file can then be distributed to others without sharing the ROM directly. Using this feature not only takes longer than using other software for creating ROM patch files, but also results in patch files that are way bigger. It is recommended to use other software to create your patch files, like Floating IPS for bps patches, or Xdelta for xdelta patches.

Star Rod String Editor

Screenshot of the Star Rod String Editor's Resource tab

Overview

Within the String Editor you can view and modify existing ingame text and create entirely new text to display. Text in Paper Mario uses a special string format which Star Rod translates into a custom markup language.

In the center on the left you can edit the current string. In the bottom left you can add special characters and formatting. In the top left a preview of how the current string will behave ingame is displayed. On the right three tabs show different sub-menues: Resources, Strings and Variables.

Resources tab

The Resources tab scans your mod folder for references to ingame text and lists all occurrences it can find. The src directory lists all strings of the original Paper Mario, ordered within several sub-groups. This directory is for reference only and strings in here should not be modified. The patch directory lists all strings you added or changed using string patch files. This is the place changed or added strings are usually put in. The Map Patches directory lists all strings declared directly within map patch files. The Battle Patches directory lists all strings declared directly within battle patch files. The Global Patches directory lists all strings declared directly within global patch files. As implied above, it is possible to declare strings directly within patch files for maps, battles, or globals. Whether you want to have a string saved in the same file it is used in, or saved in a separate string patch file, is up to you.

You can select a sub-category by left-clicking on it. This will filter all the strings listed in the Strings tab to only show those of your selection.

Strings tab

Screenshot of the Star Rod String Editor's Strings tab

The Strings tab shows all strings in your currently selected sub-category from the Resourcestab. You can select a string by left-clicking on it.

Non-printing characters are represented by tags enclosed by square brackets with colon-separated parameters. Tags are used for special characters, such as symbols and button icons like [C-LEFT]; pauses or delays in printing like [PAUSE]; and more complex formatting functions which modify text size/color/etc. Each string has a unique identifier which includes a 16-bit section ID and a 16-bit message ID. For example, string 001C0002 is message 2 in section 1C.

You can click into a block of the currently shown string to have the string preview above display that block, including any formatting you have chosen. The currently previewed block gets colored blue to show that it is currently selected.

Variables tab

Screenshot of the Star Rod String Editor's Variables tab

The Variables tab lets you test the current string's variable text. When a string has any of the [Var X] tags (0-7), then these can be filled dynamically by map or battle scripting, instead of needing different versions of static strings. This functionality is used, for example, for shop keeper dialogue and the item sockets on Shiver Mountain.

Modifying and Adding Text

Any existing string can be modified or overwritten using text files in your mod's strings/ directory or by defining strings with battle or map script files. New strings can be added in the same way, you just have to make sure their string ID is not already in use (otherwise it will overwrite any existing string with the same ID).

Star Rod Sprite Editor

Screenshot of the Star Rod Sprite Editor's Resource tab

Under Construction

Quick notes:

  • Sprite images must be indexed, and have at most 15 colors + 1 transparent (for this reason, aseprite or libresprite are the recommended sprite editors)
  • Sprite widths must be divisible by 16, heights divisible by 8
  • The width and height must be smaller than 256
  • The transparent color will create a slight outline on the character in-game, if you set the transparent color to match the sprite outline you can mask this effect

Star Rod Themes Editor

Screenshot of the Star Rod Themes Editor

Within the Themes Editor you can change the look and feel of Star Rod itself. This does not change anything about your mod and is purely cosmetic. The different interface objects on the right are sample objects that show a preview of your currently chosen theme.

Star Rod Tutorials

The following tutorials walk through different aspects of modding Paper Mario.

You should read them in order, but if you're looking for something specific, you can jump to a specific tutorial.

TutorialSummary
Basic PatchingChange the music in the "Mail call!" cutscene
Add NPC to MapAdd Kent C. Koopa to Peach's Castle, First Floor (Day)

Basic Patching

We're going to create a patch that changes the music that plays in the opening cutscene.

Source files

In Star Rod, any file that ends in .mscr, .bscr or .wscr is a source file. This tutorial will focus on .mscr files, but the method of patching described works for all different types.

.mscr files contain all the code used in overworld maps. Every file corresponds to an overworld map in the game. They are located in your mod directory, in map/src. The file we are going to patch is the one that corresponds to the first map that loads when you start the game, the Mario’s House map. The name of the file is kmr_20.mscr. When you open this file in a text editor, you see a bunch of blocks starting with a variation of #new:Function $Something_12345678 and ending with a closing brace: }. These are called Data Structures. All data structures are created with this exact format, where:

  • #new:Function = Tells Star Rod to create a new data structure of type “Function”.
  • $Something_12345678 = The name of the structure.

There are a lot of different types of data structures, but the two types you’ll find most commonly are Function and Script. In this tutorial, we are going to patch a script.

Finding the script to patch

To make changes to the opening cutscene, you need to find the script associated with it. This can be done in a variety of ways. The simplest method is by searching the file for dialogue used in the cutscene, because Star Rod provides a preview of any text that gets displayed from a script. The first bit of dialogue in the opening cutscene is “Mail call!”, said by Parakarry. If you search the file for this string, you will immediately find the script that makes that text appear, which is the opening cutscene. Scroll up a bit until you find the start, with the #new: bit. (At this point, you may already have found where the music gets set.)

Making a patch file

To change this script, you will need to make a patch file. Patch files are created in map/patch, and their name has to be the exact same as the file you’re patching, but with the extension .mpat instead of .mscr.

Copy the entire script (from the #new: part to the closing brace }) from the mscr file to the mpat file. To tell Star Rod that you’re patching a script that already exists instead of creating a new one, we replace the #new:Script with an @ symbol.

Your mpat file should now look like this:

@ $Script_8024FD70 {
  
}

With the contents of the script between the braces.

Now you can make your changes. A few lines into the script you can see a line that reads

Call  SetMusicTrack ( 00000000 .Song:MailCall 00000000 00000008 )

To change which song is playing, simply edit the part after the .Song: to be a different track title. Say you want the final boss theme to play, you’d put FinalBowserBattle in there. For a list of all songs you can use here, look in your mod folder in globals/enum/songs.enum.

Compile your mod and start a new game, and you should hear the song you selected play during the opening cutscene!

Advanced

You might think it’s a bit excessive to copy and paste an entire script just to edit one line. Luckily, there is a shorter way to do it. In the script, you will see that every single line has a hexadecimal number at the start. This number indicates how far into the script this line of code is, also known as the offset of the line. You can patch that line specifically by specifying this offset in the patch as follows:

@ $Script_8024FD70 {
    [24] Call  SetMusicTrack ( 00000000 .Song:FinalBowserBattle 00000000 00000008 )
}

This will have the same effect as the original patch. Keep in mind that if you’re patching like this, the change you make has to be the exact same size as the original line.

Add NPC to Map

We're going to add Kent C Koopa to the first map in the game where Mario is given control, which is the Entry Hall of Peach's Castle. The engine name for this map is kkj_00.

Placing the NPC in the map

Open kkj_00.xml in the map editor, and think about where you want to place the NPC. Once you've found a good spot, hold down middle click and move Mario to that position in the 3D view.

Mario placed right below the stairs in kkj_00

On the right side of the Map Editor, go into the Markers tab. Click Create, then New Marker. A window will pop up. In the window, give your marker a name, set the type to NPC, and click OK. When you select the marker you've just created, a menu appears in the bottom right corner of the map editor. In this menu, click on the Animations tab. Here you can set the sprite you want your NPC to use, as well as its palette and basic animations.

Kent C Koopa animation data

If you want, you can also give the NPC some basic movement in the AI Movement tab.

When you're done, save the map by pressing Ctrl+S. The NPC now has a position on the map, but if you compile and run the game now you'll notice he's not actually there.

NPC isn't yet visible in-game

This is because we haven't told the game to actually place an NPC here yet.

Creating the NPC with code

Create a patch file for this map. You can do this from the map editor by clicking the Scripts tab in the top right, then clicking the Create Patch File button. After that you can click the Open Patch File button to immediately open the file in a text editor.

The NpcGroup

The basis for any NPC is an `NpcGroup``. This is the first thing we're going to create, and we're going to do it by copying one from the map on which Kent C. Koopa originally appears. If you're making an NPC based on one that already exists in a different map, this is the recommended way to do it.

#new:NpcGroup $NpcGroup_KentCKoopa {
	0000003F $NpcSettings_KentCKoopa ~Vec3f:NPC_Kent % -164 0 -37
	00002D01 $Script_Init_KentCKoopa 00000000 00000000 0000010E
	~NoDrops
	~Movement:NPC_Kent
	~AnimationTable:NPC_Kent % .Sprite:KentCKoopa
	00000000 00000000 00000000 00000000 % no tattle string
}

But what does all this mean? If you followed the patching tutorial, the #new:NpcGroup $NpcGroup_KentCKoopa should at least look familiar. The name of the data structure (specified after the $) can be anything, as long as you reference it correctly later. Inside the NpcGroup, there's quite a few sets of numbers:

  • 0000003F - The NPC index. Make sure no other NPC on the map has the same index as your new NPC. Since kkj_00 already has so many NPCs, let's set this to 3F just to be safe.
  • $NpcSettings_KentCKoopa - The name of the NPC's NpcSettings structure. We'll create one of these later.
  • ~Vec3f:NPC_Kent - A reference to the marker you made earlier, make sure the marker name matches what you put after the colon here.
  • 00B44D04 - NPC flags. Each flag has a certain functionality associated with it. A complete list of what these flags do can be found in the Paper Mario decomp (the NpcFlags enum). If you're copying an NPC from a different map, just leave this unchanged (for Kent C Koopa I ended up changing this to the flags used by a Toad because Kent's flags weren't working right). If you're making a new NPC and you're not sure how to use these flags, just copy them from an NPC that looks and behaves similar to yours.
  • $Script_Init_KentCKoopa - The name of the NPC's Init script. We'll create one of these later.
  • 00000000 - "initVarCount", just leave it at 0.
  • 00000000 - "initVar", just leave it at 0.
  • 0000010E - Initial world yaw, or the rotation the NPC will have when it's spawned. If unsure, set this to 0.
  • ~NoDrops - Enemy drops after a battle. If your NPC is friendly, leave this at ~NoDrops, otherwise look at enemy NpcGroups in the source files to see how to set up drops.
  • ~Movement:NPC_Kent - Movement data as defined in the "AI Movement" tab of the NPC marker in the map editor. Make sure the marker name matches what you put after the colon here. If you want your NPC to move around instead of just standing still the whole time, you can set up basic movement in this tab.
  • ~AnimationTable:NPC_Kent - A reference to the Animation tab of the NPC's marker. Once again, make sure the marker name matches what you put after the colon here.
  • The purpose of the next three sets of numbers is unknown.
  • 00000000 - Reference to a tattle string defined in "1A NPC Tattles.str".

The NpcSettings

$NpcGroup_KentCKoopa referenced $NpcSettings_KentCKoopa, so we need to create that next.

Let's copy this data from a similar (or identical) NPC from a different map.

#new:NpcSettings $NpcSettings_KentCKoopa {
	00000000 00440050 00000000 00000000 00000000 80077F70 00000000 8007809C
	00000000 00000000 00630000
}

(Make sure the name matches the name you gave it in the NpcGroup.)

Again there are a bunch of vague sets of numbers, but this time I am not going to explain what they all do in detail. There's only one set of numbers you need to be concerned with for now, and it's the second (in this example, it's the 00440050). This set of numbers defines the NPC's collision. The first four digits define the NPC's height (and also the height of the talk icon that appears above their head when Mario gets close), the last four define the radius. If you want to know what all the other sets of numbers do, look in the decomp (the NpcSettings struct).

The init script

Now create an init script for the NPC.

#new:Script $Script_Init_KentCKoopa {
    Return
    End
}

(Once again, make sure the name matches the name of the script in the NpcGroup.)

In this script, we tell the game what to do when the NPC is first created. The main purpose of this script is to define NPC behaviour for certain situations. There are six types of behaviour scripts to define here.

  • Aux
  • Idle
  • AI
  • Interact
  • Hit
  • Defeat

Generally, the only ones you will need are Idle, Interact and Defeat. For this NPC, only an Interact is necessary. Add an Interact script to the Init script as follows:

#new:Script $Script_Init_KentCKoopa {
    Call BindNpcInteract ( .Npc:Self $Script_Interact_KentCKoopa )
    Return
    End
}

(.Npc:Self refers to the NPC this script is attached to)

The interact script

Of course, this means you now have to create another script to define the Interact behaviour.

#new:Script $Script_Interact_KentCKoopa {
    Return
    End
}

The code in this script will run when the player approaches the NPC and presses A. Most NPCs will just talk to Mario, and nothing else.

To make the NPC speak, use the SpeakToPlayer function.

#new:Script $Script_Interact_KentCKoopa {
    Call SpeakToPlayer ( .Npc:Self 00470002 00470001 00000000 000C012D )
    Return
    End
}

The arguments for this function (the things between the braces) are:

  1. The index of the NPC saying the dialogue
  2. The NPC's talk animation
  3. The NPC's idle animation
  4. Message flags (just leave this at 0)
  5. The string to say (I'm using the dialogue he uses in the original map)

Modifying the NpcGroupList

Now the NPC itself is done, but the game still doesn't place it on the map. NPC's are created with the MakeNpcs function, which creates every NPC in the NpcGroupList you provide as an argument. In order for your new NPC to be created, you need to add it to the correct NpcGroupList.

If you look in kkj_00.mscr, you'll find that there's more than one NpcGroupList in the file. To find out which list you need to modify, check the NpcGroups in each list to see if they contain the NPCs you see when you enter the castle at the start of the game. Patch that NpcGroupList and add the new NpcGroup below the last one in the list.

An NpcGroupList entry has three parts:

  1. The amount of NPCs in the Group (in this case, that's just 1)
  2. The name of the NpcGroup
  3. The battle associated with the NpcGroup (00000000 if there's no associated battle). This follows the format AAAABBCC, where
    • AAAA = the battle area
    • BB = the formation
    • CC = the stage index
@ $NpcGroupList_802439C4 {
    0000000B $NpcGroup_80242474 00000000
    00000001 $NpcGroup_KentCKoopa 00000000
    00000000 00000000 00000000
}

(Make sure to leave that line of 0s at the bottom of the list, it tells the game where the list ends.)

Of course, if you're adding a custom NPC to a new map, you need to create the NpcGroupList from scratch (with #new:) instead of patching it, and you'll also need to add a MakeNpcs call to your map's $Script_Main. To see how that function works, look at the code of any map with NPCs on it.

Compile the game, and your NPC should now appear in the map!

Introduction to decomp modding

Decomp, or papermario, refers to the Paper Mario decompilation. This is a project which contains reverse-engineered C code which can be compiled into the original game ROM.

Decomp modding is initially harder than Star Rod modding, but it is significantly more powerful. You can write C instead of assembly and modify any engine function or script source code directly without using patch files.

Decomp modding also supports versions other than the US release: JP, PAL, and iQue. At time of writing, only the US release has been 100% matched so we will only discuss modding US here.

Text editor

We recommend using Visual Studio Code. When opening the repo, a popup will appear asking if you want to install recommended extensions - make sure you click Yes.

Image editor

Sprites and textures can be edited in your favorite image editor. Bear in mind that all sprites and most textures use a color-indexed image format with strict limits for the number of colors per image (16 for sprites, 16 or 256 for textures). Many artists prefer using aseprite or libresprite for creating pixel art which can be exported as a color-indexed PNG.

BGM editor

Mamar lets you create and edit BGM files from MIDI files.

Star Rod

Star Rod has a decomp mode which is triggered by opening the decomp repo as the mod folder. This allows you to use Star Rod to edit maps and sprites.

Setting up decomp

Requirements

  • A valid Paper Mario US v1.0 ROM (There are a variety of tools you can use to dump a backup from your own cartridge. Please ensure your cartridge matches the required version.)
    • MD5-Checksum (.z64): a722f8161ff489943191330bf8416496
    • If you do have a clean NTSC-U ROM, but it is in the .n64 or .v64 format, use the following website to fix your ROM: https://hack64.net/tools/swapper.php
  • A UNIX operating system like Linux or macOS. Windows users should read the Windows page.

Installation

This guide will walk through setting up papermario-dx, a fork of papermario which makes modding easier and provides a better developer experience. If you would prefer to not use dx, simply clone the papermario repository instead.

Clone the repository:

git clone https://github.com/star-haven/papermario-dx
cd papermario-dx

Install pigment64 (our image-processing tool)

curl https://sh.rustup.rs -sSf | sh
cargo install pigment64

and make sure pigment64 is in your system path.

Install build dependencies:

./install_deps.sh
./install_compilers.sh

NOTE: On Mac, if you get an error that looks like

Error: Cannot install md5sha1sum because conflicting formulae are installed.
 coreutils: because both install `md5sum` and `sha1sum` binaries

Please `brew unlink coreutils` before continuing.

it's fine to just open install_deps.sh in a text editor, delete the md5sha1sum from the brew install line, and rerun it (put it back after so you don't accidentally commit it!)

Copy baserom into the following place:

  • ver/us/baserom.z64 (sha1: 3837f44cda784b466c9a2d99df70d77c322b97a0)

(If you're using WSL, you can enter the Linux filesystem by opening \\wsl$ in File Explorer; e.g. \\wsl$\Ubuntu\home\<your username>\papermario-dx.)

Configure the build and extract assets from the base ROM:

./configure

Compile the game:

ninja

The output ROM is ver/us/build/papermario.z64 - you can run this in any N64 emulator.

Alternatively, to compile and run, you can use the run script:

./run

(This will search known paths for an emulator. If your emulator isn't listed, add it to the list and contribute!)

If you have Visual Studio Code, you can type code . to open the repo within it.

You can now begin modding.

Setting up decomp on Windows

Windows requires that you set up Windows Subsystem for Linux.

  1. Install or upgrade to WSL 2 following these instructions (Ubuntu is recommended)
  2. Open a WSL terminal
  3. Run the following command: sudo apt update && sudo apt upgrade && cd ~
  4. Continue with setup

Decomp modding basics

The development loop is as follows:

  1. ./configure if you added or removed files
  2. ninja to compile
  3. ./run to run (will automatically run ninja if required)

splat.yaml

An important part of decomp modding is specifying where files should be linked. For our purposes, this means describing where in ROM/RAM source code and assets should go.

The file that does this is called ver/us/splat.yaml. This is a YAML file.

The segments list describes all the segments in the ROM. When adding a new file to be added to the ROM, you must add it as a segment or subsegment.

For example, to add a new map called tst_14, append this segment:

segments:
  # ...
  - name: tst_14
    dir: world/area_tst/tst_14
    type: code
    start: auto
    vram_class: map
    subsegments:
    - [auto, c, tst_14]
    - [auto]

Assets

splat.yaml has a list called asset_stack which looks like this:

asset_stack:
  - star_rod_build
  - dx
  - us

These form what we call the "asset stack". When an asset needs to be built, configure will first look for it in assets/star_rod_build, then assets/dx, then assets/us.

For example, INCLUDE_IMG("ui/input/analog_stick_left.png", ui_input_analog_stick_left_png will look in each of these directories in turn until it finds ui/input/analog_stick_left.png. This allows you to override vanilla (us) assets easily.

You should prepend a directory for your mod onto the asset stack, for example:

asset_stack:
  - my_mod
  - star_rod_build
  - dx
  - us

Then place assets for your mod in a new directory assets/my_mod.

MapFS

Map backgrounds, texture archives, geometry, and collision files live in an asset folder called mapfs. These are combined into an archive at build time.

When adding a new MapFS asset, also add it to the list in tools/splat_ext/map_data.yaml.

Improving build times

Avoid ld 2.40 and 2.41

Recent versions of GNU binutils link papermario very slowly:

lddebug?link time
2.37no4.06s
2.37yes20.26s
2.41no28.24s
2.41yes35.26s

You can check your ld version with mips-linux-gnu-ld --version.

Use a better CPU

The multi-core performance of your CPU (e.g. number of threads) has a large impact on build times. The single-core performance of your CPU also has a large impact on link times.

Use a faster disk

The speed of your disk has a large impact on build times. SSDs are much faster than HDDs.

If you are using WSL (Windows), avoid working in the /mnt/ and instead work in the actual WSL filesystem (e.g. /home/). There is a large performance penalty for accessing files in /mnt/.

Use a ramdisk

If you have enough RAM, you can create a ramdisk for your build directory (ver/us/build). More...

Ccache

Ccache speeds up recompilation by caching previous compilations.

ccache is particularly effective at improving build times after header files that are included a lot are modified. For instance, it significantly speeds up builds after message files (*.msg) are modified because they generate message_ids.h, which is included in many places.

Installing ccache

  • Ubuntu and derivatives: sudo apt install -y ccache
  • macOS: brew install ccache

Using ccache

If you have ccache available on your PATH, ./configure will automatically use it.

You can confirm that ccache is working correctly by executing ccache -s after a build and inspecting the number of cache hits.

Build without debug symbols

Building without debug symbols can significantly speed up linking depending on your CPU's single-core performance.

Make sure you are not using the --debug configure flag.

Although the link time is better, this has numerous side effects:

  • Crash backtraces will no longer include location information; they will just show addresses.
  • The size of the symbol information data appended to ROM is also made much smaller.
  • gdb becomes much less useful.

Debugging with gdb

gdb is a debugger that allows inspecting programs while they're running, tracing execution, placing breakpoints, stepping through code, and editing memory. If you've used the Project64 debugger, it's like that but much better (sorry shygoo).

To use gdb, you'll need gdb-multiarch, a gdb server and a gdb client.

Compile with debug symbols

./configure --debug
ninja

Installing gdb-multiarch

gdb server

The ares emulator has had gdb support for N64 since v134.

To enable ares' gdb server, go to Settings > Debug and check Enabled.

The following message will appear at the bottom of the ares window: GDB pending ([::1]:9123)

gdb client

Make sure the gdb server is running. Then:

  • VSCode: Open a C file and press F5. More...
  • Terminal: Start gdb-multiarch and enter target remote [::1]:9123. More...

Overlays

TODO: migrate overlay support to dx


This page was adapted from Dragorn421's oot gdb tutorial.

Publishing your romhack

TODO: improve this page

  • Install gh
  • Fork star-haven/papermario-dx (via CLI?)
  • Set up remote
  • Commit (TODO: intro to git, e.g. using gitkraken's vscode extension)
  • Create tag for release
  • Push to fork

CI/CD with GitHub Actions

If you fork DX, you can set a secret in your fork to enable CI/CD (Continuous Integration/Continuous Deployment) with GitHub Actions. This will automatically:

  • Build your mod when you push to your fork, and upload the build to a release called latest.
  • Build and publish a release of your mod when you push a new tag to your fork.
  • Complain if a commit breaks the build.

Setting up CI/CD

In your fork, go to the 'Actions secrets and variables' page.

Click the New repository secret button.

Add a new secret with the name BASEROM_US_URL.

The value will be the URL to a clean Paper Mario (U) ROM. This should be a private URL, such as one on your Google Drive.

To convert a Google Drive link to a direct download link, replace XXXXXXXX with the file ID in the following URL:

https://drive.usercontent.google.com/download?id=XXXXXXXX&export=download&confirm=y

Save this secret and you're done!

Using clangd for language server features

clangd is a language server that can work with many editors. It adds smart features to your editor: code completion, compile errors, go-to-definition and more.

clangd setup

To use clangd, you need to generate a compile_commands.json file. In the root of your Paper Mario directory, run this command: ninja -t compdb > compile_commands.json

If you move the source directory, compile_commands.json will need to be regenerated. This is because it requires hardcoded, not relative, paths to work.

Editor setup

See your editor's documentation for more details. Search "(your editor) lsp" to get started.

Reference: Event Scripting

On each frame, the EVT manager will continue executing commands in all threads until a blocking command is encountered. This means that if you have a thread that loops but does not block between iterations, the game will freeze! Avoid this by inserting a blocking command such as EVT_WAIT(1) in the loop body.

Also note that threads are never executed in parallel. If your EVT script lacks blocking commands, it will be executed all in one go, and race conditions cannot occur.

The following subset of EVT commands are blocking:

  • EVT_EXEC_WAIT / ExecWait
  • EVT_WAIT / Wait
  • EVT_WAIT_SECONDS / WaitSeconds
  • EVT_CALL / Call (if function returns ApiStatus_BLOCK)

Reference: Event Scripting > Control Flow

Conditionals

Regular:

  • decomp
    • EVT_IF_EQ(A, B) (equals)
    • EVT_IF_NE(A, B) (not equals)
    • EVT_IF_LT(A, B) (lower than)
    • EVT_IF_GT(A, B) (greater than)
    • EVT_IF_LE(A, B) (lower than or equal)
    • EVT_IF_GE(A, B) (greater than or equal)
  • Star Rod
    • If A == B (equals)
    • If A != B (not equals)
    • If A < B (lower than)
    • If A > B (greater than)
    • If A <= B (lower than or equal)
    • If A >= B (greater than or equal)

Conditional statements behave exactly as you might expect.

Flag bits related:

  • decomp
    • EVT_IF_FLAG(A, B) (bitwise check if bit B is set on value A)
    • EVT_IF_NOT_FLAG(A, B) (bitwise check if bit B is not set on value A)
  • Star Rod
    • If ((A & B) != 0) (bitwise check if bit B is set on value A)
    • If ((A & B) == 0) (bitwise check if bit B is not set on value A)

Note that the bitwise AND conditions treat the second argument as a constant. This means that they will not try to dereference script variables so you should NOT supply them with *Var[X], etc. They are intended to check whether certain flags are set for the first argument.

EVT_ELSE (decomp) / Else (Star Rod)

(optional) Begins the block to be executed if the above If condition is false.

EVT_END_IF (decomp) / EndIf (Star Rod)

Designates the end of an If..EndIf or If..Else..EndIf body.

Switch Case

EVT_SWITCH(A) (decomp) / Switch VarA (Star Rod)

Begins a switch statement using the given variable. Up to 8 switch statements may be nested within a single script.

EVT_SWITCH_CONST(A) (decomp) / SwitchConst A (Star Rod)

Begins a switch statement using the given constant.

  • decomp
    • EVT_CASE_EQ(B) (equals)
    • EVT_CASE_NE(B) (not equals)
    • EVT_CASE_LT(B) (lower than)
    • EVT_CASE_GT(B) (greater than)
    • EVT_CASE_LE(B) (lower than or equals)
    • EVT_CASE_GE(B) (greater than or equals)
    • EVT_CASE_FLAG(B) (bitwise AND not equals zero)
    • EVT_CASE_RANGE(B, C) (B <= SwitchVar <= C)
  • Star Rod
    • Case == B (equals)
    • Case != B (not equals)
    • Case < B (lower than)
    • Case > B (greater than)
    • Case <= B (lower than or equals)
    • Case >= B (greater than or equals)
    • Case & B (bitwise AND not equals zero)
    • Case B to C (B <= SwitchVar <= C)

Begins the block to be executed if the condition is true. Unlike the switch you might be used to, these cases do not support fallthrough.

EVT_CASE_OR_EQ(B) (decomp) / CaseOR [COND] B (Star Rod)

Several of these cases may appear in series. The clause is executed if any values are equal. These cases support fall-though, so every subsequent clause will be executed until a normal case or EndCaseGroup is encountered.

EVT_CASE_AND_EQ(B) (decomp) / CaseAND [COND] B (Star Rod)

Several of these cases may appear in series. All conditions must be satisfied for the clause to executed. Unused in the original code, intended use-case unknown. Potentially useful for SwitchConst blocks to check multiple variables against the constant.

EVT_END_CASE_GROUP (decomp) / EndCaseGroup (Star Rod)

Terminates a CaseOR or CaseAND fall-though/matching group.

EVT_CASE_DEFAULT (decomp) / Default (Star Rod)

Begins the block to be executed if no preceding conditions matched.

EVT_BREAK_SWITCH (decomp) / BreakCase (Star Rod)

Jumps out of a case clause to the end of the switch block.

EVT_END_SWITCH (decomp) / EndSwitch (Star Rod)

Ends a switch statement.

Jump and Goto Commands

EVT_JUMP(EvtSource) (decomp) / Jump $EvtSource (Star Rod)

Jumps to a given instruction pointer and begins execution from there. You can jump to a different EVT source and labels etc. will be loaded as expected. The timescale for the current thread is also reset to the global default.

EVT_LABEL(Label_ID) (decomp) / Label Label_ID (Star Rod)

Marks this point in the script as a EVT_GOTO target. Range: 0 <= Label_ID <= 0x16

EVT_GOTO(Label_ID) (decomp) / Goto Label_ID (Star Rod)

Moves execution to the given label.

Wait Commands

EVT_WAIT(A) (decomp) / Wait A (Star Rod)

Blocks the current thread for the given number of frames.

EVT_WAIT_SECS(A) (decomp)

Blocks the current thread for the given number of seconds. Unused.

Loops

EVT_LOOP(A) (decomp) / Loop A (Star Rod)

Repeat the following commands a certain number of times. To create an infinite loop, use A = 0. Star Rod assumes the iteration count is zero if no argument is provided.

Note: passing a variable will decrement the variable after each iteration until it equals zero. If the variable is zero before the loop begins, the loop will be infinite; make sure it breaks or blocks to avoid a freeze.

Up to 8 loops may be nested within a single script.

EVT_BREAK_LOOP (decomp) / BreakLoop (Star Rod)

Immediately jump out of a loop and continue execution after the next EndLoop command.

EVT_END_LOOP (decomp) / EndLoop (Star Rod)

Designates the end of a loop body.

Reference: Event Scripting > Threads / Script Calls

Main Threads

EVT_EXEC(EvtSource) (decomp) / Exec $EvtSource() (Star Rod)

Launches a new script, starting at the specified location. This location does not need to be at the beginning of the script.

The new script does not block its parent (it'll run in the background, i.e. in a new thread), and will continue executing even if the parent terminates.

The new script starts execution the following frame that this is called, not immediately.

EVT_EXEC_GET_TID(EvtSource, TID) (decomp)

Identical to EVT_EXEC, but the newly-launched thread ID is stored in a provided variable. The new thread may be interacted with using EVT_KILL_THREAD, EVT_SUSPEND_THREAD, EVT_RESUME_THREAD, and EVT_IS_THREAD_RUNNING

EVT_EXEC_WAIT(EvtSource) (decomp) / ExecWait $EvtSource() (Star Rod)

Launches a new child thread. Blocks for at least one frame unless the child thread is made to have a higher priority than the parent. Stops blocking the parent thread only once the child thread returns.

Child threads are killed, suspended, and resumed as their parents are, for example, a different thread using EVT_KILL_THREAD to kill a parent thread would also kill its child thread(s) launched by this command.

EVT_RETURN (decomp) / Return (Star Rod)

Finish script execution and destroy it. If the script has a parent (script[68] != null), copy script flags and variables to its parent.

EVT_END (decomp) / End (Star Rod)

Indicates the end of the script for parsing purposes. Required for all scripts for the interpreter to correctly parse them. Does not do anything in-game.

EVT_KILL_THREAD(TID) (decomp) / Kill TID (Star Rod)

Terminates the script with the given thread ID, and any ChildThreads.

EVT_CALL(Func, Args...) (decomp) / Call $Func(Args...) (Star Rod)

Calls a given C EVT API function with any number of arguments. This is used for executing code that is written in C, and not the EVT scripting language. The API function called will execute every frame unless it returns 2 on register V0. Forgetting to return 2 without proper measures to handle this on the EVT script side may cause a freeze.

EVT_IS_THREAD_RUNNING(TID, Result) (decomp) / DoesScriptExist TID Result (Star Rod)

Sets Result variable to True/False depending on whether a thread with given thread ID exists (i.e. has not been killed).

EVT_SET_PRIORITY(A) (decomp) / SetPriority A (Star Rod)

Sets the current thread's priority. Higher-priority threads execute before lower-priority threads on each frame.

EVT_SET_TIMESCALE(A) (decomp) / SetTimescale A (Star Rod)

Sets the current thread's timescale. This is a multiplier applied to EVT_WAIT and EVT_WAIT_SECONDS.

EVT_SUSPEND_THREAD(TID) (decomp) / Suspend TID (Star Rod)

Suspends a thread by its thread ID.

EVT_RESUME_THREAD(TID) (decomp) / Resume TID (Star Rod)

Resumes a thread by its thread ID.

EVT_SET_GROUP(A) (decomp) / SetGroup A (Star Rod)

Sets the current thread's group. Group value meanings are currently not known.

EVT_SUSPEND_GROUP(A) (decomp) / SuspendAll A (Star Rod)

Suspends all threads in a group.

EVT_RESUME_GROUP(A) (decomp) / ResumeAll A (Star Rod)

Resumes all threads in a group.

EVT_SUSPEND_OTHERS(A) (decomp)

Suspends all threads in a group, except the current thread. Unused.

EVT_RESUME_OTHERS(A) (decomp)

Resumes all threads in a group, except the current thread. Unused.

Child Threads

EVT_THREAD (decomp) / Thread (Star Rod)

Begins a temporary helper block that executes some tasks in parallel with the main thread. Vars and flags are copied to the thread but are not copied back after the thread finishes. The thread can also outlive its parent.

EVT_END_THREAD (decomp) / EndThread (Star Rod)

Designates the end of a Thread block.

EVT_CHILD_THREAD (decomp) / ChildThread (Star Rod)

Similar to Thread, but the child thread shares variables and flags with the parent and will be terminated if the parent script ends.

EVT_END_CHILD_THREAD (decomp) / EndChildThread (Star Rod)

Designates the end of a ChildThread block.

Binding Threads

EVT_BIND_TRIGGER(EVT_SOURCE, TRIGGER, COLLIDER_ID, UNK_A3, TRIGGER_PTR_OUTVAR) (decomp)

Bind $Script TRIGGER, COLLIDER_ID, UNK_A3, TRIGGER_PTR_OUTVAR (Star Rod)

Sets up a script to launch when a particular event is triggered. Valid triggers:

  • TRIGGER_WALL_PUSH
  • TRIGGER_FLOOR_TOUCH
  • TRIGGER_WALL_PRESS_A (displays "!" icon above player)
  • TRIGGER_FLOOR_JUMP
  • TRIGGER_WALL_TOUCH
  • TRIGGER_FLOOR_PRESS_A
  • TRIGGER_WALL_HAMMER
  • TRIGGER_GAME_FLAG_SET
  • TRIGGER_AREA_FLAG_SET
  • TRIGGER_CEILING_TOUCH
  • TRIGGER_FLOOR_ABOVE
  • TRIGGER_POINT_BOMB (takes Vec3f* instead of collider ID)

For the COLLIDER_ID param, the following values are accepted:

  • Collider ID
  • Entity ID (use EVT_ENTITY_INDEX)
  • Pointer to a Vec3f (for TRIGGER_POINT_BOMB only)

Only one thread will run for a trigger at once. Triggers will not re-activate until the associated script returns.

EVT_BIND_PADLOCK(EVT_SOURCE, TRIGGER, COLLIDER_ID, ITEM_LIST, UNK_A3, TRIGGER_PTR_OUTVAR) (decomp)

BindLock $Script TRIGGER, COLLIDER_ID, $ItemList, UNK_A3, TRIGGER_PTR_OUTVAR (Star Rod)

Similar to EVT_BIND_TRIGGER, but also takes arguments for the item list to show. Used whenever an event trigger is supposed to open an item list for the player to choose from. Despite being called "PADLOCK", and this type of binding indeed being used for padlocks, this EVT can also be used in other scripting.

EVT_UNBIND (decomp) / Unbind (Star Rod)

Unbinds the current thread from the trigger it was bound to, if any. Makes it so the trigger will no longer call the current thread, effectively deactivating the trigger. Usually used at the end of a bound thread.

Reference: Event Scripting > Variables

Types of Variables

Local Variables

Local variables do not need to be declared. They are automatically available upon starting a thread / script and are initialized to 0 / FALSE.

LocalVar(INDEX) (decomp) / *Var[INDEX] or *VarINDEX (Star Rod)

Local Word. A variable local to the current thread. LWs are copied to any threads created by this one (EVT_EXEC, EVT_EXEC_WAIT, EVT_THREAD, EVT_CHILD_THREAD). Additionally, EVT_EXEC_WAIT copies LWs back from the spawned thread when it completes.

Max. value: 4294967295 / FFFFFFFF

Range for INDEX: 0 <= v < 0x10:

LocalVar(0) to LocalVar(15) (decomp) / *Var0 to *VarF (Star Rod)


LocalFlag(INDEX) (decomp) / *Flag[INDEX] (Star Rod)

Local Flag. A boolean variable local to the current thread. LFs are copied to any threads created by this one (EVT_EXEC, EVT_EXEC_WAIT, EVT_THREAD, EVT_CHILD_THREAD). Additionally, EVT_EXEC_WAIT copies LFs back from the spawned thread when it completes.

Range for INDEX: 0 <= v < 0x60:

LocalFlag(0) to LocalFlag(95) (decomp) / *Flag[0] to *Flag[59] (Star Rod)

Map Variables

Map variables do not need to be declared. They are automatically available upon entering a map and are initialized to 0 / FALSE.

MapVar(INDEX) (decomp) / *MapVar[INDEX] or *MapVarINDEX (Star Rod)

Global Word. A variable global to all threads. Cleared upon entering a new map.

Max. value: 4294967295 / FFFFFFFF

Range for INDEX: 0 <= v < 0x10:

MapVar(0) to MapVar(15) (decomp) / *MapVar0 to *MapVarF (Star Rod)


MapFlag(INDEX) (decomp) / *MapFlag[INDEX] (Star Rod)

Global Flag. A boolean variable global to all threads. Cleared upon entering a new map.

Range for INDEX: 0 <= v < 0x60:

MapFlag(0) to MapFlag(15) (decomp) / *MapFlag[0] to *MapFlag[59] (Star Rod)

Area Variables

Area variables do not need to be declared. They are automatically available upon entering an area and are initialized to 0 / FALSE.

AreaByte(INDEX) (decomp) / *AreaByte[INDEX] (Star Rod)

Local Saved Byte. A variable local to the current world area, saved in the savefile. Cleared upon a new world area.

Max. value: 255 / FF

Rarely used. Most common use is for NPCs with dialogue that changes depending on the number of times you have interacted with them in their 'recent memory' (i.e. until you leave the area).

Range for INDEX: 0 <= v < 0x10:

AreaByte(0) to AreaByte(15) (decomp) / *AreaByte[0] to *AreaByte[F] (Star Rod)


AreaFlag(INDEX) (decomp) / *AreaFlag[INDEX] (Star Rod)

Local Save World Flag. A boolean variable local to the current world area, saved in the savefile. Cleared upon entering a new world area.

Used to track whether badges, items, etc. have been collected or whether NPCs have been interacted with.

Range for INDEX: 0 <= v < 0x100:

AreaFlag(0) to AreaFlag(255) (decomp) / *AreaFlag[0] to *AreaFlag[FF] (Star Rod)

Game Variables

GameByte(INDEX) (decomp) / *GB_NAME (Star Rod)

Global Saved Byte. A variable saved in the save file. Used for almost all savefile states.

Star Rod assigns all GameBytes a custom name, which a Byte can be called by. E.g. instead of accessing *GameByte[000] one usually uses *GB_StoryProgress. For a list of all of these aliases, see the globals/GameBytes.txt file within your mod folder. If you want to add your own Bytes that are saved to the save file within Star Rod, then add them to globals/ModBytes.txt with the format of INDEX = NameOfByte, e.g. 000 = MB_MyCoolModByte.

Max. value: 255 / FF


GameFlag(INDEX) (decomp) / *GF_NAME (Star Rod)

Global Save World Flag. A boolean variable saved in the savefile.

Used to track whether badges, items, etc. have been collected or whether NPCs have been interacted with.

Star Rod assigns all GameFlags a custom name, which a Flag can be called by. E.g. instead of accessing *GameFlag[001] one usually uses *GF_StartedChapter1. For a list of all of these aliases, see the globals/GameFlags.txt file within your mod folder. If you want to add your own Flags that are saved to the save file within Star Rod, then add them to globals/ModFlags.txt with the format of INDEX = NameOfByte, e.g. 0000 = MF_MyCoolModFlag.

Arrays

Array variables need to be declared by using their corresponding EVT_USE_ARRAY calls to become usable within the current thread.

ArrayVar(INDEX) (decomp) / *Array[INDEX] (Star Rod)

User Word. A variable stored within the current thread's array.

You can load an array with EVT_USE_ARRAY or temporarily allocate one with EVT_MALLOC_ARRAY, then get/set values with ArrayVar(INDEX)

Range: 0 <= v


ArrayFlag(INDEX) (decomp)

User Flag. A boolean variable stored within the current thread's flag array.

The flag array is distinct from the word array.

Variable Operations

EVT_SET(Var, IntValue) (decomp) / Set *Var IntValue (Star Rod)

Sets the given variable to a given value cast to an integer.

EVT_SET_CONST(Var, B) (decomp) / SetConst *Var B (Star Rod)

Sets a variable to B.

If B is also a variable, this copies the reference of B into A. Effectively, this treats B as a "compile-time" constant. You can then use Call SetValueByRef and Call GetValueByRef to set the value referenced.

When used with a non-variable B, SetConst acts identically to Set.

EVT_SETF(Var, FloatValue) (decomp) / Set *Var FloatValue (Star Rod)

Sets the given variable to a given value, but supports EVT_FLOATs.

Basic Arithmatic Operations

  • EVT_ADD(Var, B) (decomp) / Add *Var B (Star Rod)
  • EVT_SUB(Var, B) (decomp) / Sub *Var B (Star Rod)
  • EVT_MUL(Var, B) (decomp) / Mul *Var B (Star Rod)
  • EVT_DIV(Var, B) (decomp) / Div *Var B (Star Rod)
  • EVT_MOD(Var, B) (decomp) / Mod *Var B (Star Rod)

B can be a static number or a variable. Writes the result of the operation back into Var.

Basic Floating-point Arithmetic Operations

  • EVT_ADDF(Var, FloatB) (decomp) / AddF *Var FloatB (Star Rod)
  • EVT_SUBF(Var, FloatB) (decomp) / SubF *Var FloatB (Star Rod)
  • EVT_MULF(Var, FloatB) (decomp) / MulF *Var FloatB (Star Rod)
  • EVT_DIVF(Var, FloatB) (decomp) / DivF *Var FloatB (Star Rod)

FloatB can be a static number or a variable. Writes the result of the operation back into Var.

Array Operations

EVT_USE_ARRAY(INT_PTR) (decomp) / UseArray $Array (Star Rod)

Loads an s32 array pointer into the current thread. This has to be called before the array can be used.

EVT_USE_FLAG_ARRAY(PACKED_FLAGS_PTR) (decomp)

Loads an s32 array pointer into the current thread for use with ArrayFlag(INDEX). Flags are stored in a 'packed' structure where indices refer to bits.

EVT_MALLOC_ARRAY(SIZE, OUT_PTR_VAR) (decomp)

Allocates a new array of the given size for use with ArrayVar(INDEX). EVT scripts do not have to worry about freeing this array.

Within Star Rod this function is not available, instead all arrays for a map or battle script file have to be pre-defined and accessed via UseArray.

Global API Functions

Many API functions for calling C code are available globally, so they can be accessed from any map or battle script file.

These API functions are called using the EVT_CALL() / Call EVT operation, and they may modify both their function argument variables as well as variables local to the current thread (LocalVar() / *Var).

Usage examples:

  • EVT_CALL(DisablePlayerInput, TRUE) (decomp)
  • Call DisablePlayerInput (.True) (Star Rod)

Generated documentation for all global API functions is available here.

Player functions

Disable8bitMario, BOOL (decomp) / Disable8bitMario (BOOL) (Star Rod)

Enables and disables the 8-bit Mario easter egg.


DisablePartner, INT (decomp) / DisablePartner (INT) (Star Rod)

Disables the partner with the provided partner ID. See also: EnablePartner


DisablePlayerInput, BOOL (decomp) / DisablePlayerInput (BOOL) (Star Rod)

Disables and reenables the player input.

This function can disable all player inputs for controlling Mario and his partner (or Peach), and to disable opening the pause menu, partner menu or item menu. This is most commonly done to start cutscenes.

This also disables Mario's spin, should he be in a spinning animation.

Internally, this is not tracked as a boolean flag, but rather as integer. The player is only in control while this integer equals 0, and calling DisablePlayerInput, TRUE adds 1 to that integer, while calling DisablePlayerInput, FALSE subtracts 1.

This is done so multi-layered scripts, which each try to disable the player input on their own, don't give back control too early.


DisablePlayerPhysics, BOOL (decomp) / DisablePlayerPhysics (BOOL) (Star Rod)

Disables and reenables the player physics.

This function can disable all player physics. This causes the physics system to no longer force gravity on the player, and physics-related animations no longer play automatically (like setting Mario's / Peach's running animation when forced to move via EVT script).

Internally, this is not tracked as a boolean flag, but rather as integer. The player is only in control while this integer equals 0, and calling DisablePlayerPhysics, TRUE adds 1 to that integer, while calling DisablePlayerPhysics, FALSE subtracts 1.

This is done so multi-layered scripts, which each try to disable the player physics on their own, don't reenable these too early.


DisablePulseStone, BOOL (decomp) / DisablePulseStone (BOOL) (Star Rod)

Enables and disables the blinking Pulse Stone speech bubble. However, the Pulse Stone speech bubble is programmed to only show in the SBK area and only within certain maps.


EnablePartner, INT (decomp) / EnablePartner (INT) (Star Rod)

Enables the partner with the provided partner ID. See also: DisablePartner


FacePlayerTowardPoint, FLOAT_X, FLOAT_Y, INT (decomp) 802D2884 (FLOAT_X, FLOAT_Y, INT) (Star Rod)

Turns the player character towards a given point (FLOAT_X, FLOAT_Y) over the duration of INT frames.


ForceUsePartner (decomp) / 802D2B50 () (Star Rod)

Forces the player to use the currently active partner's overworld ability. This circumvents partner abilities usually only being triggered by a C-Down input while player input is enabled.


FullyRestoreHPandFP (decomp) / FullyRestoreHPandFP () (Star Rod)

Sets the player's HP and FP equal to their current maximum HP and FP.


FullyRestoreSP (decomp) / FullyRestoreSP () (Star Rod)

Sets the player's SP equal to their current maximum SP.


func_802D2C14


func_802D1270


func_802D1380


func_802D2148


func_802D2484


GetPartnerInUse, *INT (decomp) / GetCurrentPartner (*INT) (Star Rod)

Returns the partnerID of the current partner if they're using their ability, otherwise returns PARTNER_NONE.


GetPlayerActionState, *INT (decomp) / GetPlayerActionState (*INT) (Star Rod)

Returns the ID of the player's current action state.


GetPlayerAnimation, *INT (decomp) / GetPlayerAnimation (*INT) (Star Rod)

Returns the ID of the player's current animation.


GetPlayerPos, *INT_X, *INT_Y, *INT_Z (decomp) / GetPlayerPos (*INT_X, *INT_Y, *INT_Z) (Star Rod)

Returns the player's current position.


GetPlayerTargetYaw, *FLOAT (decomp) / GetPlayerTargetYaw (*FLOAT) (Star Rod)

Returns the player's current target yaw. Since EVT calls like PlayerFaceNpc can make the player turn towards a certain target over several frames, this EVT call can be used to check the goal value of this ongoing turning action.


HidePlayerShadow, BOOL (decomp) / HidePlayerShadow (BOOL) (Star Rod)

Disables and reenables the player character's shadow.


InterpPlayerYaw, *FLOAT, *INT (decomp) / InterpPlayerYaw (*FLOAT, *INT) (Star Rod)

Turns the player towards target yaw value FLOAT over INT frames.


InterruptUsePartner (decomp) / 802D2B6C ( ) (Star Rod)

Immediately interrupts any partner overworld ability in progress.


IsPlayerOnValidFloor, *BOOL (decomp) / IsPlayerOnValidFloor (*BOOL) (Star Rod)

Returns whether the player is in contact with valid groud currently.


PlayerFaceNpc, INT_X, INT_Y (decomp) / PlayerFaceNpc ( INT_X, INT_Y ) (Star Rod)

Turns the player towards the Npc with ID INT_X and locks the player facing to follow the target for INT_Y frames. This is mostly used with INT_Y = 0 to just turn the player once.


PlayerJump, FLOAT_X, FLOAT_Y, FLOAT_Z, INT (decomp) / PlayerJump ( FLOAT_X, FLOAT_Y, FLOAT_Z, INT ) (Star Rod)

Makes the player jump towards target location (FLOAT_X, FLOAT_Y, FLOAT_Z) over INT frames. If INT equals zero, then the player's current movespeed value is used to calculate the duration of the jump. This function uses mode 0 of the internal player_jump function, which plays a jumping sound, changes the player's animation to a jumping animation fitting the current status (default, holding Watt, 8bit Mario), turns the player towards the jump goal, and checks for collider behavior when landing at the end of the jump.


PlayerJump1, FLOAT_X, FLOAT_Y, FLOAT_Z, INT (decomp) / PlayerJump1 ( FLOAT_X, FLOAT_Y, FLOAT_Z, INT ) (Star Rod)

Makes the player jump towards target location (FLOAT_X, FLOAT_Y, FLOAT_Z) over INT frames. If INT is zero, then the player's current movespeed value is used to calculate the duration of the jump. This function uses mode 1 of the internal player_jump function, which does not play a jumping sound, does not change the player's animation to a jumping animation fitting the current status (default, holding Watt, 8bit Mario), does not turn the player towards the jump goal, and does not check for collider behavior when landing at the end of the jump.


PlayerJump2, FLOAT_X, FLOAT_Y, FLOAT_Z, INT (decomp) / PlayerJump2 ( FLOAT_X, FLOAT_Y, FLOAT_Z, INT ) (Star Rod)

Makes the player jump towards target location (FLOAT_X, FLOAT_Y, FLOAT_Z) over INT frames. If INT is zero, then the player's current movespeed value is used to calculate the duration of the jump. This function uses mode 2 of the internal player_jump function, which does not play a jumping sound, does not change the player's animation to a jumping animation fitting the current status (default, holding Watt, 8bit Mario), does not turn the player towards the jump goal, and checks for collider behavior when landing at the end of the jump.


PlayerMoveTo, FLOAT_X, FLOAT_Y, FLOAT_Z (decomp) / PlayerMoveTo ( FLOAT_X, FLOAT_Y, FLOAT_Z ) (Star Rod)

Makes the player move towards given X/Y coordinate (FLOAT_X, FLOAT_Y) over FLOAT_Z frames. If FLOAT_Z equals zero, then the player's current movespeed value is used to calculate the duration of the move.


PlaySoundAtPlayer, INT_X, INT_Y (decomp) / PlaySoundAtPlayer ( INT_X, INT_Y ) (Star Rod)

Plays sound effect with ID INT_X at the player current location, using sound flags INT_Y.


SetPlayerActionState, INT (decomp) / SetPlayerActionState ( INT ) (Star Rod)

Sets the player's action state to the action state with ID INT.


SetPlayerAnimation, INT (decomp) / SetPlayerAnimation (INT) (Star Rod)

Sets the player's current animation to a given animation ID. This will get overwritten immediately by the physics engine, if the physics are not disabled and the player is moving in some way or controller input is made.

If the chosen animation is ANIM_MarioW2_Collapse, then also shakes the camera for a short moment.


SetPlayerAnimationSpeed, FLOAT (decomp) / SetPlayerAnimationSpeed ( FLOAT ) (Star Rod)

UNUSED! Sets the player's animation speed to FLOAT (default 1.0).


SetPlayerCollisionSize, INT_HEIGHT, INT_RADIUS (decomp) / SetPlayerPos (INT_HEIGHT, INT_RADIUS) (Star Rod)

Sets the player's collision size, colloquially called the hit box.


SetPlayerFlagBits, INT, BOOL (decomp) / SetPlayerFlagBits ( INT BOOL ) (Star Rod)

Sets the player's given flags, represented by flag bits INT, to BOOL.


SetPlayerImgFXFlags INT (decomp) / 802D286C ( INT ) (Star Rod)

Sets flags represented by INT for the player's ImgFX. Used before calling UpdatePlayerImgFX.


SetPlayerJumpscale, FLOAT (decomp) / SetPlayerJumpscale (FLOAT) (Star Rod)

Sets the player's jump scale. This determines how quickly a jump started by a script (not by player input) is performed. The player moves along the jump arc slower or faster, depending on the jump scale.


SetPlayerPos, INT_X, INT_Y, INT_Z (decomp) / SetPlayerPos (INT_X, INT_Y, INT_Z) (Star Rod)

Sets the player's position immediately.


SetPlayerPushVelocity, FLOAT_X, FLOAT_Y, FLOAT_Z (decomp) / SetPlayerPushVelocity ( FLOAT_X FLOAT_Y FLOAT_Z ) (Star Rod)

UNUSED! Sets the player's current push velocity to (FLOAT_X, FLOAT_Y, FLOAT_Z).


SetPlayerSpeed, FLOAT (decomp) / SetPlayerSpeed (FLOAT) (Star Rod)

Sets the player's grounded movement speed. This automatically reset once the player input gets enabled.


UpdatePlayerImgFX, INT_1, INT_2, INT_3, INT_4, INT_5 (decomp) / 802D2520 ( INT_1 INT_2 INT_3 INT_4 INT_5 ) (Star Rod)

Clears the player's ImgFX, then applies parameters INT_2 to INT_5 to chosen special sprite effect INT_1 to cause a new ImgFX. These effects can be a holographic effect, color tinting, changing the alpha, making the player sprite wavy, and more. Used after calling SetPlayerImgFXFlags.


UseEntryHeading, INT_X, INT_Y (decomp) / UseEntryHeading ( INT_X, INT_Y ) (Star Rod)

Used internally by the EnterWalk group of functions.


UseExitHeading, INT_X, INT_Y (decomp) / UseExitHeading ( INT_X, INT_Y ) (Star Rod)

Called before ExitWalk to set the player's "walk-off" animation target using a given walk-off length INT_X and entry ID INT_Y. This modifies the calling script's Var1, Var2 and Var3 values for use by ExitWalk.


WaitForPlayerInputEnabled (decomp) / WaitForPlayerInputEnabled ( ) (Star Rod)

Stops the current script and loops infinitely until player input is enabled.


WaitForPlayerMoveToComplete (decomp) / WaitForPlayerMoveToComplete ( ) (Star Rod)

Stops the current script and loops infinitely until the current player move is complete.


WaitForPlayerTouchingFloor (decomp) / WaitForPlayerTouchingFloor ( ) (Star Rod)

Stops the current script and loops infinitely until player touches any valid floor from above, landing on it.

Camera Function

AdjustCam(Evt* script, s32 isInitialCall)


func_802CA90C(Evt* script, s32 isInitialCall)


func_802CA988(Evt* script, s32 isInitialCall)


func_802CABE8(Evt* script, s32 isInitialCall)


func_802CACC0(Evt* script, s32 isInitialCall)


func_802CAE50(Evt* script, s32 isInitialCall)


func_802CB710(Evt* script, s32 isInitialCall)


GetCamDistance(Evt* script, s32 isInitialCall)


GetCamPitch(Evt* script, s32 isInitialCall)


GetCamPosA(Evt* script, s32 isInitialCall)


GetCamPosB(Evt* script, s32 isInitialCall)


GetCamPosC(Evt* script, s32 isInitialCall)


GetCamPosition(Evt* script, s32 isInitialCall)


GetCamType(Evt* script, s32 isInitialCall)


InterpCamTargetPos(Evt* script, s32 isInitialCall)


LoadSettings(Evt* script, s32 isInitialCall)


PanToTarget(Evt* script, s32 isInitialCall)


ResetCam(Evt* script, s32 isInitialCall)


SetCamBGColor(Evt* script, s32 isInitialCall)


SetCamDistance(Evt* script, s32 isInitialCall)


SetCamEnabled(Evt* script, s32 isInitialCall)


SetCamFlag80(Evt* script, s32 isInitialCall)


SetCamLeadPlayer(Evt* script, s32 isInitialCall)


SetCamPerspective(Evt* script, s32 isInitialCall)


SetCamPitch(Evt* script, s32 isInitialCall)


SetCamPosA(Evt* script, s32 isInitialCall)


SetCamPosB(Evt* script, s32 isInitialCall)


SetCamPosC(Evt* script, s32 isInitialCall)


SetCamProperties(Evt* script, s32 isInitialCall)


SetCamSpeed(Evt* script, s32 isInitialCall)


SetCamTarget(Evt* script, s32 isInitialCall)


SetCamType(Evt* script, s32 isInitialCall)


SetCamViewport(Evt* script, s32 isInitialCall)


SetPanTarget(Evt* script, s32 isInitialCall)


ShakeCam(Evt* script, s32 isInitialCall)


UseSettingsFrom(Evt* script, s32 isInitialCall)


WaitForCam(Evt* script, s32 isInitialCall)

Map Function

CloneModel(Evt* script, s32 isInitialCall)


EnableGroup(Evt* script, s32 isInitialCall)


EnableModel(Evt* script, s32 isInitialCall)


EnableTexPanning(Evt* script, s32 isInitialCall)


GetColliderCenter(Evt* script, s32 isInitialCall)


GetEntryID(Evt* script, s32 isInitialCall)


GetLoadType(Evt* script, s32 isInitialCall)


GetMapID(Evt* script, s32 isInitialCall)


GetModelCenter(Evt* script, s32 isInitialCall)


GetModelIndex(Evt* script, s32 isInitialCall)


GetTransformGroup(Evt* script, s32 isInitialCall)


GotoMap(Evt* script, s32 isInitialCall)


GotoMapByID(Evt* script, s32 isInitialCall)


GotoMapSpecial(Evt* script, s32 isInitialCall)


InvalidateModelTransform(Evt* script, s32 isInitialCall)


MakeLocalVertexCopy(Evt* script, s32 isInitialCall)


MakeTransformGroup(Evt* script, s32 isInitialCall)


ModifyColliderFlags(Evt* script, s32 isInitialCall)


ParentColliderToModel(Evt* script, s32 isInitialCall)


PlaySoundAtCollider(Evt* script, s32 isInitialCall)


PlaySoundAtModel(Evt* script, s32 isInitialCall)


ResetFromLava(Evt* script, s32 isInitialCall)


RotateGroup(Evt* script, s32 isInitialCall)


RotateModel(Evt* script, s32 isInitialCall)


ScaleGroup(Evt* script, s32 isInitialCall)


ScaleModel(Evt* script, s32 isInitialCall)


SetCustomGfx(Evt* script, s32 isInitialCall)


SetCustomGfxBuilders(Evt* script, s32 isInitialCall)


SetCustomGfxEnabled(Evt* script, s32 isInitialCall)


SetGroupVisibility(Evt* script, s32 isInitialCall)


SetModelCustomGfx(Evt* script, s32 isInitialCall)


SetModelFlags(Evt* script, s32 isInitialCall)


SetModelTexVariant(Evt* script, s32 isInitialCall)


SetRenderMode(Evt* script, s32 isInitialCall)


SetTexPanner(Evt* script, s32 isInitialCall)


SetTexPanOffset(Evt* script, s32 isInitialCall)


SetTransformGroupEnabled(Evt* script, s32 isInitialCall)


SetZoneEnabled(Evt* script, s32 isInitialCall)


TranslateGroup(Evt* script, s32 isInitialCall)


TranslateModel(Evt* script, s32 isInitialCall)


UpdateColliderTransform(Evt* script, s32 isInitialCall)

Model Functions

AddAnimatedModelRootPosition(Evt* script, s32 isInitialCall)


ChangeModelAnimation(Evt* script, s32 isInitialCall)


DeleteAnimatedModel(Evt* script, s32 isInitialCall)


GetAnimatedModelRootPosition(Evt* script, s32 isInitialCall)


GetAnimatedNodePosition(Evt* script, s32 isInitialCall)


GetAnimatedNodeRotation(Evt* script, s32 isInitialCall)


GetAnimatedPositionByTreeIndex(Evt* script, s32 isInitialCall)


GetAnimatedRotationByTreeIndex(Evt* script, s32 isInitialCall)


InitAnimatedModels(Evt* script, s32 isInitialCall)


LoadAnimatedMesh(Evt* script, s32 isInitialCall)


LoadAnimatedModel(Evt* script, s32 isInitialCall)


PlayModelAnimation(Evt* script, s32 isInitialCall)


PlayModelAnimationStartingFrom(Evt* script, s32 isInitialCall)


SetAnimatedModelRenderMode(Evt* script, s32 isInitialCall)


SetAnimatedModelRootPosition(Evt* script, s32 isInitialCall)


SetAnimatedModelRootRotation(Evt* script, s32 isInitialCall)


SetAnimatedModelRootScale(Evt* script, s32 isInitialCall)


SetAnimatedNodeFlags(Evt* script, s32 isInitialCall)


SetAnimatorFlags(Evt* script, s32 isInitialCall)

Message Functions

CancelMessage(Evt* script, s32 isInitialCall)


CloseChoice(Evt* script, s32 isInitialCall)


CloseMessage(Evt* script, s32 isInitialCall)


ContinueSpeech(Evt* script, s32 isInitialCall)


EndSpeech(Evt* script, s32 isInitialCall)


func_802D0C94(Evt* script, s32 initialCall)


SetMessageImages(Evt* script, s32 isInitialCall)


SetMessageText(Evt* script, s32 isInitialCall)


SetMessageValue(Evt* script, s32 initialCall)


ShowChoice(Evt* script, s32 isInitialCall)


ShowMessageAtScreenPos(Evt* script, s32 isInitialCall)


ShowMessageAtWorldPos(Evt* script, s32 isInitialCall)


SpeakToNpc(Evt* script, s32 isInitialCall)


SpeakToPlayer(Evt* script, s32 isInitialCall)


SwitchMessage(Evt* script, s32 isInitialCall)

NPC Functions

ClearPartnerMoveHistory(Evt* script, s32 isInitialCall)


CreateNpc(Evt* script, s32 isInitialCall)


DeleteNpc(Evt* script, s32 isInitialCall)


DisablePartnerAI(Evt* script, s32 isInitialCall)


EnableNpcBlur(Evt* script, s32 isInitialCall)


EnableNpcShadow(Evt* script, s32 isInitialCall)


EnablePartnerAI(Evt* script, s32 isInitialCall)


func_802CF54C(Evt* script, s32 isInitialCall)


func_802CF56C(Evt* script, s32 isInitialCall)


GetCurrentPartnerID(Evt* script, s32 isInitialCall)


GetNpcAnimation(Evt* script, s32 isInitialCall)


GetNpcPointer(Evt* script, s32 isInitialCall)


GetNpcPos(Evt* script, s32 isInitialCall)


GetNpcYaw(Evt* script, s32 isInitialCall)


GetPartnerPos(Evt* script, s32 isInitialCall)


InterpNpcYaw(Evt* script, s32 isInitialCall)


NpcFaceNpc(Evt* script, s32 isInitialCall)


NpcFacePlayer(Evt* script, s32 isInitialCall)


NpcFlyTo(Evt* script, s32 isInitialCall)


NpcJump0(Evt* script, s32 isInitialCall)


NpcJump1(Evt* script, s32 isInitialCall)


NpcMoveTo(Evt* script, s32 isInitialCall)


NpcSetHomePosToCurrent(Evt* script, s32 isInitialCall)


PartnerCanUseAbility(Evt* script, s32 isInitialCall)


PartnerIsFlying(Evt* script, s32 isInitialCall)


PlaySoundAtNpc(Evt* script, s32 isInitialCall)


PutPartnerAway(Evt* script, s32 isInitialCall)


SetNpcAnimation(Evt* script, s32 isInitialCall)


SetNpcAnimationSpeed(Evt* script, s32 isInitialCall)


SetNpcCollisionChannel(Evt* script, s32 isInitialCall)


SetNpcCollisionSize(Evt* script, s32 isInitialCall)


SetNpcDecoration(Evt* script, s32 isInitialCall)


SetNpcFlagBits(Evt* script, s32 isInitialCall)


SetNpcImgFXFlags(Evt* script, s32 isInitialCall)


SetNpcImgFXParams(Evt* script, s32 isInitialCall)


SetNpcJumpscale(Evt* script, s32 isInitialCall)


SetNpcPaletteSwapLower(Evt* script, s32 isInitialCall)


SetNpcPaletteSwapMode(Evt* script, s32 isInitialCall)


SetNpcPaletteSwapping(Evt* script, s32 isInitialCall)


SetNpcPos(Evt* script, s32 isInitialCall)


SetNpcRenderMode(Evt* script, s32 isInitialCall)


SetNpcRotation(Evt* script, s32 isInitialCall)


SetNpcRotationPivot(Evt* script, s32 isInitialCall)


SetNpcScale(Evt* script, s32 isInitialCall)


SetNpcSpeed(Evt* script, s32 isInitialCall)


SetNpcSprite(Evt* script, s32 isInitialCall)


SetNpcYaw(Evt* script, s32 isInitialCall)

Item Functions

AddBadge(Evt* script, s32 isInitialCall)


AddCoin(Evt* script, s32 isInitialCall)


AddItem(Evt* script, s32 isInitialCall)


AddKeyItem(Evt* script, s32 isInitialCall)


AddStarPieces(Evt* script, s32 isInitialCall)


AddStarPoints(Evt* script, s32 isInitialCall)


ClearVariable(Evt* script, s32 isInitialCall)


CloseChoicePopup(Evt* script, s32 isInitialCall)


CountFortessKeys(Evt* script, s32 isInitialCall)


DropItemEntity(Evt* script, s32 isInitialCall)


DropResizableItemEntity(Evt* script, s32 isInitialCall)


FindItem(Evt* script, s32 isInitialCall)


FindKeyItem(Evt* script, s32 isInitialCall)


GetItemPower(Evt* script, s32 isInitialCall)


HasKeyItem(Evt* script, s32 isInitialCall)


MakeItemEntity(Evt* script, s32 isInitialCall)


RemoveBadge(Evt* script, s32 isInitialCall)


RemoveFortressKeys(Evt* script, s32 isInitialCall)


RemoveItem(Evt* script, s32 isInitialCall)


RemoveItemAt(Evt* script, s32 isInitialCall)


RemoveItemEntity(Evt* script, s32 isInitialCall)


RemoveKeyItemAt(Evt* script, s32 isInitialCall)


SetItemAlpha(Evt* script, s32 isInitialCall)


SetItemFlags(Evt* script, s32 isInitialCall)


SetItemPos(Evt* script, s32 isInitialCall)


ShowConsumableChoicePopup(Evt* script, s32 isInitialCall)


ShowGotItem(Evt* script, s32 isInitialCall)


ShowKeyChoicePopup(Evt* script, s32 isInitialCall)

Audio Functions

AdjustMusicProximityMix(Evt* script, s32 isInitialCall)


ClearAmbientSounds(Evt* script, s32 isInitialCall)


EnableMusicProximityMix(Evt* script, s32 isInitialCall)


FadeInMusic(Evt* script, s32 isInitialCall)


FadeOutMusic(Evt* script, s32 isInitialCall)


PlayAmbientSounds(Evt* script, s32 isInitialCall)


PlaySound(Evt* script, s32 isInitialCall)


PlaySoundAt(Evt* script, s32 isInitialCall)


PlaySoundAtF(Evt* script, s32 isInitialCall)


PlaySoundWithVolume(Evt* script, s32 isInitialCall)


PollMusicEvents(Evt* script, s32 isInitialCall)


PollMusicEvents(Evt* script, s32 isInitialCall


PopBattleSong(Evt* script, s32 isInitialCall)


PopSong(Evt* script, s32 isInitialCall)


PushBattleSong(Evt* script, s32 isInitialCall)


PushSong(Evt* script, s32 isInitialCall)


RegisterMusicEvents(Evt* script, s32 isInitialCall)


SetBattleSong(Evt* script, s32 isInitialCall)


SetMusicTrack(Evt* script, s32 isInitialCall)


SetMusicTrackVolumes(Evt* script, s32 isInitialCall)


StopSound(Evt* script, s32 isInitialCall)


StopTrackingSoundPos(Evt* script, s32 isInitialCall)


UseDoorSounds(Evt* script, s32 isInitialCall)


UseRoomDoorSounds(Evt* script, s32 isInitialCall)

FX Functions

DismissEffect(Evt* script, s32 isInitialCall)


DismissItemOutline(Evt* script, s32 isInitialCall)


func_802D7B74(Evt* script, s32 isInitialCall)


func_802D7690(Evt* script, s32 isInitialCall)


InterpMotionBlurParams(Evt* script, s32 isInitialCall)


PlayEffect(Evt* script, s32 isInitialCall)


RemoveEffect(Evt* script, s32 isInitialCall)


SetMotionBlurParams(Evt* script, s32 isInitialCall)


SetSleepBubbleTimeLeft(Evt* script, s32 isInitialCall)


ShowEmote(Evt* script, s32 isInitialCall)


ShowRecoveryShimmer(Evt* script, s32 isInitialCall)


ShowSleepBubble(Evt* script, s32 isInitialCall)


ShowStartRecoveryShimmer(Evt* script, s32 isInitialCall)


ShowSweat(Evt* script, s32 isInitialCall)

Virtual Entity Functions

CreateVirtualEntity_ALT(Evt* script, s32 isInitialCall)


CreateVirtualEntity(Evt* script, s32 isInitialCall)


CreateVirtualEntityAt(Evt* script, s32 isInitialCall)


DeleteVirtualEntity(Evt* script, s32 isInitialCall)


GetVirtualEntityPosition(Evt* script, s32 isInitialCall)


InitVirtualEntityList(Evt* script, s32 isInitialCall)


SetVirtualEntityFlagBits(Evt* script, s32 isInitialCall)


SetVirtualEntityFlags(Evt* script, s32 isInitialCall)


SetVirtualEntityJumpGravity(Evt* script, s32 isInitialCall)


SetVirtualEntityMoveSpeed(Evt* script, s32 isInitialCall)


SetVirtualEntityPosition(Evt* script, s32 isInitialCall)


SetVirtualEntityRenderCommands(Evt* script, s32 isInitialCall)


SetVirtualEntityRenderMode(Evt* script, s32 isInitialCall)


SetVirtualEntityRotation(Evt* script, s32 isInitialCall)


SetVirtualEntityScale(Evt* script, s32 isInitialCall)


VirtualEntityJumpTo(Evt* script, s32 isInitialCall)


VirtualEntityLandJump(Evt* script, s32 isInitialCall)


VirtualEntityMoveTo(Evt* script, s32 isInitialCall)