[Shenmue III][GUIDE] A General Guide for Shenmue III Modding

LemonHaze

Banned
Joined
Dec 25, 2018
Some users have reached out to me asking for some details on making mods for Shenmue III. I'll update this as and when I get time.

There are generally a few ways to go about making mods for Shenmue III, so I'll try to give a brief outline on a couple.


As Shenmue III is an Unreal game, it tends to be easier to use that to produce your mods. That's because Unreal changes between versions, sometimes greatly. Shenmue III is built with Unreal Engine 4.20, so downloading and installing that is probably a good idea.

Extraction
Firstly, you should extract all of the game files so you can easily access them. To do that, you can locate UnrealPak.exe within your UE installation and extract each pakchunk located within the Paks directory of your install of Shenmue III.

Because Shenmue III PAKs use the default UE settings at the time, the indexes are encrypted, which simply means you need to find the AES key for Shenmue III. Retrieving this key and also providing it is outside of the scope of this guide, so please seek the key by your own (legal) means.

With the AES key, you can make a JSON file which stores it, which you can then give UnrealPak.exe to then extract the pakchunks correctly.

crypto.json
JSON:
{
  "$types": {
    "UnrealBuildTool.EncryptionAndSigning+CryptoSettings, UnrealBuildTool, Version=4.0.0.0, Culture=neutral, PublicKeyToken=null": "1",
    "UnrealBuildTool.EncryptionAndSigning+EncryptionKey, UnrealBuildTool, Version=4.0.0.0, Culture=neutral, PublicKeyToken=null": "2"
  },
  "$type": "1",
  "EncryptionKey": {
    "$type": "2",
    "Name": null,
    "Guid": null,
    "Key": "AES_KEY_GOES_HERE"
  },
  "SigningKey": null,
  "bEnablePakSigning": false,
  "bEnablePakIndexEncryption": true,
  "bEnablePakIniEncryption": true,
  "bEnablePakUAssetEncryption": false,
  "bEnablePakFullAssetEncryption": false,
  "bDataCryptoRequired": true,
  "SecondaryEncryptionKeys": []
}

Example command to unpack PAK files using the above crypto.json file:

Bash:
.\UnrealPak.exe <PAK> -Extract <OUTPUT DIR> -cryptokeys=crypto.json

For this, I created a batch script which will extract each chunk into their own directory, this can be placed inside the Paks directory, alongside your crypto.json and UnrealPak.exe.

unpack_all_chunks.bat
Bash:
@echo off
setlocal enabledelayedexpansion
SET UEPak="%cd%\UnrealPak.exe"
SET cryptoArg=-cryptokeys=crypto.json
SET pakChunksNum=0

REM -----------------------------------------------------------------------------
ECHO Extracting all found PAKs
FOR /r %%i in ("*.pak") DO (
    SET /A pakChunksNum+=1

    ECHO Extracting %%~nxi
    TITLE Extracting %%~nxi
    %UEPak% %%~nxi -Extract %%~ni %cryptoArg%
)
ECHO Finished extracting %pakChunksNum% PAKs.
REM -----------------------------------------------------------------------------
PAUSE

Once you have extracted the chunks, you probably won't need to do this again and are free to move these files/folders somewhere else.

You can also use UModel itself to select the PAKs, simply select the PAK files and then provide it with the AES key as prompted.

Modifying
When making Unreal Engine projects, you typically use the assets/content as-is and once you are ready to make a build of your project, it goes through a process known as "cooking". In this process, the assets/content are sometimes compressed or otherwise converted into a different type of asset, which contains just the necessary data needed for the game to function or use it. This means that opening a cooked asset in Unreal Engine, requires changes to be made to the engine. You can modify Unreal Engine so that it can open cooked assets.


For most mods, you will want to modify something that already exists and as such you must find that asset. There are numerous ways to go about that, but most often than not, you can simply look at the filenames to find what you wish to change. You can open assets with multiple open/closed-source tools, such as UModel and FModel. Personally, I've used UModel, but you can use whatever you want. With UModel, you can provide the directory of your extracted PAK chunks and have it scan it for any assets. You can view most types of assets wtih these tools.


When it comes to modifying the game itself, the process is pretty straightforward, but again there are multiple ways to go about this.

Simply create a new project in Unreal Engine 4.20 and call it "Shenmue3". Then, recreate the exact directories/hierarchy for the asset you want to modify. For example, if I wish to modify "Shenmue3/Content/Media/Images/UI/test/TX_Icon102_blank.uasset", then I would create each folder starting from Media.

Then, in the same manner, recreate the asset that you want to become your modification, using the exact same name.
image.png



In some cases, it might help to look at the information your asset previewing tools tell you about the asset you want to modify, as that may reveal that a setting is turned on/off/changed from its default and as such, it would be advisable to use the same settings in your asset. Examples of this can be texture groups, in my TX_Icon102_blank example, this is a UI asset and the original version uses the TEXTUREGROUP_UI texture group.

image.png


Once you're happy with the changes and want to test what you've done, simply go to Package your project in Unreal. Once complete, navigate to the directory you chose to place the packaged build files and then extract your PAK files that were generated during the packaging process.


Now you should have a cooked version of your own asset, created with the same version of Unreal Engine that Shenmue III uses. What's next now is to make your own PAK file which uses the exact same internal paths as Shenmue III or verify that it does.. in theory if you named your project "Shenmue3" then your PAK file just needs some files removing. For this, again, you'll use UnrealPak.exe.



Firstly, create a new directory and copy all of your newly-extracted mod files into it. Then, create a new file containing the new directory and the mountpoint:

config.txt
Code:
C:\moddir\* "../../../Shenmue3/Content/"

Finally, to produce your mod PAK file, use the following command with UnrealPak.exe:

Bash:
.\UnrealPak.exe mod.pak -Create=C:\config.txt


Once complete, you should now have a mod.pak file which you can place inside a folder such as ~mods and attempt to boot the game. Again, you don't have to use this method of creating PAK files, it's just my personal preference.


Some assets may consist of data that you want to change which can't really be imported back into Unreal without extra work and for that you can use UAssetGUI. Another useful tool is Asset Editor.

Code
Let's say you can't (or don't want to) just modify an asset. Perhaps you want to control some system while it's running, in real-time.

In order to achieve similar levels of control that you usually posess as an Unreal developer, but with Shenmue 3, I have created ShenmueIIISDK. This allows you to use the (reverse engineered) structures of Shenmue III, in the same way that you usually would if writing your own project code.


C++:
    if (showWarpingWindow)
    {
        ImGui::Begin("Warping Window");
        for (auto controller : UObject::FindObjects<ADebugCameraController>()) {
            if (controller && !IsNameDefault(controller->GetFullName())) {
                ImGui::Text("Freecam Position");
                ImGui::Separator();
                ImGui::Text("X: %f \tY: %f \tZ: %f",    controller->PlayerCameraManager->GetCameraLocation().X,
                                                        controller->PlayerCameraManager->GetCameraLocation().Y,
                                                        controller->PlayerCameraManager->GetCameraLocation().Z);
            }
        }
        if (GetRyo() != nullptr) {
            ImGui::Text("Ryo Position");
            ImGui::Separator();
            ImGui::Text("X: %f \tY: %f \tZ: %f", GetRyo()->K2_GetActorLocation().X,
                GetRyo()->K2_GetActorLocation().Y,
                GetRyo()->K2_GetActorLocation().Z);
        }
        ImGui::InputFloat3("Warp Position", warpPosition);
        if (ImGui::Button("Go")) {
            FVector newLoc;
            newLoc.X = warpPosition[0];
            newLoc.Y = warpPosition[1];
            newLoc.Z = warpPosition[2];
         
            GetRyo()->K2_TeleportTo(newLoc, FRotator());
            //GetRyo()->SetActorLocationAndRotationWithCamera(newLoc, FRotator(), false, true);
        }
        ImGui::End();
    }



Not only does ShenmueIIISDK provide a way to use original structures and functions, but I also wrote a method which allows you to hook existing functions:

C++:
    CreateProcessEventHook("Retro Camera Mod", "Function BP_S3PlayerCameraManagerBase.BP_S3PlayerCameraManagerBase_C.BlueprintUpdateCamera", [](class UObject* _this, class UFunction* a2, void* pParms) {
            if (bHookActive) {
                ABP_S3PlayerCameraManagerBase_C* camBase = reinterpret_cast<ABP_S3PlayerCameraManagerBase_C*>(_this);
                if (camBase && _this) {
                    if (!hasSetOrig) {
                        origDefaultFOV = camBase->LockedFOV;
                        origCurrentArmLength = camBase->CurrentArmLength;
                        origINDOOR_ARM_LENGTH = camBase->INDOOR_ARM_LENGTH;
                        origTargetArmLength = camBase->TargetArmLength;

                        if (camBase->SpringArm)
                            origSpringArmTargetArmLength = camBase->SpringArm->TargetArmLength;

                        origDEFAULT_ARM_LENGTH = camBase->DEFAULT_ARM_LENGTH;
                        origCAMERA_PITCH_OFFSET = camBase->CAMERA_PITCH_OFFSET;
                        origSABUN_PITCH_LIMIT = camBase->SABUN_PITCH_LIMIT;
                        origDEFAULT_ARM_HEIGHT = camBase->DEFAULT_ARM_HEIGHT;
                        origbUserEnableAutoCameraRotation = camBase->bUserEnableAutoCameraRotation;
                        origbEnableAutoRotate = camBase->bEnableAutoRotate;

                        hasSetOrig = true;
                    }

                    if (camBase->CameraState == ECameraState::ECameraState__Zoom ||
                        camBase->CameraState == ECameraState::ECameraState__Search ||
                        playerBehavior == ES3PlayerBehavior::ES3PlayerBehavior__Search) {
                        ProcessEventOriginal(_this, a2, pParms);
                        return;
                    }

In that example, we use the method created to hook the function BlueprintUpdateCamera, which belongs to one of the parent classes of Shenmue III's S3PlayerCameraManagerBase class, UCamera.


Forklift is a useful tool, in that it serves 2 purposes. It bypasses the signature check performed on PAK files which are loaded, which means you can freely modify the pakchunk PAK files directly, without encountering UE's integrity checks which use cryptographic functions. This also of course implies that you can load regular (unencrypted) PAK files aswell. Forklift will also load any DLLs with the file extension ".asi" in the same directory as Shenmue3-Win64-Shipping.exe, which is useful if your mod contains asset changes and you also want to execute your own code.



As we do not have the signing key for PAK files that are used by Shenmue III, we can use Forklift to bypass the signature checks, allowing arbitrary PAK files to be loaded & directly modified, without signatures and without any cryptography. You don't have to do this depending on how you generate your PAKs, it all depends on what you want to achieve and also prefer to use.
 
Last edited:
I'm unsure on the rules about sharing the AES key, but if anyone has any suggestions regarding that, I'll make whatever changes necessary.
 
do you think there is any way to add "scenes" or extend scenes. for example, i like to use free cam and record scenery scenes which i think 3 lacked. then id love to add these cutscenes in before entering parts of the game.
thanks
 
do you think there is any way to add "scenes" or extend scenes. for example, i like to use free cam and record scenery scenes which i think 3 lacked. then id love to add these cutscenes in before entering parts of the game.
thanks

Sure!

When making mods (or anything in general really), the simpler we can make it, the better. So really, you could probably do that by hooking the LevelLoad events that Shenmue III has, then you can have conditions in there which you can use to set different scenes depending on the level that's being loaded.

Then, you'd simply build your scene/camera sequence stuff inside Unreal as normal, cook it and put it into a mod PAK. :)

Another way you could do it using UAssetGUI, is by looking at how the Shenmue III blueprints call out to camera sequence data and plays them, then you can copy the opcodes probably and then change the asset name for your own camera sequence data. You'd obviously put these opcodes wherever necessary.
 
ok cool. ive seen in shenmue 3 installation folder Shenmue3\Content\Movie there are 4 movies that are USM files. so i was thinking these must be triggered somehow and if i record extra scenes hopefully i can do the same at any point in the game.
 
ok cool. ive seen in shenmue 3 installation folder Shenmue3\Content\Movie there are 4 movies that are USM files. so i was thinking these must be triggered somehow and if i record extra scenes hopefully i can do the same at any point in the game.
Oh, I didn't realise you meant pre-rendered movies.

The same process applies, make the movies then just trigger them to load the same way that the game does, when you want to.
 
Back
Top