Deep Rock Galactic

Deep Rock Galactic

This is the mod.io page for Deep Rock Galactic. Here you can find mods for the game made by others and also upload mods yourself. NB! This page is under development, guidelines, instructions, and more coming soon.

Learn more and find the game on Steam.

How To: Blueprint Mod

This video series aims to walk people through the complex process of UE Blueprint Modding!

Posted by on (updated ago)


DRG Mods: A Comprehensive Guide to Blueprint Modding

Please do not hesitate to ask for help on the DRG Modding Discord in #mod-questions!

Credits:
Buckminsterfullerene - Originally wrote and maintains guide.


Contents

  • 1. Introduction
    • Tools
    • Reading this guide
    • Final note
  • 2. How blueprints work
    • How BP mods are loaded into DRG
    • Framework mods
    • Methods of BP modding
    • Useful acryonyms to know for BP modding
  • 3. Setting up your UEE workspace
  • 4. No-dummy method
    • Creating your first DRG mod
    • A bit more complex version
    • Outputting time dilation to the HUD
    • Toggle HUD button
    • Saving and loading settings
    • Basic replication
  • 5. Dummy method
    • Kill player on button press
    • Self-destruct Bosco on button press
  • 6. Packaging your mod
    • Using DRG Modding Automation Scripts
    • From UE
    • Directories to never cook
  • Video Tutorial
  • Feedback

1. Introduction

Tools

Before you can even get started with your mod, you need to install a few tools:

IMPORTANT: By the time you are reading this guide, you should already have these tools and have at least the minimum required knowledge to use them (more on UE4 later). If not, I refer you to Rauliken's more general guide on the DRG Modding discord.

Reading this guide

Make sure that you read through every detail of this guide thoroughly as missing something may result in many problems down the line. Of course, you can always refer back to this if you need assistance on anything. Critically important details are highlighted in bold, and optional but useful information is highlighted in italics. Inline code is used for 'specifics'.

You should know the basics of Blueprinting in Unreal Engine. There are plenty of tutorials on YouTube. You should also know how Blueprinting associates with C++; here is a really good video on that. If you haven't already, watching this video is basically a requirement to understand much of what is going on here.

If you are into other forms of UE modding, please don't hesitate to join the UE Modding discord server.

Final note

Please be aware that as BP modding becomes increasingly advanced, this guide may become out of date until I update it. Since I'm really busy all the time this may not happen for a few days or weeks.


2. How blueprints work

How BP mods are loaded into DRG

Native spawning is something that was added by the developers when the modding update dropped. This allows you to load your blueprint from the BeginPlay event node. If you want your BP mod to have user-interactable UI (like a settings menu), you should use a framework like ModHub.

Framework mods

Usually, you will only want to use a framework mod if you want the user to be able to change settings for your mod in game. If you don't need this for your mod, you do not need to use a framework. Framework mods so far have always come in two parts:

  • The devkit tools that you put into your mod's UE project for interfacing with your mod
  • The in-game mod dependency that runs all of the framework's functions and processes

I suggest that for now, as you are learning BP modding, that you don't touch any frameworks, otherwise you'll find yourself spending more time wrangling with widgets than actually learning new techniques.

ModHub

ModHub is the "official" shared-settings mod interface. If you want a place to put settings widgets for your mods, use this. You can view the source here, and the guide for use here (you need to be in the DRG Modding discord).

DRGLib

Samamster has been developing this framework as a more feature-rich BP modding library. The great thing about this library, is that it provides helper functions and DRG-like UI objects that makes BP modding just that little bit easier. You can view both the source and guide for use here.

Methods of BP modding

There are two methods, in a way that you can use both at the same time or not if you wish:

  • No-dummy method. This doesn't require any knowledge in C++ to use. You also won't need the game dumps. This is limited to built-in UE BP functions and events or those you have from a framework devkit, or you created yourself. You can still achieve a fair bit from this but are limited.
  • Dummy method. You can manipulate the functions, variables and events that are running in the game. You can figure out what you need from looking at the game's dumps files. You can find the most up-to-date dumps versions here (be aware that GitHub only displays the first thousand classes on its website version).

Useful acronyms to know for BP modding

  • ABP – Animated BluePrint
  • BP – BluePrint
  • GD – Game Data
  • GM – GaMe
  • ID – IDentifier
  • ITM – ITeM
  • LIB – LIBrary
  • LVL – LeVeL
  • MUT – MUTators
  • OC – OverClocks
  • PRJ – PRoJectile
  • UI – User Interface
  • UPC – UPgrade Category
  • UPG – UPgrade Group
  • W – Widget
  • WND – WiNdow Widget
  • WPN - WeaPoN

3. Setting up your UEE workspace

For ANY Blueprint mods, you MUST name your project FSD. Therefore, I make all my mods inside the same project and then delete the mods I don't want to pak before I pak them. The reason the name must be FSD, is because that is what the original game's UE project is called. "FSD" is probably the code-word for DRG (most games have these for various reasons).

First, select the games category, then click next:

image003

Then click on blank and click next:

image002

Select the following options on the project settings:

image001

Then hit create project, and you're ready to move onto the next part!


4. No-dummy method

I'm going to run through the creation of a super simple mod which then outputs text to the screen, and finally saves and loads mod data. Note that my UE might look different to yours – don't worry, I'm just using a couple of plugins that makes it looks nicer.

Creating your first DRG mod

This mod will simply set the global time dilation (the speed) of the game to 5. The purpose of this mod is to just run through the process of making a mod – the time dilation bit will validate that we know the mod is loaded.

To spawn a blueprint into the game, first you need to create a folder with the same name as your mod inside the Content folder. Then create a blueprint inside of that called one of two things:

  • InitSpacerig – this will load your blueprint when the player is spawned in the spacerig.

  • InitCave – this will load your blueprint when the player is spawned in the drop pod at the start of a mission.

To make a blueprint, right click inside the content browser and hit Create Blueprint Class. Then inherit it from Actor.

image004

Double click on InitSpacerig first, and navigate to the Event Graph tab. We can ignore Event ActorBeginOverlap and EventTick. Drag off Event BeginPlay and find the set global time dilation node:

image005

Now set this to 5.

image006

To save, hit the Compile button on the toolbar. Remember to compile and save your project every now and again. Tip: you can compile and save at the same time when you click compile, by clicking the little arrow dropdown to the right of compile button and setting save to "always":

image007

Now we are ready to package and test this simple mod.

Refer to section 6 on packaging your mod.

When you load into the game, everything should be moving 5x as fast! More importantly, now you know how to make blueprint mods!

A bit more complex version

This time around, the mod will change the time dilation based on a key press.

First though, let's streamline the same mod to be loaded by both InitCave and InitSpacerig, since we don't want to copy and paste everything into both BPs.

Make a new BP called something like Mod (it doesn't matter). Now in InitSpacerig and InitCave, we want to spawn this actor immediately. Get out a Spawn Actor From Class node, and set the class to whatever you called your mod BP. Do this in both InitSpacerig and InitCave:

image008

We're not quite done yet, we need to set Collision Handling Override to always spawn, ignore collisions. Also, right click on that orange Spawn Transform pin and hit split struct pin. If you don't do this, it won't know where to spawn the actor. Later on, if you're spawning a physical actor but don't want it to be seen, spawn it at like Z=99999.

Make sure to compile and save when you're done in both BPs!

Now inside of your new mod BP, we want to add the functionality that increments or decrements the global time dilation based on what key you press. Let's say that the hyphen key decrements it by 0.5 and the equals key increments it by 0.5.

First, let's make a variable that stores the time dilation. Set its default value to 1. Now we need to get the key events. Right click on the graph and type Hyphen and get out that node, and then do the same for Equals. Make sure that you enable input when the mod is spawned, otherwise this won't work:

image009

Player index 0 is always host, i.e. your player if you are the only one in the server or hosting a server.

Now make your mod functionality like this (you should have done basic blueprinting before as a pre-requisite to this so you should be able to easily follow what this does):

image010

Now let's make sure that the dilation never goes below 0 (otherwise the game crashes) or higher than 8 (otherwise FPS is reduced the rubble):

image011

Before we go any further, let's compile, package and test the mod.

Outputting time dilation to the HUD

Now we want to output the current dilation to the HUD (Heads Up Display) so we can see the value in-game.

In our Tutorial folder, make a new widget blueprint called something like HUD:

image012

Inside of the widget designer, find the text box widget in the palette and drag it out. Place it anywhere on the window – I recommend putting it about 2/3 the way up the left or right side of the window, which is where we know there is empty space on the DRG HUD. This text will just be some text like "Time Dilation:". Next to it, put another text box with the text "1". This is where we will change the value. The default dilation in the game is 1 so we set the default text to match that.

image013

Now name that second text box to something sensible. You also need to check the Is Variable box, otherwise we won't be able to change it from our mod BP.

image014

Hit Compile and switch back to the mod BP. To access and set our text box, we need to first construct the widget and get an object reference from it:

image015

This HUD Ref variable is our object reference. The variable type is that HUD widget:

image016

Now drag out the HUD Ref variable and we want to get the object reference to the txtDilation:

image017

Now to set its text, we drag out the Set Text (Text) node:

image018

Now we want to set the text to the value of time dilation:

image019

image145

Now we can see our time dilation and that it changes when we hit our key binds. But what if we want to toggle the HUD on or off?

Toggle HUD button

First, we need to go back into our HUD designer and set that description text box to a variable so we can control it from our mod:

image021

Now back in our mod, make a variable that will store the boolean value of whether or not the HUD is enabled. Make sure the default value is true.

When a key, say, '#', is pressed, we want to switch the visibily of the text boxes between Visible and Collapsed (you can read the tooltip regarding the differences between Collapsed and Hidden):

image022

Let's check to see if this works!

Now… what if we want to save the dilation and if the HUD is enabled so that the next time the mod is loaded we save our settings?

Saving and loading settings

We first need to make a new blueprint that inherits the SaveGame class:

image023

Inside of it, simply make the two variables that we want to save, and make sure that they are set to public:

image024

Back in our mod, make a variable that is an object reference to this SaveData blueprint:

image025

Now let's make a function that will load the save. This checks if the save game exists, and if it does, load the game from the slot. If it does not, we create an empty save game object. The save file name is Mods/<your mod name>/<your name name>. The saves are stored at FSD/Saved/SaveGames. Here my save name is Mods/Tutorial/Settings:

image026

Call this function after we construct our widget (I've added a sequence node to tidy up a bit).

image027

Now we want to make another function that loads the save data into our mod variables. We also want it to change the HUD values, i.e. if the HUD is disabled in the save, we want to toggle the HUD off when we load it in:

image028

Chuck it after load save:

image029

The Toggle HUD and Set Dilation Text functions are just what we have already done but put into functions so that we don't have duplicated code.

image030

image031

The last thing we want to do is save our values every time we change them. So let's make a new function that does this:

image032

Now we call this function when we change time dilation and the HUD value. Now the mod looks like this (I've tidied it up with comments):

image033

Now, compile, package and test. If you toggle your HUD off, and set dilation to like 5, then restart the game, your settings should be saved!

But we want this mod to work in multiplayer, so we need to do a bit of basic replication and handling with that.

Basic replication

Before you read this section, I suggest that you go watch some basic UE4 replication video on YouTube as it will explain the basic processes that I will use here. If you're not interested in replication (it's hard), don't worry, you can skip this section without any problems.

While the mod works perfectly fine in singleplayer, it goes all a bit funky in multiplayer. If you're the host, you need to replicate (copy) the time dilation that you're setting for the rest of the clients in the server. Otherwise, anything client side only (like player movement) will not be affected. And if you're not the host, then you shouldn't be able to change the time dilation because otherwise things get even more funky if yours is different to the server's.

So firstly, let's just get the easy bits out of the way. If a client is not the server, disable the input so that they can't change their local time dilation value. We can do this by simply using the Is Server node:

image146

We also need to prevent the time dilation from being set when the save is loaded. While we could do the same Is Server check before the entire load save section, we want to still allow all the clients to load the Is HUD Enabled value from their own saves. So we can just do the check inside of Load Save Data instead.

image149

Now for the fun stuff. First, we need to change the mod settings to allow replication. Click Class Defaults on the top bar and change the replication settings like this:

image150

You also need to go into the class defaults for InitCave and InitSpacerig and change the replication settings like this:

image151

Next, we need to actually set the Time Dilation variable to replicate. You can do this by clicking on the variable and setting the Replication parameter to RepNotify. The reason we want to use this, instead of just Replicated, is that we want to notify the clients when the value of it changes.

image147

You may notice that in the functions pane, a new function called OnRep_<your variable> e.g. OnRep_Time Dilation, has been created. This function is called by every client whenever the value is changed, including the host. You may also notice that 2 white spheres have appeared on all the variables' getters and setters - this shows that the variable is set to RepNotify (one sphere is Replicated). You can also hover over the setters and it'll tell you how it works.

So inside this new OnRep function, when we then set the global time dilation and HUD value, we need to make sure that it only runs for non-host clients (AKA remotes). To achieve this, we can use the Switch Has Authority node and pull off execution only when remote. Then we set the global time dilation and the HUD text:

image148

Then you're done! You don't need to call the OnRep function - this is done automatically everytime the variable is set.

Now to test, you will need a friend (oh no, this isn't looking good for you) to check that all the logic works as expected. To achieve this, you will need to make a new hidden mod on mod.io and use the preview link or add your friend as a moderator so that they can subscribe to it.


5. Dummy method

I'm going to run through making a couple of mods which utilise some of the C++ and dummy methods. Once you know how the basics work, you are then set to much more easily be able to experiment, test, and implement any of your own features that use any of the game's functions and BPs for your mods. The possibilities here are endless. Overview of the two example mods I will step-through in this tutorial:

  1. Kill player on button press.
  2. Self-destruct Bosco from a button press.

Both examples will still feature info on how to look at the C++ header dumps.

The very first thing you need to do is download and build the FSD Template project. This has all of the C++ classes automatically reflected in the project source. This saves modders a LOT of time, as there are thousands of classes!

Then you will also need the latest version's dumps from here. You will need to download a text editor or code viewer such as Visual Studio Code to view and navigate the dumps (I use CLion).

Kill player on button press

Scouting the C++ header dumps

Now, you will notice that there are a LOT of C++ classes in the dumps. Don't be overwhelmed – most of the main functions you will need are in FSD.hpp (although saying that, the file alone is 20k lines). If you need C++ from another class you know at the time what you are looking for – and if you don't, you can always search for key words that you are looking for and look through those files. You will be doing a lot of searching through files anyway, so you'll get good at this pretty quickly. Don't hesitate to ask in #mod-chat in the Discord where stuff might be located though.

So, back to this mod example. We need to find the function in the game that deals with killing the player. As you should always do, start by looking in FSD.hpp as it is most likely to be there. Do Ctrl + F to open the search function (this is the same for all IDEs and code editors), and type Kill. You may see about 100 results. You could look through these manually, OR, you could try toggling on "match by word" option that most IDEs and code editors have. In CLion, it is a square button with a "W" on it.

image034

So, here is a function that just kills the player when it is called. An AActor object is passed through but you can just ignore that as we don't need it. The important thing to do here is to check what class this function is inside. This is again relevant for any other functions you will find for your mods. So here, Kill() is inside struct UHealthComponentBase, which is a child class of UActorComponent, as denoted by the :.

image035

When you are looking for functions and variables for your mod, you will come across some really interesting looking functions and variables. I have regularly come up with entire mod ideas just from being distracted when looking through the code. Every single function and variable in all these header files can be dummied… which is a lot of possibilities. Feel free to go wild!

Accessing the C++

Now we know where our Kill function is, we can go about accessing it from our BP mod. Make a new mod (I just made a new one in my tutorial folder and changed the InitSpacerig and InitCave to spawn that instead).

Inside your mod, right click and get a node called Get Component by Class. In the dropdown, you should be able to find the HealthComponentBase class:

image036

Then if you drag off the return value pin and type Kill, you should see a function that pops up called Kill. This is your function that you created inside the HealthComponentBase C++.

image037

Now when we press a key, say, the period, we want to kill the player:

image038

There is a problem with this though! You cannot just call the Kill player function, as you will notice that the component by class node requires a target, which will be the player to kill.

To get the player you want to kill, we need to get the game state player array, loop through that player array then cast the array elements to BP_PlayerCharacter pawns, which you can then use as the targets.

Dummying player character BP

But what is BP_PlayerCharacter? This is a blueprint class that the game has that controls all the logic for the player. We need to dummy this in order for our killing player to work.

In the dumps, navigate to APlayerCharacter : ACharacter. You will see that this is where all the info about the player is stored. ACharacter inherits from APawn, which inherits from AActor. This is important to know because when you dummy blueprints, you can set the parent to be super parent (i.e. the highest in the hierarchy).

Create a folder inside Content called Character. Here we are recreating the exact file path of the asset (you can find BP_PlayerCharacter inside of your unpacked files at this location). Now you need to create a new blueprint class called BP_PlayerCharacter. Inherit it from PlayerCharacter.

Once you create this blueprint, you don't need to do anything with it. Since we aren't dummying this file, we don't want to overwrite anything in the game with it so that is why we don't change any values. All we are doing is accessing the REFERENCE to the blueprint for the mod.

Now, back in your mod, let's get to work on this logic.

First, there is a node from the UE base Gameplay Statistics library called Get Game State. Drag off the return value and type Player Array; we want to get that. Then drag off player array and create For Each Loop with Break node. This will loop through all players in the player array and stop when it receives the break call. If you are in a multiplayer server, all the players in the game will be registered in this player array. So, if you just use a for each without a break, you could kill all the players in the game, if you wanted. This cluster of nodes will be very useful for your mods.

image039

Now drag off the loop's array element and type Pawn Private. Then from the output of that read node, type Cast To BP_PlayerCharacter. Connect the execution node for that cast into the loop body.

image040

Now plug in your Kill function execution node, and your target from As BP Player Character from the cast. Then, if you want to kill just the first player in the player array, hook up the end of the kill function execution to the break for the for each loop with break node. You don't have to do that though, as mentioned above.

image041

Make sure that you enable input on BeginPlay!

image042

Before you package your mod, you have to make sure that you set your directories to never cook to include the Character folder. This is because if we pack our dummied BP_PlayerCharacter, the game will crash. This is explained in section 6, packaging your mod.

Self-destruct Bosco on button press

Scouting the C++ header dumps

First off, we want to find BP_Bosco in the header dumps. It is nicely called BP_Bosco.h. You will see a function called SelfDestruct() inside of it.

image043

If you go into FSD.hpp, and search for ABosco (which is what this class inherits from), you will also see SelfDestruct and a bunch of other functions. Let's say that I also want Bosco to salute before he self-destructs. When writing this tutorial I was just planning on him self-destructing but saw that PlaySalute() function and just knew I had to include it. That'll happen a lot when you are looking through the dumps :)

Before we make the dummy blueprint, we need to figure out what class it needs to inherit from. So, if you look at the struct ABosco line, you will see a :, which as described previously, means "inherits from", then the class it inherits from to the right. So here we see that ABosco inherits from ADeepPathfinderCharacter.

image044

If your IDE has the feature, you should be able to just hover over the name and it will tell you what that class inherits from and click to go to the location of it. If not, don't worry, as you can just search the file for that classname manually.

image045

So you will see now that this class is inherited from AFSDPawn. Now we search for what AFSDPawn is inherited from, and we will see APawn.

image046

APawn is a base UE class so that's as far as we need to go – but now we know, that ABosco is a child class of APawn, even though it is a bit down the inheritance tree.

Creating the dummy BP

Now, we need to recreate a dummy blueprint in the same location where this guy is in the game files, like we do for hex mods. So in your unpacked files, search for BP_Bosco. It should be inside Content\GameElements\Drone.

Inside your project files, navigate to that file location and create a new blueprint class. Since we discovered that ABosco is a child class of Pawn, we can select Pawn class to inherit from. We name the blueprint BP_Bosco. It should look like this:

image047

Inside of this, all we have to do, is create two functions, one called SelfDestruct, and another called PlaySalute. That is literally all you have to do. This now allows us to call these functions without having to touch any C++.

image048

Now, to call on our blueprint, all we have to do is create a node Get Actor of Class and select BP_Bosco in the little dropdown. Then drag off the return value and type Play Salute.

image049

Now, let's put a short delay between saluting and self-destructing, and then call the self-destruct function.

image050


6. Packaging your mod

When you want to test your mod, there are two options for packing:

  1. Automatically using DRGModdingAutomationScripts that Samamstar and DrTurtle made. I really highly recommend using this as it saves a LOT of manual time!
  2. Manually from UE then using DRGPacker.

There's also directories to never cook, which is an extremely important setting, so make sure you scroll down to read that part too.

Using DRG Modding Automation Scripts

First head to this GitHub repository. Then hit the big green Code dropdown and download the code using your preferred method (e.g. download as ZIP). Then extract the DRGModdingAutomationScripts folder and follow the instructions on its README file. Once you are setup, literally all you need to do is double click a .bat and it'll do whatever the bat says it does in the README.

From UE

Go into the Untitled tab. Click File -> Package Project -> Packaging Settings.

image106

Make sure that this Use Pak File option is off.

image107

Now, package your project by clicking File -> Package Project -> Windows (64-bit).

image111

Then selecting a folder to package to:

image112

Tip: if you already have an old cooked folder in there, delete it then click on the parent folder again in the top bar. Because otherwise, since you selected the old folder, it will cook into WindowsNoEditor again, even though you deleted the old one. This sounds confusing so if you just try it yourself you'll understand what I mean.

Assuming you didn't do anything wrong, your project should package after about 30 seconds (differs on how large your project is - when using the FSD-Template, the first time around takes many minutes).

Now, navigate to the packaged files and delete any stuff you don't want to pak (other mods etc.).

image113

Now copy both the Content AND AssetRegistry.bin files, and put them into the input folder inside your DRGPacker.

image114

image115

Then drag the input folder into _Repack.bat. Remember to rename the .pak to your mod name. Then navigate to DeepRockGalactic\FSD\Mods\ and make a new folder with the same name as your mod. Then put the .pak into that folder.

Directories to never cook

You can set directories to never package, which is useful when you don't want to pack say, any of the dummy BP folders. Although you don't have to do this, it does mean that you don't have to delete these files manually within the cooked files, every time. To do this, click the little dropdown arrow in package settings, just above the Project tab:

image109

Then in directories to never cook, press the + button to add directories to the array. This is what mine currently looks like:

image110


Video Tutorial

Tutorials playlist

Important announcement: these video guides are now very out of date, with methods inside still working but newer, less tedious methods now exist. I suggest that you follow this written guide first.

Created by myself, featuring a segment recorded by Samamstar and edited by Hand Drawn Nerd, this guide aims to walk people through the complex process of BP Modding!

These videos are not intended to replace the written guide.

The segments recorded include:

  1. Introduction info and setting up your workspace
  2. The basics of setting up native spawning, native spawning with DRGLib & pre-native spawning with BPMM
  3. The no-dummy BP modding method, using the pre-native BPMM method and then converting the same mod to native using BPMM's interface
  4. The dummy BP modding method, which includes how to navigate the C++ header dumps, as well as reflect them and dummy BPs
  5. Reflection demo, which shows exactly how to reflect some certain C++ objects/delegates/functions/properties that weren't covered in episode 4

Feedback

Hello modder! If you found this guide useful, I invite you to rate it in this form. Feedback is optional, but very welcome.

Comments

Join the community or sign in with your gaming account to join the conversation: