Overwriting and Modifying Existing Content
It is possible to overwrite or modify content from the base game or from other mods. This is not recommended as opposed to creating your own content that extends it, because mods that overwrite the same thing will likely be incompatible with each other. However, it is the most practical way to achieve certain functionality.
Some other modders have already created mods that assist with the process of overwriting or modifying content. They can save you a lot of time.
TweakIt by Feyko allows you to write Lua scripts to programmatically modify game content.
Documentation can be found via the 'docs switcher' on this site’s sidebar, or here
ContentLib by Nog and Robb allows creating and modifying content via writing JSON files. It also offers a Blueprint and C++ API to programmatically generate, modify, or parse content at runtime. Additionally, it offers a limited form of CDO modification (described below) via JSON files.
Documentation, including a step-by-step walkthrough of some common tasks, can be found here.
The mod has been officially released, and its documentation describes how to configure your mod to depend on it.
If you still want to overwrite content without using a library, the correct mechanism for doing so is Class Default Object (CDO) manipulation.
To perform a CDO modification, get the class default object of the class you’re trying to override and change the relevant properties.
Changes to CDO’s are reflected on all of the objects of the selected class that are created after the modification. Be mindful when using this, because you can break other mod and vanilla content without leaving a trace. For safety reasons, the function will log a warning when you’re attempting to modify a class not owned by your mod.
Keep in mind that when performing a CDO, you’re not actually changing anything on existing objects, you’re just overwriting property values on "archetype" objects. You may still need to get all existing instances of the class and modify their values too to ensure they match your new desired value. Performing your CDO modifications earlier in the mod loading process can sometimes remove the need for this extra step.
When performing CDO manipulation, you need to keep the CDO in-memory to ensure that Unreal does not garbage collect your patched object (and its descendants) and later load it unmodified from disk, undoing your change.
To do this, you need to reference the CDO in a property. More on this in the language-specific sections below.
It is important to understand that Class Default Object modification is not capable of accomplishing everything.
CDO modification can only influence behavior and properties that already exist an object - it can’t define new behaviors.
Also, the way some features are implemented behind the scenes could mean that modifying the class default object could have no effects whatsoever, as the values you changed could be overwritten by something else.
In Blueprint, you can use the
Get Class Default Object node to get the class default object.
Afterwards, you can use the class' existing setters to modify fields.
You might need to use an Access Transformer to make the field that you intend to change accessible from blueprints.
To keep a reference to the CDO, create a property of type Object in the blueprint where you also change the CDO. Set the property’s value to be the CDO before manipulating the object.
If you are modifying multiple CDOs, you can make the property an array of objects instead, and add each CDO to the array.
Here’s an example from Kyrium’s KBFL for adding additional allowed classes to the Pressurizer and its extractor nodes.
if(const TSubclassOf<AFGBuildableFrackingActivator> BPBuildableFrackingActivator = LoadClass<AFGBuildableFrackingActivator>(NULL, TEXT("/Game/FactoryGame/Buildable/Factory/FrackingSmasher/Build_FrackingSmasher.Build_FrackingSmasher_C")))
AFGBuildableFrackingActivator* FrackingActivatorDefault = BPBuildableFrackingActivator.GetDefaultObject();
frackingActivatorCDO = FrackingActivatorDefault
if(const TSubclassOf<AFGBuildableFrackingExtractor> BPBuildableFrackingExtractor = LoadClass<AFGBuildableFrackingExtractor>(NULL, TEXT("/Game/FactoryGame/Buildable/Factory/FrackingExtractor/Build_FrackingExtractor.Build_FrackingExtractor_C")))
AFGBuildableFrackingExtractor* FrackingExtractorDefault = BPBuildableFrackingExtractor.GetDefaultObject();
frackingExtractorCDO = FrackingExtractorDefault
In this example, the CDO-referencing properties are
To properly reference CDOs, create a property of type
UObject* in the class where you also change the CDO. Make sure to mark the property as
UPROPERTY or UE will not know about the property.
If you are modifying multiple CDOs, you can make the property a
TArray<UObject*> instead, and add each CDO to the array.
If you need to add new behavior to existing content, it may be easier to extend it by making a subclass of it, then define the new behaviors in your subclass.
This works well in tandem with the Placeholder System - even though we don’t have the implementation details of the real version, by extending its placeholder, we will still be able to use those features at runtime.
If a CDO modification isn’t working and extending the existing content is not an option, hooking existing functions on the content may allow for the modifications you want.
Hooking is a very complicated topic covered in more detail on its own page.