Skip to content
This repository was archived by the owner on Jan 2, 2023. It is now read-only.

Generating UHT compatible headers

UE4SS edited this page Aug 15, 2022 · 16 revisions

Generating UHT compatible headers

Supported versions

While the UHT header generator is only officially supported in 4.25+, it has worked for older game versions (tested on 4.18.3; 4.17 (has some default property issues that should be fixed soon)).

How to use

The key bind to generate headers is by default CTRL + Numpad 9, and it can be changed in Mods/UHTCompatibleHeaderGeneratorMod/Scripts/main.lua

To utilize the generated headers to their full potential, see UE4GameProjectGenerator by Archengius. The project generator only works in >4.25. If generating a project for an older engine version, generate it by compiling the project generator for 4.25+. Before compiling the projectgencommandlet, open GameProjectGenerator.uproject and your game's pluginmanifest or .uproject and add any default engine plugins used by the game or plugins that the game uses and you found open source or purchased (it is not recommended to include purchased plugins in a public uproject) to the commandlet's uproject file.

After compiling the commandlet and running it on your game files, simply change the engine version in the generated .uproject to the correct engine version for your game.

image

This commandlet will enter the CLI commands for the project gen for you, and make a batch file to regenerate with the same settings (e.g., to regenerate after a major game update). https://github.com/bananaturtlesandwich/UE4-Mod-Tools/releases/tag/UE4ProjectGen-GUI

Recommended settings:

It is recommended to use the override settings in UE4SS to make your project more powerful. If you want the property/class to be accurate to the dev's version instead, it is recommended to at least use the MakeEnumClassesBlueprintType override, though some enums may need to be changed afterwards.

image

Possible inaccurate generation issues:

UE4SS has two different types of generators, a UHT compatible generator and what's called a CXX generator.
The UHT compatible generator is what's used when creating a .uproject file with the UE4GameProjectGenerator, and the CXX generator is a very shoddily made generator that doesn't generate UHT macros or proper #include statements but it does generate headers for core UE classes which the UHT generator doesn't.

Note the UE4SS CXX dumps do not currently have accurate padding. An SDK dump generated from another source may be a better source for determining the below corrections if it generates with correct padding, particularly for the bitfield checks.

Certain default properties may not generate correctly in older engine versions. For example, SoftObjectProperty was called AssetObjectProperty and SoftClassProperty was AssetClassProperty in <4.17. It is recommended to also generate an SDK/CXX dump to check for those properties and correct them in your project. The default generation for these properties should be fixed in a UE4SS update soon.

Bitfields will always generate as uint8. However, they may actually be declared as uint32 in the original source. You can try to determine the actual size based on the CXX/SDK dump to correct these. In a CXX dump the bitfields will show the same offset. If there are multiple bitfields at the same offset and the next property is 4 bytes after that offset, then the bitfield should be changed to uint32.

The UHT generator currently has a bug when generating "Instanced" property flags, and will generate many as "Export" instead. Export is implied with the Instanced flag, and Export alone is rarely used. Most Export flags can safely be replaced with "Instanced". An SDK dump may also give you info on the correct flag here.

Instructions for possible errors you may encounter

These are some general instructions of how to generate a project and it also covers a few errors that you are likely to encounter.
The following errors & solutions is what was found when generating projects for various games.
Note that you can check here for solutions even if your game isn't listed below. Error lists compiled by Buckminsterfullerene, CheatingMuppet and Narknon.

Tick Functions fix

When you've got a tick function like this:
USTRUCT(BlueprintType)
struct FNameofGameStructTickFunction : public FNameofGameStructParentTickFunction {
    GENERATED_BODY()
public:
    GAMENAME_API FNameofGameStructTickFunction();
};

Add code like this to the bottom:
template<>
struct TStructOpsTypeTraits<FNameofGameStructTickFunction> : public TStructOpsTypeTraitsBase2<FNameofGameStructTickFunction>
{
    enum
    {
        WithCopy = false
    };
};

Inherited Virtuals

UE4SS is unable to generate inherited virtuals if they are unreflected. This is often the source of LNK2001: unresolved external symbol errors, particularly when a class inherits from an interface. The build log is often not helpful for determining which file needs these virtuals. To determine the file that they need to be added to, search for the virtual function listed in the error or for the class of the function in the engine, e.g., Module.AkAudio.cpp.obj : error LNK2001: unresolved external symbol "public: virtual class FString const __cdecl UInterpTrack::GetEdHelperClassName(void)const you could search for GetEdHelperClassName or UInterpTrack. Find the parent function and then find any classes within your project that inherit from same. Ideally find a sample of another class that inherits those virtuals within the engine on which to base your fixes, and copy the implementations from same into your affected project files, being sure to change the class name to match the class in your project. You typically will also want to delete the logic in the implementations to simply return the correct type of data or "null" without actually running any logic.

Game Target Generation

The project gen commandlet does not generate a game target file. Copy and duplicate your GameNameEditor.target.cs file in the same location. Remove Editor from the name. Open the file and delete "Editor" in the red crossed locations, and replace "Editor" with "Game" in the highlighted location.

image

Deep Rock Galactic

========================== First do: ==========================
Convert GameProjectGenerator to 4.27
Generate project using commandlet
Then open it in Rider/VS.

========================== Then do, in no particular order: ==========================
Find out what version of mod.io game currently uses. At time of writing it is https://github.com/modio/modio-ue4/releases/tag/v2.16.1792. Paste the 'Modio', 'ModioTests' and 'ThirdParty' folders from this into Plugins/Modio/Source, replacing the existing 'Modio' folder. Do not replace the .uplugin file.

Comment out/delete #include "ModioModID.h" in ModioSubmissionExtensionLibrary.h in that ModioEx game module. Then add '#include "Types/ModioCommonTypes.h"'.

Add 'config = Engine' to the 'UCLASS' macro in any error that says "UCLASS(defaultconfig) not defined"

"GetHashType" errors:
In Struct file FChunkID, add this line to the bottom of the file, outside of the struct: 
FORCEINLINE uint32 GetTypeHash(const FChunkId) { return 0; }

In Struct file FMusicHandle, add this line to the bottom of the file, outside of the struct: 
FORCEINLINE uint32 GetTypeHash(const FMusicHandle) { return 0; }

"Override of UFUNCTION in parent class ... cannot havae a UFUNCTION() declaration above it" errors:
Comment out or remove the function both in the .h file and the .cpp file (if it has a declaration)

Errors that look like this: "ActorFunctionLibrary.gen.cpp(153): [C2664] 'void UActorFunctionLibrary::DissolveMaterials(UObject *,const UMeshComponent *&,float)': cannot convert argument 2 from 'UMeshComponent *' to 'const UMeshComponent *&'":
Remove the const before the arguments that have the error (remember to also remove them in the definition stub too)

Packing for first time, "game target not found" errors:
Copy the EditorTarget file, rename it to FSDGame.Target, and inside of it change target type to Game

In "ShowroomStage.cpp" inside of the implementation of the constructor, comment out "this->SceneCapture = CreateDefaultSubobject<USceneCaptureComponent2D>(TEXT("SceneCapture"));" 

========================== No longer shows but may still be relevant to know: ==========================
Add "OnlineSubsystem" and "GameplayTasks" to "FSD\FSD.Build.cs" in the "PublicDependencyModuleNames" list - if already there, ignore

Packing for first time, linker errors:
Ctrl + T look for IMPLEMENT_MODULE (located in FSDModule.cpp). Replace this line with IMPLEMENT_PRIMARY_GAME_MODULE(FDefaultGameModuleImpl, FSD, "FSD");

cyubeVR

Convert GameProjectGenerator to 4.27

Right click generated project and open with IDE (e.g. Rider)

Rename the following files in UWorksWeb to add a "2" at the end (or anything. Make sure refactor function is used to rename all instances of those files):
    - FindOrCreateLeaderboardDelegateDelegate.h
    - FindOrCreateLeaderboardMinimalDelegateDelegate.h
    - GetNumberOfCurrentPlayersDelegateDelegate.h
    - GetNumberOfCurrentPlayersMinimalDelegateDelegate.h

Replace UCLASS(DefaultConfig) with UCLASS(config = Engine, DefaultConfig) in:
    - GoogleAnalyticsSettings.h
    - LivPluginSettings.h
    - DLSSSetings.h
    - VRGlobalSettings.h (don't remove BlueprintType flag)

Replace UCLASS( ProjectUserConfig) with UCLASS(config = Engine, ProjectUserConfig) in:
    - DLSSOverrideSettings.h

Remove BlueprintReadWrite flag from:
    - LiveCaptureContext.h
        - TArray<TWeakObjectPtr<UPrimitiveComponent>> HiddenComponents;
        - TArray<TWeakObjectPtr<AActor>> HiddenActors;
    - UInt32.h - uint32 Value;
    - UInt64.h - uint64 Value;
    - DLSSSettings.h - uint32 NVIDIANGXApplicationId;
    - MeshComponentInfo.h - all properties
    - TexSource.h - all properties

Remove BlueprintCallable flag from:
    - LightReceiveInterface.h - all functions

Comment out UFUNCTION(BlueprintCallable) from following functions in ReceiveLightActor.h:
    - UseActorCustomLocation
    - GetActorCustomLocation

Set the "_MAX UMETA(Hidden)," to "_MAX = 0xFF UMETA(Hidden)," in:
    - EUGCMatchingUGCTypeBP.h
    - EItemPreviewTypeBP.h

In IpNetDriverUWorks.h and cpp files.
Add as a parameter to the constructor: "const FObjectInitializer& ObjectInitializer"
Add before the "{" in the cpp file: ": UIpNetDriver(ObjectInitializer)"

Remove TEnumAsByte<> (but not the type inside of it) in:
    - OnInput inside VRGripInterface.h
    - OnEndPlay inside VRGripScriptBase.h and its _Implementation version in the .cpp file
    - SetMobilityAllEvent inside DeerCPP.h and its _Implementation version in the .cpp file

Add this code underneath the struct in GripComponentEndPhysicsTickFunction.h:
template<>
struct TStructOpsTypeTraits<FGripComponentEndPhysicsTickFunction> : public TStructOpsTypeTraitsBase2<FGripComponentEndPhysicsTickFunction>
{
    enum
    {
        WithCopy = false
    };
};

Add the following 4 lines in the "Plugins" section in the generated "cyubeVR.uproject":
{
    "Name": "ChaosEditor",
    "Enabled": false
}

Packing for first time, you will get "game target not found" errors. Close Rider and UE. Then, copy and paste the cyubeVREditor.Target.cs file (inside Source folder) and name it cyubeVRGame.Target.cs. Then replace any mentions of "editor" and replace with "game" inside of this new file (or just put this code into the file):
using UnrealBuildTool;

public class cyubeVRGameTarget : TargetRules {
	public cyubeVRGameTarget(TargetInfo Target) : base(Target) {
		Type = TargetType.Game;
		DefaultBuildSettings = BuildSettingsVersion.V2;
		ExtraModuleNames.AddRange(new string[] {
			"cyubeVR",
		});
	}
}

If you get the "failed to create version memory for PCH" errors when trying to build or pack, do it again.

Clone this wiki locally