-
Notifications
You must be signed in to change notification settings - Fork 0
Basic Modding Tutorial
Here is a basic modding tutorial for folks who want to get started modding characters in Tales of Berseria. While I have written the toolset to accomodate complex modding, understanding what is going on under the hood is not necessary for most simple mods. Here we will do a basic mesh delete, mesh modification (partial delete in this case) and texture replacement. This tutorial does not have any major spoilers.
Click here for details on how to adapt this tutorial to Tales of Zestiria.
Note that this is not a tutorial on how to use tools like Blender or Paint.NET. I will not be teaching basic universal skills - please refer to other tutorials such as those on YouTube etc. I particularly recommend watching "3DMigoto Costume Mod Tutorial for Fairy Tail (PC)" by Ikaros; while it was made for 3DMigoto, I learned 90% of what I know from that video alone. I will put some basic steps so that you can still follow along, even if you have no Blender skills, but this tutorial will be much easier with some basic skills.
- Install Python 3, if you don't have it already. (www.python.org/downloads, I'm using python 3.11 but any version newer should work.)
- Install Blender (free!) in Steam. Optional: change to 4.2 LTS (right click Blender in steam, select Properties -> Betas -> 4.2 stable LTS).
- Download DarkStarSword's plugin here (Right Click, Save As)
- Install the plugin (Blender -> Edit menu at top -> Preferences -> Add-ons -> Install, click the link for video.)
- Download the Berseria Model Tool.
- Download tltool.exe from TalesOfTools by DaZombieKiller.
- Download the Berseria filename list for TalesOfTools here. Thank you to Meebo (Tales of ABCDE Discord) and DaZombieKiller for providing this file!
First, let's get ourselves a model! I want to mod Velvet's default costume today.
First, we need to unpack the game assets. The base assets are in {Steam}\Tales of Berseria\GAMEDATA\BASE\CHUNK0\GENERAL\COMMON\
(which I will call the "base {COMMON}
folder" for short). Put tltool.exe
in this folder along with bers_names.txt
(see above for links).
Go into the command line in the base {COMMON}
folder by typing cmd
into the address bar of the windows explorer menu. Unpack the assets with the following command:
tltool.exe unpack --dictionary bers_names.txt --encrypted FILEHEADER.TOFHDA FILEHEADER.TOFHDB TLFILE.TLDAT common
This command unpacks all the files and then applies the names in the bers_names.txt
dictionary. Some files will still have hashed names; this is normal.
The model files are in two parts: a .TOMDLB_D
file and a .TOMDLP_P
file (inside the TOMDLB_D
folder and TOMDLP_P
folder, respectively). The texture files are also in two parts: a .TOTEXB_D
file and a .TOTEXP_P
file. Additionally, character models (and presumably any other model using skeletal animation) have an external skeleton, which is another .TOMDLB_D
/.TOMDLP_P
file. We need both parts of the model for mesh editing, but we only need the .TOMDLB_D
part for the external skeleton and the .TOMDLP_P
file is actually completely empty.
Finding the main model is fairly easy via file names, Velvet is CHR_VEL_HUM_CHEST_MI.TOMDLB_D
(and CHR_VEL_HUM_CHEST_MI.TOMDLP_P
). Finding the skeleton is not as easy because they are not internally linked. Here are the skeletons for the six playable characters:
Character | Body Model | External Skeleton |
---|---|---|
Velvet | CHR_VEL_HUM_000_CHEST_MI | CHR_BONE_LAI_ALL_000_MI |
Eizen | CHR_EIZ_TEN_000_CHEST_MI | CHR_BONE_DEZ_ALL_000_MI |
Eleanor | CHR_ELN_GUR_000_CHEST_MI | CHR_BONE_ALI_ALL_000_MI |
Laphicet | CHR_LFI_HUM_000_CHEST_MI | CHR_BONE_KAN_ALL_000_MI |
Magilou | CHR_MGL_HUM_000_CHEST_MI | CHR_BONE_ROS_ALL_000_MI |
Rokurou | CHR_ROK_HUM_000_CHEST_MI | CHR_BONE_DEZ_ALL_000_MI |
If the character you are modding is not in the table, you will have to find the skeleton file (or any compatible file). There are two ways to find a skeleton. First, the most accurate way is to use the Berseria Name Dumper from TalesOfTools. Put winmm.dll
in the game's base folder (same folder with Tales of Berseria.exe
) and load the game, then make the character appear on screen. Quit the game, and look in the file log name_db.txt
it created to find the model. Often the skeleton is loaded at around the same time, assuming it has not been loaded previously (because the dll only adds new names that are not already on the list).
The second way is to copy all the .TOMDLB_D
files starting with CHR_BONE
into the folder with your model and use the exporter, and it will use any file that is compatible. The skeleton will probably be the wrong size, but the model will export.
So, to sum up, we will be modding CHR_VEL_HUM_000_CHEST_MI
(Velvet's costume / body), so we need {COMMON}/common/TOMDLB_D/CHR_VEL_HUM_000_CHEST_MI.TOMDLB_D
, {COMMON}/common/TOMDLP_P/CHR_VEL_HUM_000_CHEST_MI.TOMDLP_P
, and {COMMON}/common/TOMDLB_D/CHR_BONE_LAI_ALL_000_MI.TOMDLB_D
. (Don't worry about textures for now, we will find them in a minute.)
Make a folder somewhere, which I will refer to as the work folder, and copy these files into that folder along with the files from the Berseria Model Toolset. Your folder should look like this:
Double click berseria_export_model.py
and it will unpack your model. When it is done, you will have a new folder, CHR_VEL_HUM_000_CHEST_MI
with the unpacked model inside.
NOTE: Instead I actually recommend running berseria_export_model.py
from the command line. Again, type cmd
into the address bar of the windows explorer menu, then type:
python berseria_export_model.py CHR_VEL_HUM_000_CHEST_MI.TOMDLB_D
Python will not report any errors if the script crashes when you double-click the script, and no one will be able to help you. Run from the command line for helpful error messages.
Inside the {Work Folder}/CHR_VEL_HUM_000_CHEST_MI/
folder, you will see 1. all the meshes (.fmt/.ib/.vb/.vgmap files), 2. the materials (material_info.json
), 3. the mesh structure including bone palettes and material assignements (mesh_info.json
), and 5. a list of all the linked files (including textures) used by this .TOMDLB_D
(linked_files.json
).
Textures are not kept in the .TOMDLB_D
file. Open linked_files.json
with Notepad or equivalent to see what the texture filenames are. Note that while the linked files list point to .TOTEXB_D
files, those are also linking dependency files, and the actual textures are in .TOTEXP_P
files with identical names. You can use totexp_to_dds.py
, included in the model toolset, to convert them to .dds
textures - discussed further below.
Before doing any mods, I am actually going to go through repacking the model. This is a good exercise to make sure you know how to get working a model file from your unpacked model. In addition, all subsequent mods below will refer back to this step.
If you followed the above steps, you will have your original model files file, berseria_export_model.py
, berseria_import_model.py
, lib_fmtibvb.py
, the pyffi_tstrip
folder and the CHR_VEL_HUM_000_CHEST_MI
folder which contains your model files.
Note: The model importer expects working .TOMDLB_D
/ TOMDLP_P
files to already be in the folder. It will use the working .TOMDLB_D
file as a template, and copy over portions of the .TOMDLB_D
file that are not in the meshes / metadata folder.
Repack CHR_VEL_HUM_000_CHEST_MI.TOMDLB_D
by double-clicking berseria_import_model.py
.
NOTE: Again I actually recommend running python berseria_import_model.py
from the command line.
If the repack was successful, there should now be shiny new CHR_VEL_HUM_000_CHEST_MI.TOMDLB_D
/ CHR_VEL_HUM_000_CHEST_MI.TOMDLP_P
files in your folder! (The originals will be backed up as CHR_VEL_HUM_000_CHEST_MI.TOMDLB_D.bak
/ CHR_VEL_HUM_000_CHEST_MI.TOMDLP_P.bak
.)
Tales of Berseria allow for making patch archive files to overwrite the original archives, so we will take advantage of that to create mod files. Make a folder called PATCH
inside the {Tales of Berseria}/GAMEDATA/
folder with the full structure inside; it should look like this: (replace YOURMODNAMEHERE
with whatever folder name you like)
+---Tales of Berseria
+---GAMEDATA
+---PATCH
+---YOURMODNAMEHERE <--- You can make multiple folders in PATCH for various mods
+---GENERAL
+---COMMON <--- Put tltool.exe in this folder
+---modfiles
+---TOMDLB_D
| .TOMDLB_D files go in this folder
|
+---TOMDLP_P
| .TOMDLP_P files go in this folder
|
+---TOTEXB_D
| .TOTEXB_D files go in this folder
|
+---TOTEXP_P
.TOTEXP_P files go in this folder
Put your new CHR_VEL_HUM_000_CHEST_MI.TOMDLB_D
and CHR_VEL_HUM_000_CHEST_MI.TOMDLP_P
in folders called TOMDLB_D
and TOMDLP_P
, inside a folder called modfiles
, inside the {Steam}\Tales of Berseria\GAMEDATA\PATCH\YOURMODNAMEHERE\GENERAL\COMMON\
folder (which I will call the "patch {COMMON}
folder" for short). Put tltool.exe
in the patch {COMMON}
folder next to modfiles.
Go into the command line in the patch {COMMON}
folder by typing cmd
into the address bar of the windows explorer menu. Pack your modded assets with the following command:
tltool.exe pack modfiles .
There should be a new FILEHEADER.TOFHDB
and TLFILE.TLDAT
containing your mod files. Load the game to see the result!
(Note, when distributing any mods, delete the modfiles
folder and include only FILEHEADER.TOFHDB
and TLFILE.TLDAT
to save space. Those files can be easily unpacked with tltool.exe
.)
First, we will do a very simple mod - removing an entire submesh. Blender is not involved, but we will use it to preview what will happen.
Load Velvet's meshes into Blender. (File menu -> Import -> 3DMigoto raw buffers (.vb + .ib)) The meshes are in {Work Folder}/CHR_VEL_HUM_000_CHEST_MI/
. To maintain Blender's forward axis, set Forward Axis to Z-forward and Up Axis to Y-Up.
Note: The game engine and Blender interpret the X-axis in opposite directions, so what is on the left in Blender will be on the right in the game and vice-versa.
13_GANTLET0_VEL_HUM_000_MISHAPE.vb
and 14_GANTLET0_VEL_HUM_000_MISHAPE.vb
are her gauntlet, we will delete those. For this mod we do not need Blender at all, except to identify the mesh.
Go into {Work Folder}/CHR_VEL_HUM_000_CHEST_MI/
and delete 13_GANTLET0_VEL_HUM_000_MISHAPE.vb
and 14_GANTLET0_VEL_HUM_000_MISHAPE.vb
. (I recommend backing up your files first.)
Compile and test your model. Congratulations on your first mod!
This time I want to shorten Velvet's cape. This will not be as easy as removing the gauntlet, since the cape is part of her upper outfit and deleting the entire mesh will disconnect her arms from her torso.
The cape is part of 23_CHEST0_VEL_HUM_000_MISHAPE.vb
. Select 23_CHEST0_VEL_HUM_000_MISHAPE.vb
, go into Edit Mode, select the parts of the belt you want to delete in Blender, and delete. (Again, this is not a Blender tutorial, although the basic steps are below. Please watch the video linked above or reference any Blender tutorial you like.)
Step by step: (Video tutorial here)
A. In the Topbar, go into the Layout workspace (tabs at top -> Layout), if you are not already there. Make sure you are in the 3D Viewport (Shift-F5). In the upper left you can see the current mode, which is likely Object Mode. If you are not in Object Mode, switch into Object Mode (from the drop down, or Ctrl-Tab)
B. In the Outliner, aka the box in the upper right with all the meshes and other objects, hide all the meshes except Velvet's cape (
23_CHEST0_VEL_HUM_000_MISHAPE.vb
). Select each one and press H (or click the eye icon on the right). Select 23_CHEST0_VEL_HUM_000_MISHAPE.vb. Velvet's cape should now be selected. Change Object Mode to Edit Mode with the upper left dropdown in the viewport.
C. Three icons will appear directly to the right of Edit Mode, which are Vertex Select, Edge Select and Face Select modes. Switch to Face Select mode.
D. Unselect everything (Select menu -> None, or Alt-A.)
E. With your cursor in the viewport (middle of the screen), hold down mouse wheel click (MWC) and move your mouse to pan and tilt the camera around the model. Hold down Shift-MWC and move your mouse to move shift the camera position (i.e. to strafe across the screen). Use Mouse wheel scroll (MWS) to zoom in and out.
F. Switch to Circle select (Select menu -> Circle Select, or press C). MWS to adjust the size of your "brush" for selecting polygons. Hold down the left mouse button (LMB) to select polygons. Hold down MWC to unselect polygons. Click the right mouse button (RMB) to leave circle select mode. You will need to do this to pan the camera.
G. Repeatedly do this until you have selected the polygons you plan to delete. Press C, MWS to adjust size, LMB to select some polygons, MWC to unselect ones you accidentally set, RMB to go back to camera mode, MWC/Shift-MWC to adjust the camera, press C again to select or unselect some more...
H. When you are done, delete those faces. (Mesh menu -> Delete -> Faces, or RMC in the viewport {when not in circle select} and select "Delete Faces") Want to do something else besides just delete? Try transforming! (Mesh menu -> Transform -> Move / Rotate / Scale, or one of the specialized tools like Push / Pull or Shrink / Fatten.) Just remember to consider how your changes will affect pose / animation.
Go back into Object Mode.
Export the mesh. File menu -> Export -> 3DMigoto raw buffers (.vb + .ib) Overwrite the original 23_CHEST0_VEL_HUM_000_MISHAPE.vb
. (Again, I recommend backing up your files first.)
Note: If you are using the newer versions of the 3DMigoto plugin, it will output a .vb0
file instead of a .vb
file. DO NOT RENAME THIS FILE. The import script knows to look for .vb0
instead of .vb
, and will refuse to load the file if it has been renamed back to a .vb
file!
You will notice that there is a decoration on the lower cape that is part of her leather detail and metal detail meshes, 07_CHEST0_VEL_HUM_000_MISHAPE.vb
and 12_CHEST0_VEL_HUM_000_MISHAPE.vb
, respectively. Repeat the above steps for 07_CHEST0_VEL_HUM_000_MISHAPE.vb
and 12_CHEST0_VEL_HUM_000_MISHAPE.vb
, removing only the decoration on the bottom of the cape.
Compile and test your model. Congratulations on your second mod!
This time I will change the color of Velvet's outfit (24_CHEST0_VEL_HUM_000_MISHAPE.vb
and 25_RED0_VEL_HUM_000_MISHAPE.v
b).
Open mesh_info.json
in a text editor such as Notepad. We can see that the same material is assigned to both meshes, and it is called ALPHA3_VEL_HUM_000_MAT
. NOTE: You can change which material each mesh is assigned to here.
Open material_info.json
in the work folder. Find ALPHA3_VEL_HUM_000_MAT
. We can see the diffuse (basic coloring) texture is CHR_VEL_HUM_000_ALPHA0_C
. (the first texture listed is the color texture.)
Grab CHR_VEL_HUM_000_ALPHA0_C.totexp_p
from the unpacked files and put it in a folder with totexp_to_dds.py
(from the model toolset). Double-click totexp_to_dds.py
to convert CHR_VEL_HUM_000_ALPHA0_C.totexp_p
to CHR_VEL_HUM_000_ALPHA0_C.dds
.
Open CHR_VEL_HUM_000_ALPHA0_C.dds
and make your changes. (Again, this is not a Paint.NET tutorial, but the basic steps are below.)
Step by step:
A. Open CHR_VEL_HUM_000_ALPHA0_C.dds in Paint.NET.
B. The texture is on a single layer, duplicate that layer (Ctrl-Shift-D). You will now have two identical images on top of each other. Select the upper layer, by clicking on it in the Layers window. If you do not see the Layers window, press F7. If you still cannot see it, press Ctrl-Shift-F7 to reset it to its default position in the lower right. (Video tutorial on using layers here.)
C. Select the red parts of the image. Press S to go into select mode, and to cycle between the four select modes (Rectangle select, lasso select, ellipse select and magic wand. Select part of the area that you want to start. Hold down the Ctrl key while selecting to add to your current selection, and the Alt key to subtract from your current selection.
D. Edit -> Invert selection (Ctrl-I), so that it is now selecting all the parts you do not want to change. Edit -> Erase selection (Press Del), so that all those parts are gone. Your image will not change, because those parts are still present on the lower layer! (You can see this in the layers window.)
E. Optional: I have more success doing recolor if I remove the existing color first. Adjustments menu -> Black and White (Ctrl-Shift-G). Even more optional but recommended: Duplicate this black and white layer a few times. You can try making a bunch of different colors, and then just drag the layers up and down and you will have variations to enjoy with minimal effort!
F. Switch to the Recolor Tool (Press R). Increase the brush size to something large, like 500. Increase the Tolerance to 100% (since we have already removed the areas we do not want recolored). In the Colors tool, select a new color. Drag-Click on the texture, and color the texture. (Note: Where you start will determine the color shift. So if your cursor is over a light area when you start, the entire recolor will be darker, and vice versa.) (Video tutorial on Recolor - This is worth a watch, it shows how to properly recolor and makes some of my steps above moot. But I like my method.)
Optional: Save as a pdn file before saving as a dds file. When you save as a dds file, it will need to flatten all your layers back into a single layer. If you have a pdn file, all the layers will be preserved, allowing you to keep making changes and variant textures.
Save the file in .dds format. Be sure to save in BC3 (Linear, DXT5) format if there is transparency, or BC1 (Linear, DXT1) if there is no transparency. If you are not sure, you can always default to BC3 but the file size will be double that of BC1. The game also seems to expect mipmaps, so turn that on as well.
Put dds_to_berseria_totexp_p.py
in the folder and run the script. It will make a new CHR_VEL_HUM_000_ALPHA0_C.TOTEXB_D
and CHR_VEL_HUM_000_ALPHA0_C.TOTEXP_P
.
Put your new .TOTEXB_D
and .TOTEXP_P
files into the TOTEXB_D
and TOTEXP_P
folders of your modfiles
folder, and rebuild your mod TLFILE.
Congratulations on your third mod, you have made it to the end of the basic tutorial!
Optional: Instead of overwriting the original, you can save as a new file, with a new filename. Then update the name in material_info.json
, and repack CHR_VEL_HUM_000_CHEST_MI.TOMDLB_P
. It will look for the new texture file instead. You will want to use tltool.exe
to check for filename hash collision (two different files with the same hash). If you want one mesh to use the new texture while leaving the other meshes in the same model alone, you can copy the entire ALPHA3_VEL_HUM_000_MAT
material, add it to the bottom of the file and give it a new name / internal ID.
The modding toolset does work with Tales of Zestiria, but there are a few differences to note in comparison to above.
First, tltool.exe
must be run in 32-bit mode, and does not require decryption. Use zest-names.txt
instead; download here. Thank you to Meebo (Tales of ABCDE Discord) and DaZombieKiller for providing this file!
The base assets are in {Tales of Zestiria}\PK1\WIN\
(what I call the "base {COMMON}
folder" above).
Unpack the assets with the following command:
tltool.exe unpack --dictionary zest_names.txt FILEHEADER.TOFHDB TLFILE.TLDAT common --bit32
NOTE: There are some models in {Tales of Zestiria}\PK0\WIN\
as well, but very few and the character models in that archive seem to be test models.
For finding the skeleton, luckily for this game the names match. (In fact the likely reason they do not match in Berseria is because the devs reused Zestiria skeletons for Berseria characters.)
For modding the game, there is no PATCH
folder system for Zestiria. You must modify the original archives.
First, instead of placing your modfiles
folder in {Tales of Berseria}/GAMEDATA/PATCH/YOURMODNAMEHERE/GENERAL/COMMON
, you will place that folder in {Tales of Zestiria}/PK1/WIN/
. Back up your original FILEHEADER.TOFHDB
and TLFILE.TLDAT
, and use the following command to insert the files in your modfiles
folder into FILEHEADER.TOFHDB
and TLFILE.TLDAT
:
tltool.exe insert FILEHEADER.TOFHDB TLFILE.TLDAT modfiles --bit32
See above for how to structure the modfiles
folder to store your modded files
For making textures, use dds_to_zesteria_totexp_p.py
in place of dds_to_berseria_totexp_p.py
.