Introduction


Arc System Works fighting games, specifically those made in Unreal Engine by Team RED, can be heavily modded. From basic texture and model imports all the way to gameplay overhauls and custom characters, these games have a ton of modding potential. However, modding documentation for these games is incredibly lacking.

Guides for easier mods like texture and model imports are easy to find, but are outdated and lacking critical information. Meanwhile, documentation for editing gameplay scripts is harder to find and split across multiple resources. And there is only one document for custom characters, and it's incredibly lacking. More niche mod types such as UI mods or code mods have zero documentation at all, forcing anyone interested into asking around in Discord servers hoping for answers.

This book aims to fix that. Included within its pages will be thorough information on modding the Team RED games, primarily for the Unreal Engine 4 ones. Most information can be applied to every UE4 game. However, each game has its own quirks, so there will be more specific information in their own categories.

As Guilty Gear Xrd was made in Unreal Engine 3, a vastly different engine from Unreal Engine 4, most general information will not be directly applicable. Pages for it will be added later.

Contributing

If there is something missing that you would like to add, please leave an issue at the GitHub repository. If you have experience with writing Markdown, you may also make a pull request.

Installing Unreal Engine


Arc System Works has customized various aspects of Unreal Engine 4 to suit their needs.

This means that although we can install the plain vanilla UE4 and use that to make mods, we'd be missing on key features needed to make them work properly. Thankfully, Ryn has reverse-engineered several of these changes and implemented some of the key features we require into custom UE4 builds.

You can find the download links below. Just pick the one matching the game you wish to mod. Note that the exact version is important; you cannot do things like use UE4.27 to mod DBFZ.

GameEngine
Dragon Ball FighterZUnreal Engine 4.17
Guilty Gear -Strive-Unreal Engine 4.25 Plus
DNF DuelUnreal Engine 4.25
Granblue Fantasy VersusUnreal Engine 4.21
Granblue Fantasy Versus RisingUnreal Engine 4.27

The Guilty Gear -Strive- editor may receive periodic patches in another archive. You'll want to download both GGSTCookedEditor.rar and GGSTCookedEditor_Patch.rar. After extracting the first RAR, extract the second RAR into the same folder. This should replace files.

Starting the editor


Extract all of the contents from the custom UE4 archive you downloaded in the previous step. You can use tools like WinRAR or 7-Zip to do so.

Once that is complete, you can fire up the engine with .\Engine\Binaries\Win64\UE4Editor.exe

The current Guilty Gear -Strive- editor works differently. It will be booted from .\RED\Binaries\Win64\GGSTCookedEditor.exe.

You do not need the Epic Games Launcher for this.


The first boot of the UE4 editor usually takes a while to get going. If you want to check whether it's actually starting or not, open Task Manager (Ctrl + Shift + Esc) and check for high CPU usage. This usually means it's busy compiling shaders.

Once Unreal finishes initializing, you will be met with the Project Browser menu. While you could create your own project from scratch, we highly recommend starting off with one of the pre-made custom projects.

Getting the project for your game


The prebuilt custom projects provide all of the custom asset types the game supports, and for newer games, they even include many assets from the game, such as UI elements or data tables.

Below are download links for each game:

The Guilty Gear -Strive- custom project does not come with content by default. To get the content, you can copy pakchunk0-WindowsNoEditor.pak from your copy of Strive into RED\Content\Paks. If the Paks folder does not exist, create it.

Additionally, the Strive project may receive asset patches for certain assets. To use these, extract GGSTContent_Patch.rar into RED.

Once you have downloaded the correct project, extract it to your Unreal Projects directory. If you've run the editor before, you can usually find it at Documents\Unreal Projects\. For Guilty Gear -Strive-, the custom project is already part of the editor.

You'll also need a working installation of Microsoft's Visual Studio in order for the editor to be able to compile the project.

  • Dragon Ball FighterZ requires Visual Studio 2017.
  • Guilty Gear -Strive- is already compiled, so you do not need Visual Studio.
  • DNF Duel, and Granblue Fantasy Versus Rising require Visual Studio 2019.

For more information on how to set up Visual Studio for UE4, read the official Unreal Engine documentation.

External tools


Besides Unreal Engine 4 itself, several key pieces of software are used for nearly every aspect of modding these games. We recommend just getting all of them.

In addition, several specialized tools were written specifically for modding Arc System Works games. However, they are specific in their functionality, so you'll find in their respective sections of this document whenever they are needed.

Using Fmodel


Using Umodel


Using AssetEditor


Using UAssetGUI


Using Blender


Note that this document will not cover the basics of Blender.

Several tools were created to make Blender compatible with modding Arc System Works games.

FModel with Arc System Works animation support

Download the UEFormat addon Download the modified FModel with ArcSys animation support

FModel supports exporting models and animations to a new "UEFormat", which is more accurate than either PSK/PSA or glTF. To export to UEFormat, open FModel's settings, then click on the Models tab. Finally, set Mesh Format to UEFormat (uemodel).

Now, you can right-click a model, animation, or folder containing either, and export the models/animations to UEFormat. The attached Blender addon can then import these.

Aerthas' custom materials & shaders

Download BLENDER-Arc-System-Works-Shader

While not strictly needed for modding, the shader is highly recommended for previewing models and textures within Blender itself.

Aerthas made a ton of practical videos on how to use his shader. Here is a link to a playlist containing said videos.

Scripts

Browse Arc-Sys-scripts

The most useful scripts have their own wiki pages, which also go into detail on how to use them.

A note on Blender FBX export into UE4

The default Blender FBX exporter, while usable, is not preferred for Unreal Engine 4 modding. If you're willing to pay up, consider Better FBX Importer & Exporter instead.

If you are modding Guilty Gear -Strive- or a game newer than it, there is also Epic Games' very own Send to Unreal addon. The linked release is the last one that works on UE4.25. Newer releases only support UE4.27 and above, and the most recent releases only supports UE5.

Note that you must have connected your GitHub account to your Epic Games account in order to view this page. Click here for more information.

If you are not using the Better FBX addon, there is one step that must be followed in order to export an FBX to Unreal:

  • The Armature for your model must be named Armature. If it is named anything else, skeletal mesh imports will not animate correctly.

Additionally, if you are not using the Send to Unreal addon, there is one more step that must be undertaken:

  • Under the Scene tab of the Properties menu, set the Unit Scale to 0.01. You will also need to scale your model proportionately (100 times).

Loose file loading


Mesh/Model


Texture/Colors


Animations


Hurt & hitboxes


Particles


Moveset


Movesets are defined on a per-character basis in a custom scripting engine developed by Arc System Works. These scripts are called BBScript, but are often abbreviated to BBS.

BBS is a very well-documented and understood format, allowing us to not just alter characters, but create entirely new ones as well.


We highly recommend you read A Sketch of the Arc System Works Engine Script, by Pangaea, first.

For the sake of consistency, all example code uses internal ArcSys nomenclature. Game-specific code might be included where deemed necessary.

Extracting & injecting BBS


Automated method

All In One BBScript Tool

TODO: Upload generic versions of Broscar's DBFZ scripts


Manual method

Manually extracting and injecting scripts is preferred if other assets need to be packaged.

Bulk extracting all BBS from the game

Open the game's pak in FModel, and open the package search window (Ctrl + Shift + F). Type in BBS_. Select all items in that window (Ctrl + A), right click, and select 'Export Raw Data (.uasset)'.

The files will appear in the 'Output' directory, but with their original folder structure intact, which can be time consuming to work with. To consolidize all of these BBS files, you can slap any of these scripts into your FModel directory. When you run it, it'll copy all BBS files into a single folder named 'bbs'.

TODO: Slap scripts into a github and just offer download links. Also, create a Windows batch version.

#!/bin/bash
mkdir -p "./bbs/"
for f in `find "Output" -type f -name "BBS_*"`
    do cp -f "${f}" "./bbs/"
done

Extract a script from the .uasset/.uexp

Using Pangaea's ggst-bbs-unpacker, scripts (and other ArcSys binaries) can be extracted. After exporting the .uasset from FModel, open the .uasset and .uexp files using ggst-bbs-unpacker. Then, click Extract and save it in a location of your choosing.

Parse the script

Using Pangaea's BBScript tool by itself, you will need to use the command line. If you have never used the command line before, find a tutorial on it first.

In the command line, run ```cmd bbscript parse


where <config> is the matching configuration filename in static_db, <binary> is the extracted script, and <text> is the file to parse to.

<div class="warning">

If the file to parse to already exists, an error will be thrown to prevent accidental overwriting. If you do wish to overwrite the given file, put `-o` after the command.

</div>

### Rebuild the script

The BBScript tool can also rebuild scripts from text back into binary form. 

In the command line, run ```cmd
bbscript rebuild <config> <text> <binary>

where is the matching configuration filename in static_db, is the modified text, and is the script to write to.

Inject the script back into the .uasset/.uexp

ggst-bbs-unpacker can also inject scripts and other binaries back into the .uasset/.uexp. Open the original .uasset and .uexp. Then, select the file you wish to inject. Finally, click Inject.

Learning BBS


The two best tutors to learn BBS from are ArcSys and yourself. Read the vanilla game scripts, try to understand them, and go in and get your hands dirty. Learn by experimentation.

Having said that, we're not throwing you completely into the deep-end. What follows on this page is a sort of quick overview of how BBS is structured.

If you want an actual glossary encompassing nearly everything BBS, check out BBScript Documentation (Strive), DBFZ BBS doc or DBFZ BBS Lookup.

Note that the latter uses Broscar's bbscript for the name_given field and any code examples, so you can't directly copy-paste those unless you use the same system.

State

The very basis of a move. The game reads and executed a state from top to bottom. This is called the program flow.

When a state ends for a character object, that character object is returned to a neutral state by native code (CmnActStand while standing, 'CmnActCrouch' while crouching, or CmnActJump while airborne). When a state ends for an effect object, that effect object is deactivated.

If you require players to be able to enter a state directly (e.g. through user input), you'll have to register it with addMove and registerMove. However, that is not needed if you only interact with a state by jumping to it.

Subroutine

A subroutine (or function) is a separate block of code that can be reused in any state. It cannot contain sprites, but all other elements of BBS are usable.

Think of calling a subroutine as copy-pasting the contained code into the part of the state you call it in.

Subroutines are usually used to share one block of code with multiple different states. For example, if several special moves share common code, a subroutine could be used.

If a subroutine starts with cmn (not case-sensitive), that means you'll find that specific subroutine inside CMNEF, and not inside the character's script.

Labels

Normally, states are run from top-to-bottom. However, with labels, you can instead have the game jump to a specific point within a state.

Label: s32(loop)
CellBegin: s32(xxx034_13), 3
CellBegin: s32(xxx034_14), 3
CellBegin: s32(xxx034_12), 3
CellEnd:
Goto: s32(loop)

The above code runs an indefinite loop. However, this isn't very useful by itself. Instead of Goto, you can instead write ID_GotoIfOP2: s32(loop), (IS_LESS_OR_EQUAL), var(ActionTime), int(60). Now the loop will run until ActionTime hits 61. ActionTime is a variable that tracks how long an object is in a certain state in terms of frames. If ActionTime is 61 or more, the gotoLabel function does not trigger, and regular state flow is resumed from that point onwards.

You can find more functions like Goto by visiting DBFZ BBS Lookup and clicking on the 'Flow' button next to the search bar.

Variables

Interrupts

Also known as upon in the standard BBS dialect.

An interrupt executes a bit of code the moment its condition is triggered. This happens independent of the script flow, meaning you can allow your objects to react to an event the moment it actually happens.

ActionBegin: s32(ExampleMove) {
    InterruptBegin: (IMMEDIATE) {
        copyVar: var(act1), int(0)
        InterruptBegin: (IDLING) {
            if: var(act1) {
                addTension: 20
            } endIf:
        } InterruptEnd:
        InterruptBegin: (RECEIVE_ATTACK) {
            clearRegisteredUponCode: (IDLING)
        } InterruptEnd:
    } InterruptEnd:
    CellBegin: s32(avp022_01), 1
    CellBegin: s32(avp022_02), 1
    CellBegin: s32(avp022_03), 1
    OpCopy: var(act1), int(1)
    CellBegin: s32(avp022_04), 1
    CellEnd:
} ActionEnd:

When you register an interrupt, you also define what code runs when it is triggered. As you can see, calls to set interrupts can also be nested.

In the code above, InterruptBegin: (IMMEDIATE) activates before everything else, even before the first sprite is drawn. It also registers two new interrupts. IDLING runs every game tick.

As an extra challenge, try to understand what this entire block does.

CMNEF

CMNEF is a special BBS file used to share states and subroutines among all objects in the game. This makes it extremely potent for applying changes that affect all characters and all spawned effect objects.

However, if you alter it, it means your mod becomes incompatible with any other mods that change it.

In short, if you're creating a single custom character, you're better off not changing it. If you're making a complete overhaul / balance patch, use and abuse it.

Signals

Interacting with other objects

applyTo, triggerUponInObject, signals, copyVarFromObject, linkObject

Examples

Here is a document listing several techniques and how one can choose to implement them:

google doc

TODO: Split off the BBS snippets from the DBFZ Google Doc into their own document.

  • Armor
  • Locking out moves
  • Revive on death

Tips

In 10.1 there's a section called Bulk extracting all BBS from the game. If you parse all of them, you can use them to find the various uses of a certain bit of code in all vanilla game scripts. Notepad++, for example, allows you to search for bits of text in multiple files (ctrl+shift+f). Just point it at the directoy where all those parsed scripts are stored, and you're good to go!

How BBS works in-game


Generic states

The native code of the game looks for, and uses, several default states. This means the developers don't have to explicitly handle generic state transitions. If a standing move ends, characters start looping CmnActStand. If a character gets hit, they'll go into the state that matches the hit reaction.

Native code is also able to affect script flow within those default states.

ActionBegin: s32(CmnActJump) {
	Label: s32(_Upper)
	Label: s32(upperloop)
	CellBegin s32(kfs021_00), 3
	CellBegin s32(kfs021_01), 3
	CellBegin s32(kfs021_02), 3
	CellEnd:
	Goto: s32(upperloop)
	Label: s32(_UpperToTop)
	CellBegin s32(kfs021_03), 2
	CellBegin s32(kfs021_04), 2
	CellBegin s32(kfs022_00), 2
	CellBegin s32(kfs022_01), 2147483647
	Label: s32(_Top)
	CellBegin s32(kfs022_02), 2147483647
	Label: s32(_TopToDown)
	CellBegin s32(kfs022_03), 3
	CellBegin s32(kfs022_04), 2147483647
	Label: s32(_Down)
	Label: s32(downloop)
	CellBegin s32(kfs022_05), 3
	CellBegin s32(kfs022_06), 3
	CellBegin s32(kfs022_07), 3
	CellEnd:
	Goto: s32(downloop)
} ActionEnd:

As you can see, there are several different labels in this CmnActJump state, but you won't ever find a function that actually jumps to _TopToDown. Instead, the native code does so itself when the proper conditions are met (e.g. airborne, Y-speed less than 0).

Native code can also add function calls whenever it detects certain active state names. For example, DBFZ's CmnActMikiwameMove (Vanish) will initiate a worldStop, even if all relevant calls in the script have been deleted.

Generic subroutines

Native code is also able to call a subroutine for an object of its own accord. Here are a few notable ones:

SubroutineFunctionality
OnIdlingCalled every game tick, no matter which state the object is in.
Affected by worldStop.
OnLanding
OnDamage
OnGuard
OnFrameStepCalled every game tick, no matter which state the object is in.
Not affected by worldStop.

For DBFZ, OnIdling is called even for assist characters that are off-screen.

Thinking outside the box


BBS allows you to do much more than simply change damage numbers and spawn projectiles.

Although it's a bit limited by the very nature of functioning inside of a fighting game framework, you can effectively achieve nearly anything you want with it, as long as you're willing to get creative.

This page serves to highlight a few of these techniques, and lists some examples of what is truly possible with BBS.

Utilising secondary 'helper' objects

Changing character moves by only changing CMNEF

Dynamically altering the move registry

Examples

  • Stage hazards in DBFZ
  • Lethal League in DBFZ
  • FPS in DBFZ

TODO: Actually make these things publicly available and do small write-ups on them.

Per-game BBS specifics


Although the concept of BBS is shared among all modern Arc System Works games, their exact implementation still differs per title.

In this section, you'll find various bits of information pertaining to BBS in their respective games. This includes tweaks, bugfixes, and other bits of documentation managed by the community.

Strive


DBFZ


Bugs

  • BRS: Replace createParticle: s32'bg_ roundsmokeL', 0 with createParticle: s32'bg_groundsmokeL', 0
  • ASN: Do a global search and replace to turn Don’t into Dont
  • JNNEF: Do a global search for KidanFire', 0, 100 and remove the odd symbol at the beginning of every one of them.
  • FRN: The subroutine named FDownLoop_Type is missing 1 function.
    • Add storeValue: (VARIABLE), 52, (STATIC), 1 if you're using old bbscript.
    • Add storeValue: Mem(52), Val(1) if you're using regular bbscript 1.0(+).
    • Add copyVar: var(act7), int(1) if you're using Broscar's bbscript.
    • Add Unknown46: Unknown, Unknown, Unknown, Unknown if you're using Burritoscript.

Broscar's workflow

A consequence of DBFZ barely having any modders active in BBS, is that Broscar has been pushing forward solo, with little regard for existing BBS conventions. You may choose to go along for the ride.

ProsCons
Easy to use tools that allow for very fast iterationThe first setup requires a bit more work
Detailed documentationUses a different 'dialect' of BBS.
All concepts of BBS still apply, but functions and variables use different keywords.
Automatically fixes the parser bugs for BRS, ASN and JNNEFAssumes you have some experience with programming
Has better indentation, code folding and works with the Function list feature of Notepad++

https://github.com/dobosken/bbscript

https://github.com/dobosken/dbfz_npp

https://dobosken.github.io/dbfz_bbs_lookup/

TODO: Clean up and share build scripts. Check if ye olde Windows versions still work.

Audio


UI Modding


Due to limitations of creating custom projects in earlier Unreal Engine versions, this section is not applicable to Dragon Ball FighterZ or Granblue Fantasy Versus. At the current moment, it is not currently feasible to mod UI in those games.

If you are modding Guilty Gear -Strive-, DNF Duel, or Granblue Fantasy Versus Rising, continue with this section.

UMG basics


UMG (Unreal Motion Graphics) is the built-in UI framework in Unreal Engine, and is what Team RED uses in all of their games for UI. As such, learning the basics of UMG is critical to modding.

This topic is beyond the scope of this guide, but I will leave useful resources for using UMG here:

Once you feel like you have a decent grasp on UI modding, proceed with this section.

Finding widgets


In Team RED Unreal Engine 4 games, all widgets can be found in RED\Content\UI. The overall contents of the folder differ per game, but names are fairly consistent.

  • The HUD for battles can be found in UI\battle in most games. In Strive, it can be found in UI\Battle_Xrd3.
  • Widgets with Allset in their names refer to the "master" widget. This widget is the one that's directly displayed, containing all other widgets used for its section.
  • Strive tends to postfix its UI folders with Xrd3. This was the codename for Strive during development.

Look inside the folder in the custom project, and try to find the UI element you're looking for. There will be a visual preview of the widget upon opening it. Once you find it, feel free to get creative! Design is incredibly subjective, so I will not provide a tutorial on that. But before you do, make sure to check out the next page, as there are several common pitfalls that could ruin your mod.

Common pitfalls


Modding UI can be quite complicated, and you may run into crashes. Here are several of the common pitfalls I've personally run into, and how they can be avoided.

  • If the game crashes upon loading the UI element, there is a very good chance that you deleted a part of the widget. Never delete parts of the widget, as the game may try to reference it. Even something as innocuous as a text box could crash the game if it was missing. Instead, set its visibility to Collapsed.
  • (Strive/DNF) If your UI elements don't appear in-game, you most likely did not package the Allset widget. In earlier versions of Unreal Engine, the widget hierarchy is "baked" into every widget, and only the directly created widget has its hierarchy referenced. This means that all of your changes to the child widget will be disregarded unless you also package the Allset widget.
  • Some widgets may also contain Blueprint code. If this code is not properly replicated, the game may act unpredictably. Replicating this code deserves a section of its own, but I will leave you with the primary tool I use to replicate blueprint code: kismet-analyzer by trumank.
  • If parts of a widget show up as pure black in the editor, they probably use a material. The material can be found under the Details panel for the UI element. The autogenerated materials are broken by default for UI elements, but they likely contain a texture that can be used to preview the material. You'll know if it's the right one because it will resemble the UI element in-game. Simply plug that texture into Final Color, and its alpha channel into Opacity and Opacity Mask.

Code


Code mods are the "holy grail" of modding in any game. Being able to change how the game works at a fundamental level will always be incredibly powerful. However, such power requires programming experience and intimate knowledge of the game internals.

Luckily, Guilty Gear -Strive-'s arcade version shipped with debug symbols, which gave tons of insight into how all Team RED games work, and especially cracked open Strive.

Additionally, various breakthroughs in the last year of Unreal modding has made making code mods for UE4/5 games easier than ever. The advent of UE4SS revolutionized code modding for Unreal Engine games, with its ability to create Lua, Blueprint, and C++ mods.

As code modding is such a broad topic, this section expects a basic understanding of how to use C++ and how to use a disassembler. Any disassembler may be used, but this guide will assume the use of Ghidra, as it is the best open source option.

Creating a .pak archive

Installing your mod