Modme Forums

Custom Gobblegum Tutorial

Game Asset Reversing | Releases


func_vehicle:

Demo Video


Introduction
This tutorial will teach you how to create a custom Gobblegum (internally referred to as BGB), complete with an image, model, and custom effects.

Creating custom Gobblegums is a lengthy process, so be prepared to do quite a bit of work. This can be done either as a mod, or as a part of a map. You'll almost certainly want to use the map method as it doesn't need a mod to function, so players downloading your map won't need to find the mod for the map to work, but I've included steps for both for completeness. Skip over sections marked as 'MOD ONLY' if you are using the map method, and vice versa.

You'll need to use my custom Gobblegum machine if you want to dispense the Gobblegum (don't worry, it's better than the original anyway). If you haven't already got it, you'll learn more later in this tutorial.

Download this pack, which contains (almost) everything you'll need to create your custom Gobblegum and have it work on your map. The steps in this tutorial will refer to files in the corresponding folder of the zip.

This has taken a lot of researching to do, so there might be some errors in this tutorial. Let me know if you have any issues.

Step 0(Preplanning)
The first thing you need to do is think of what your Gobblegum is going to do. Changing its internal name, activation type, etc. later is not easy, so make sure you know what you want to call it and what you want it to do now. For this tutorial, I'll create a round-based (blue) Gobblegum with internal name func_vehicle, to keep it simple to understand. Just replace func_vehicle with your_gobblegum_name (lowercase, underscores as spaces) whenever you see it.

Step 1(Logo)
One of the most important assets you need to create is the Gobblegum logo. Open the Step 1 folder in the zip, which contains the background circle for the four types of Gobblegum. Open the background in an image editor and create a new layer on top of the background. Use pure white (255, 255, 255) to create the logo inside the coloured area. Once you're finished, save it in your image editor's format to preserve layers in case you want to edit it later. Then save it as a png, called i_mtl_p7_zm_bgb_icon_func_vehicle_c.png.

Step 2(HUD icon)
Another asset we need to create is the Gobblegum HUD icon. Open the Step 2 folder, which contains existing HUD icons for every colour and rarity combination. Open the image that matches the colour and rarity combination that you want in an image editor and create a new layer. Add the logo png you created in the last step to this new layer, and use your editor's tools to remove the white around the logo. Position your logo so that it perfectly covers the existing logo, while keeping the white outline. Create a third layer on top, and either use one of my premade 'magic layers' to make the logo look like it is shaded or create your own. To make your own magic layer, make a circular selection that matches the size of the logo area, and then use large, soft brushes of pure black or pure white at about 8-32/256 transparency. Then just try to recreate the shading effect.

At this point, you should compare your HUD icon to one of the base icons I have provided, to make sure they look similar enough. I've found you might need to boost the saturation on the logo layer to get the look to match up. Once you're done, save this twice, once in your editor's format and again as a png called t7_hud_zm_bgb_func_vehicle.png.

Step 3(APE 1)
Firstly, move your two created pngs to a suitable game folder. Personally, I used Call of Duty Black Ops III\texture_assets\custom_bgb. If you don't use this folder, you're going to have to change a lot of file paths.
While you're here, also move all the textures in the Step 3 textures folder to this location.


Now we need to set things up in APE. Drag the GDTs found in the Step 3 GDTs folder to Call of Duty Black Ops III\source_data.
You need to locate the zm_bgb_func_vehicle GDT in APE, and rename all instances of func_vehicle with your_gobblegum_name, including the GDT name itself and the assets names and properties.

We also need to quickly change some model textures. You need to open the XMODEL_EXPORT files in a text editor and scroll to the bottom. You'll see some filenames. Replace 'func_vehicle' in the lower pair with your_gobblegum_name, and the upper pair line with one of the following lines depending on colour and rarity:

Classic
MATERIAL 0 "mtl_p7_zm_bgb_regular_blue" "Phong" "color:..\_images\i_mtl_p7_zm_bgb_regular_blue_c.png"
MATERIAL 0 "mtl_p7_zm_bgb_regular_green" "Phong" "color:..\_images\i_mtl_p7_zm_bgb_regular_green_c.png"
MATERIAL 0 "mtl_p7_zm_bgb_regular_orange" "Phong" "color:..\_images\i_mtl_p7_zm_bgb_regular_orange_c.png"
MATERIAL 0 "mtl_p7_zm_bgb_regular_purple" "Phong" "color:..\_images\i_mtl_p7_zm_bgb_regular_purple_c.png"

Mega
MATERIAL 0 "mtl_p7_zm_bgb_mega_blue" "Phong" "color:..\_images\i_mtl_p7_zm_bgb_mega_blue_c.png"
MATERIAL 0 "mtl_p7_zm_bgb_mega_green" "Phong" "color:..\_images\i_mtl_p7_zm_bgb_mega_green_c.png"
MATERIAL 0 "mtl_p7_zm_bgb_mega_orange" "Phong" "color:..\_images\i_mtl_p7_zm_bgb_mega_orange_c.png"
MATERIAL 0 "mtl_p7_zm_bgb_mega_purple" "Phong" "color:..\_images\i_mtl_p7_zm_bgb_mega_purple_c.png"

Rare Mega
MATERIAL 0 "mtl_p7_zm_bgb_rare_mega_blue" "Phong" "color:..\_images\i_mtl_p7_zm_bgb_rare_mega_blue_c.png"
MATERIAL 0 "mtl_p7_zm_bgb_rare_mega_green" "Phong" "color:..\_images\i_mtl_p7_zm_bgb_rare_mega_green_c.png"
MATERIAL 0 "mtl_p7_zm_bgb_rare_mega_orange" "Phong" "color:..\_images\i_mtl_p7_zm_bgb_rare_mega_orange_c.png"
MATERIAL 0 "mtl_p7_zm_bgb_rare_mega_purple" "Phong" "color:..\_images\i_mtl_p7_zm_bgb_rare_mega_purple_c.png"

Ultra-rare Mega
MATERIAL 0 "mtl_p7_zm_bgb_urm_blue" "Phong" "color:..\_images\i_mtl_p7_zm_bgb_urm_blue_c.png"
MATERIAL 0 "mtl_p7_zm_bgb_urm_green" "Phong" "color:..\_images\i_mtl_p7_zm_bgb_urm_green_c.png"
MATERIAL 0 "mtl_p7_zm_bgb_urm_orange" "Phong" "color:..\_images\i_mtl_p7_zm_bgb_urm_orange_c.png"
MATERIAL 0 "mtl_p7_zm_bgb_urm_purple" "Phong" "color:..\_images\i_mtl_p7_zm_bgb_urm_purple_c.png"

Whimsical
MATERIAL 0 "mtl_p7_zm_bgb_whim_blue" "Phong" "color:..\_images\i_mtl_p7_zm_bgb_whim_blue_c.png"
MATERIAL 0 "mtl_p7_zm_bgb_whim_green" "Phong" "color:..\_images\i_mtl_p7_zm_bgb_whim_green_c.png"
MATERIAL 0 "mtl_p7_zm_bgb_whim_orange" "Phong" "color:..\_images\i_mtl_p7_zm_bgb_whim_orange_c.png"
MATERIAL 0 "mtl_p7_zm_bgb_whim_purple" "Phong" "color:..\_images\i_mtl_p7_zm_bgb_whim_purple_c.png"

Once you've made the changes, use Export2Bin to turn them into XMODEL_BINs. Then move these bins to a suitable folder, this time I used Call of Duty Black Ops III\model_export\custom_bgb. Then, change LOD0 in both models in APE to the corresponding XMODEL_BIN.

A sign that you have done this correctly is the models (p7_zm_bgb_func_vehicle, p7_zm_bgb_func_vehicle_ui) will look correct in the 3D preview (use alt and drag left mouse to rotate the model). Don't worry about the camo (mtl_zmb_t7_camo_bgb_func_vehicle_i), that will still look untextured even if you have changed the color map property.

We need to do some more stuff in APE in the next step, so keep it open.

Step 4(APE 2)
Now we need to modify the camo list. You've already moved the required GDT (zm_bgb_shared) to the correct folder in the previous step. Find it in APE, and modify camo_t7_zmb_bgb_ship. Scroll down to Camo Type 64. This is the first available slot that we can add our Gobblegum, and this is the slot which the example uses. Each camo slot has two materials, and they each have a 'base material', and a 'replace with' property. Don't change the base materials. For Material 1, you want to change the 'replace with' value to the material used by a Gobblegum with the same type and rarity as yours. For example, because my Gobblegum will be round-based with a Mega rarity appearance, I will choose this material to be the same as Board Games, and thus will put 'mtl_zmb_t7_camo_bgb_board_games' as Material 1's replace with value.

Material 2 should be your camo material ie. mtl_zmb_t7_camo_bgb_func_vehicle_i.

You can ignore the 'Asset doesn't exist' warnings, it will work in game just fine.

The slot you choose is important, because it maps to a Camo Index which we will need later. Unfortunately, Treyarch has kind of fucked with this table internally, so it doesn't exactly work like you think it would. Camo Type 64 - 71 work, and they map to Camo Index 61 - 68 (just take 3 away to get index). Camo Type 72 - 75 don't work as already existing Gobblegums take up their respective indices for some reason. If you need more than 8 slots, move to the second file, camo_t7_zmb_bgb_base76.
Camo Type 76 and higher seem to map to one less in the Camo Index (ie. Camo Type 76 -> Camo Index 75).

Step 5(Modifying existing scripts)
To get our Gobblegum to work in game, we will eventually need to 'register' it. The register function definitions are not included in bgb gsc or csc skeletons by default, so we need to add them. Open Call of Duty Black Ops III\share\raw\scripts\zm\_zm_bgb.gsc in a text editor. Below the last line, add

function register(name, limit_type, limit, enable_func, disable_func, validation_func, activation_func) {}
. Likewise in the corresponding .csc (Call of Duty Black Ops III\share\raw\scripts\zm\_zm_bgb.csc), add
function register(name, limit_type) {}
below the namespace. If you're wondering why this works or is needed, the compiler checks against these skeleton files when compiling, but the real versions are used when in-game.

Step 6(Localization)
Now we need to add the localized name, description and hint for our Gobblegum. This is done in zmui.str. Drag this file from Step 6 to Call of Duty Black Ops III\usermaps\your_map_name\english\localizedstrings. Open it in a text editor, and change the references to have your_gobblegum_name instead of func_vehicle. The first entry is the name of the Gobblegum, the second is the menu description (which you won't see unless you're using the mod method), and the third is the in-game hint that pops up at the top of the screen when you take the Gobblegum from the machine.

Make sure to keep ^1CUSTOM\n^7 from the start of the description, to help distinguish your Gobblegum from ones in the base game. Your hint should be short and descriptive, as it is possibly the only description of what your Gobblegum does that the user will see, and it's only visible for a few seconds. You can use \n for a new line.

Step 7A(Modifying the stats table)
(THIS STEP IS MOD ONLY)

Next up is modifying zm_statstable.csv to include our Gobblegum. Move the csv in Step 7A to Call of Duty Black Ops III\mods\your_mod_name\gamedata\stats\zm, and open it with a spreadsheet program or text editor. You need to locate a free slot (a number between 0-255 that isn't already used in the first column). Make a new row inbetween the existing ones. For example, I see 199 is free, so I create the row between 198 (next lowest) and 200 (next highest).

Column 1: slot number (found from above)
Column 2: blank
Column 3:
bubblegum
(Gobblegum will appear in Classics tab on menu), or
bubblegum_consumable
(Gobblegum will appear in Mega tab on menu)
Column 4:
zmui_bgb_func_vehicle

Column 5:
zm_bgb_func_vehicle

Column 6: camo index (refer to Step 4)
Column 7:
t7_hud_zm_bgb_func_vehicle

Column 8:
zmui_bgb_func_vehicle_desc

Column 9: blank
Column 10: sort order on menu (just put 1)
Column 11: unlock level (just leave blank)
Column 12: blank
Column 13 can be either 1 (appear in menu) or -1 (hidden from menu), just use 1
Column 14:
equippedbubblegumpack

Column 15: blank
Column 16: dlc requirement (just leave blank)
Column 17: rarity (0 for classic, 1 for mega, 2 for rare mega, 3 for ultra-rare mega, 4 for whimsical)
Column 18: level locked (just put 0)
Column 19: unknown (just leave blank)
Column 20: blank
Column 21: activation method (should be obvious, look at other rows)

Step 7B(Modifying the HUD)
(THIS STEP IS MAP ONLY)
We need to alter the HUD elements responsible for displaying Gobblegums as we cannot alter zm_statstable.csv with just a map (clients will be disconnected immediately upon loading an online game if you do so). Drag the ui folder from Step 7B of the pack into your map's folder.


IMPORTANT: For Lua to actually compile as part of your map, you need L3akMod.

Steps continue in next post...


func_vehicle:

Step 8 (Coding the Gobblegum's effects)
This is the fun step! It's finally time to make your Gobblegum do something. Copy the files in Step 8 to Call of Duty Black Ops III\usermaps\your_map_name\scripts\zm\bgbs (or corresponding mod folder). Once you've renamed these files, open them in a text editor. In __init__(), we 'register' the Gobblegum. Here's what the parameters do:

Parameter 1 is your Gobblegum's internal name.
Parameter 2 is activation method. (rounds, time, event, or activated).
Parameters 3+ are only used in GSC.
Parameter 3 is the 'use limit'. For rounds, this is 'full rounds' (ie. 0 means till end of current round). For time, it's the time in seconds. For activated, it's the number of times it can be activated. For event, completely skip this parameter.
Parameters 4 and 5 are the enable / disable functions. Enable is called on receiving the BGB, and disable is called when the BGB is swapped or expires.
Parameters 6 and 7 are the validation / activation functions. These are only used on 'activated' (purple) Gobblegums.
The validation function should return true or false depending on whether the user should be able to activate the Gobblegum. The basic cases (drinking perk, downed, etc) are already taken care of, so you don't need to worry about them. An example of when you would need this is with a gum like In Plain Sight, where you don't want it to be activated again while the first use is still active.
The activation function is called when the bubble blowing animation is finished. Don't forget a

self endon("disconnect");
if necessary.

Other useful functions (might need to be added to skeleton GSC):
self thread bgb::run_timer(10);
- Make the BGB thermometer show a timed use before reverting to normal status (eg: In Plain Sight activation).
self bgb::set_timer(3, 5);
- Set the BGB thermometer to a certain percentage (eg 3/5, 60%), useful for event-type Gobblegum as they need to store use count themselves.
self bgb::do_one_shot_use();
- Make the BGB thermometer show a use (pulsate).

Step 9 (Integration with my custom Gobblegum machine)
To dispense the gums, you need to use my custom Gobblegum machine.

Follow the instructions here to install it if you don't already have it.

(MAP ONLY)
Because of the changes needed to get custom Gobblegums working without a mod, you need a different version of my machine. This is a drag and drop replacement once you've got my custom Gobblegum machine from above.

(BOTH MAP AND MOD)
Create a new row at the bottom of Call of Duty Black Ops III\usermaps\zm_testlevel\gamedata\weapons\zm\zm_levelcommon_bgb.csv.

Column 1:
zm_bgb_func_vehicle

Column 2: statstable slot number
(If using the map method, pick an unused number in the first column of zm_statstable.csv in the Step 7A folder)
Column 3: camo index (refer to Step 4)
Column 4: activation method (1 for activated, 2 for event, 3 for rounds, 4 for time)
Column 5: rarity (DIFFERENT FROM STATSTABLE! 1 for classic, 2 for mega, 3 for rare mega, 4 for ultra-rare mega, 5 for whimsical)
Column 6: coop only (
TRUE
or
FALSE
)
Column 7: weight

Step 10 (GSC / CSC setup)
In your mapname.gsc file, add this line:
#using scripts\zm\bgbs\_zm_bgb_func_vehicle;

In your mapname.csc file, add this line:
#using scripts\zm\bgbs\_zm_bgb_func_vehicle;


(MAP ONLY)
In your mapname.csc file, add these lines to the start of
main()
to load our HUD overrides:
LuiLoad( "ui.uieditor.menus.hud.t7hud_zm_custom" );
LuiLoad( "ui.uieditor.widgets.hud.zm_ammowidget.zmammo_bbgummeterwidget_fix" );
LuiLoad( "ui.uieditor.widgets.mphudwidgets.cursorhint_image_fix" );
LuiLoad( "ui.uieditor.widgets.hud.zm_cursorhint.zmcursorhint_fix" );

Step 11(Zone setup)
We need to include a lot of files in your mapname.zone file. I'll just list them below.

(YOU SHOULD ALREADY HAVE)
stringtable,gamedata/weapons/zm/zm_levelcommon_bgb.csv
scriptparsetree,scripts/zm/_zm_bgb_fix.gsc
scriptparsetree,scripts/zm/_zm_bgb_fix.csc

(BOTH MAP AND MOD)
stringtable,gamedata/weapons/zm/zm_levelcommon_bgb.csv
localize,zmui

image,i_mtl_p7_zm_bgb_icon_func_vehicle_c
image,t7_hud_zm_bgb_func_vehicle
material,mtl_p7_zm_bgb_icon_func_vehicle
material,t7_hud_zm_bgb_func_vehicle
material,mc/mtl_zmb_t7_camo_bgb_func_vehicle_i
xmodel,p7_zm_bgb_func_vehicle
xmodel,p7_zm_bgb_func_vehicle_ui

weaponcamo,camo_t7_zmb_bgb

image,i_mtl_p7_zm_bgb_mega_g
image,i_mtl_p7_zm_bgb_mega_blue_c
material,mc/mtl_p7_zm_bgb_mega_blue

scriptparsetree,scripts/zm/bgbs/_zm_bgb_func_vehicle.gsc
scriptparsetree,scripts/zm/bgbs/_zm_bgb_func_vehicle.csc

NOTE: The 'Mega' speckled rarity requires a gloss map (i_mtl_p7_zm_bgb_mega_g). This is special to this rarity, and this line can be removed for other rarities.

(MOD ONLY)
stringtable,gamedata/stats/zm/zm_statstable.csv

(MAP ONLY)
rawfile,ui/uieditor/menus/hud/t7hud_zm_custom.lua
rawfile,ui/uieditor/widgets/mphudwidgets/cursorhint_image_fix.lua
rawfile,ui/uieditor/widgets/hud/zm_cursorhint/zmcursorhint_fix.lua
rawfile,ui/uieditor/widgets/hud/zm_ammowidget/zmammo_bbgummeterwidget_fix.lua

We also need to comment out some lines from csv files in Call of Duty Black Ops III\zone_source. Put two slashes in front of the following lines:

(BOTH MAP AND MOD)
Call of Duty Black Ops III\zone_source\english\assetlist\core_patch.csv - localize,zmui
Call of Duty Black Ops III\zone_source\all\assetlist\zm_common.csv - weaponcamo,camo_t7_zmb_bgb

(MOD ONLY)
Call of Duty Black Ops III\zone_source\all\assetlist\core_patch.csv - stringtable,gamedata/stats/zm/zm_statstable.csv

Step 12(Testing)
At this point, everything should be ready to work. For testing purposes, I would recommend setting the weight of every gum to 0 except for your gum and a vanilla gum. Buy from the machine in game, and see if everything is working.
Also, I would recommend testing your map with at least one other player online, just to make sure everything functions properly in coop.

Congratulations
If you've reached this point, you've got your hands on a fully functioning custom Gobblegum!

Credits
Scobalula - Cerberus, HydraX
DTZxPorter - Wraith
JariK - Lua decompiler
The D3V Team (DTZxPorter, SE2Dev, Nukem) - L3akMod, t7hud_zm_custom.lua
Niknokinater - Testing

Update #1 (20/10/2020)
Added missing XMODEL_EXPORT files to the Step 3 folder.
Updated Step 8 instructions.


GreenDonut:

This is insane. Thank you for this and being extremely specific with the instructions. Much appreciated!