Creating Custom Weapons
Last updated
Was this helpful?
Last updated
Was this helpful?
Most information below this point has been reproduced from Mccad00's "How to make custom weapons for GTFO" guide, with updates, additions, and clarifications.
In most, if not all cases, information from the actual DataBlock pages on this wiki is marginally more up-to-date than whatever is reproduced in this guide - please refer to the DataBlock pages if there are discrepancies.
In GTFO, weapons are composed of a large number of DataBlocks which provide stats, determine behavior, recoil data, and configure their appearance.
Before going any further, it’s important that you understand what main DataBlocks contain weapon data, and what data are in each.
PlayerOfflineGearDataBlock: Creates an inventory object that players can select in the lobby and then use in-game by defining a collection of 3d objects (weapon parts) and associating them with data from a GearCategoryDataBlock entry, as well as some other DataBlock entries.
GearCategoryDataBlock: Groups together 4 ArchetypeDataBlock entries and 1 ItemDataBlock entry.
ArchetypeDataBlock: Defines weapon statistics and associates a RecoilDataBlock entry with them, in addition to referencing other metadata.
ItemDataBlock: Defines what inventory slot a piece of equipment uses, controls its HUD elements, and defines what type of Item it is.
Note: There will be some DataBlock information reproduced in this guide. For clarity, inline comments have been added. Again, please refer to the actual datablock pages for more detail.
At the heart of every weapon in GTFO is the ArchetypeDataBlock, which determines a gun’s statistics and metadata. Like most DataBlocks, there are many fields and not all of them are always relevant.
This is a very terse guide to this DataBlock - please see the actual ArchetypeDataBlock page for more details.
Note: Any new weapon Archetype you create needs a unique PersistentID for its data. Keep track of this ID as you’ll be using it in the GearCategory DataBlock.
Perhaps the most baffling DataBlock involved in custom weapons and gear is the GearCategory DataBlock. The GearCategory system is designed to group together 4 archetype DataBlock entries into one category and assigns them an entry in the Item Datablock, which is used to assign the weapons behavior on the HUD and a slot in the inventory to fit into. Let’s take a look at an example.
Note: Any new GearCategory you create needs a unique PersistentID for its data. Keep track of this PersistentID so you can reference it in the PlayerOfflineGearDataBlock.
Sometimes, multiple parts in a GearJSON will share the same aligns as each other, which will result in one of the parts defaulting to have that align. In order to control which parts get the align in cases like this, we need to edit the PartAlignPriority in the GearCategoryDataBlock. The GearCategory which is linked to your weapon via the ‘Category’ component type will determine which GearCategory you need to modify for this. Let’s look at the Magnum’s part align priority to see how it works:
"AlignType":
This corresponds to the Enum that is used by Aligns in the GearDataBlocks.
"PartPrio":
A list of gear component types, ordered by priority. This determines which part to assign this align to.
So, this set of align priorities means that align types 7 and 8 (LeftHand and RightHand) are both going to prioritize part 12. From this setup, we can guess that this is probably necessary so that both hands align on the grip.
In GTFO, almost every piece of equipment is assembled programmatically to get more mileage out of the limited assets the game shipped with.
Weapons, tools, and even some consumables are put together using this system. For the sake of simplicity, we will refer to these assembled items as ‘Gear’. Every assembled Gear item in GTFO is set up in the PlayerOfflineGearDataBlock via a string called GearJSON.
To start, let’s break down the GearJSON string for the Pistol:
Note: Line breaks have been added into this string for the explanation, but in your DataBlock the entire string must be on a single line with no linebreaks.
"{\"Ver\":1,\"Name\":\"Shelling S49\",
This line assigns the GearJSON a ‘descriptive name’, which is displayed in your inventory and in the lobby screen.
\"Packet\":{\"Comps\":{\"Length\":16,
This line tells the game how many gear components your part contains. If this number doesn’t match the actual number of gear components, the game won’t read the GearJSON string correctly.
\"a\":{\"c\":2,\"v\":8},
This line defines a gear component to add to our GearJSON, which is broken up into 3 values:
\"a\"
The index, in alphabetical order, of this gear component. Notice in our example that every component starts with a unique letter identifier.
\"c\":2
The component type, such as FrontPart, ReceiverPart, or StockPart. In this component, type is ‘2’ which corresponds to GearCategory. If you attempt to use the same component type on multiple components, only one of them will load.
"V\":8
The component value. This tells the game which component to load for a given type. In this component, since the type was GearCategory, this will load the GearCategory with persistentID 8.
The ending section of the GearJSON string, starting with \"MatTrans\"
, is not used by the game.
You can have as many gear components as you want in a GearJSON, provided you use correct syntax to define them. Because of the complexity and obscurity of GearJSON strings, writing one from scratch is discouraged. Instead, duplicating and modifying an existing GearJSON from the base game is a simpler method that will save you time (and sanity).
Note: Unused/Unusable component types are omitted.
1
FireMode
0-3, determines which FireMode PersistentID to use from the GearCategory
2
Category
PersistentID of the GearCategoryDataBlock to load
3
BaseItem
PersistentID of the ItemDataBlock entry to load.
4
ItemFPSSettings
PersistentID of the ItemFPSSettings entry to load.
5
AudioSetting
PersistentID of the WeaponAudio entry to load
6
MuzzleFlash
PersistentID of the WeaponMuzzleFlash entry to load
7
ShellCasing
PersistentID of the WeaponShellCasing entry to load
12
FrontPart
The front, barrel portion of a weapon
16
ReceiverPart
The receiver of a weapon
19
StockPart
The grip or stock of a weapon
21
SightPart
The sight of a weapon; some front parts have this function built in
23
MagPart
The magazine of a weapon. Not all parts support this
25
FlashlightPart
The flashlight of a weapon
27
ToolMainPart
The base part which the rest of the tool parts align to
30
ToolGripPart
The grip or stock of a tool; this is interchangeable with StockPart
33
ToolDeliveryPart
Typically the business end of a tool
37
ToolPayloadPart
Varies widely between tools
40
ToolTargetingPart
The ‘targeting module’ placed on some tools
42
ToolScreenPart
The display screen, only functional if the gear uses the correct BaseItem
44
MeleeHeadPart
The head of a melee weapon
46
MeleeNeckPart
The part that connects the head to the handle of a melee weapon
48
MeleeHandlePart
The handle of a a melee weapon
50
MeleePommelPart
The base of the handle of a melee weapon
Note: Even though the developers typically only used appropriate parts, you can actually use any of these parts on any piece of gear.
The gear DataBlocks are used to assign behavior, animations, models, and aligns to gear parts, for use in GearJSON. The most simple, and arguably the most important part of these DataBlocks is ‘General’, which tells the game what model and children to load, and what hand animations to use.
"Model":
The path of the part prefab to load
"Children":
A list of child prefabs to load
"GearCategoryFilter": 0,
Unused.
"LeftHandGripAnim":
The animation clip to play for the player’s arms on layer 5
"RightHandGripAnim":
The animation clip to play for the player’s arms on layer 6
"AssetBundle": 20,
The asset bundle to load the prefabs from.
"BundleShard": 3
The asset shard to load the prefabs from.
Generally, when copying prefabs into this DataBlock, it’s important to make sure you use the same AssetBundle and BundleShard as the prefab you copied.
Gear parts are attached to each other using aligns, which are empty Game Objects placed onto gear parts which aligned parts are parented to. In order to change the usage of these aligns, you need to edit, or make a copy of the gear DataBlock entry for the desired part. Let’s look at the aligns of Front_UZI_1:
"AlignType": 0,
The Type of the align, which determines which part attaches to this
"AlignName": "Receiver_M"
The name of the game object which this align attaches parts to. Unfortunately, we can’t add or modify these game objects in this DataBlock, but we can tell the game what parts to place onto these aligns.
0
Muzzle
Weapon’s muzzle flash
1
ShellEject
Weapon’s ejection port
2
Magazine
Corresponds to the MagPart gear component
4
Sight
Corresponds to the SightPart gear component
5
Flashlight
Corresponds to the FlashlightPart gear component
6
SightLook
The aim camera if no sight part is present
7
LeftHand
The player’s left hand
8
RightHand
The player’s right hand
9
Receiver
Corresponds to the ReceiverPart gear component
10
Front
Corresponds to the FrontPart gear component
12
ToolGrip
Corresponds to the ToolGripPart gear component
13
ToolDelivery
Corresponds to the ToolDeliveryPart gear component
14
ToolPayload
Corresponds to the ToolPayloadPart gear component
15
ToolTargeting
Corresponds to the ToolTargetingPart gear component
16
ToolScreen
Corresponds to the ToolScreenPart gear component
17
ToolDetection
Unknown
18
ToolScanning
Unknown
20
MeleeHead
Corresponds to the MeleeHeadPart gear component
40
RotationPivot
Presumably used by sentry guns to position the contained weapon parts
41
GroundPlacement
Presumably used to position the base of a sentry gun
To handle animations, the many Gear DataBlocks contain lists of WeaponAnimSequenceItems, which provide timing, behavior, and a string to reference the animation. Let’s look at the Short Shotgun reload sequence:
"TriggerTime": 0.0,
The delay, from the start of the sequence, to play the clip.
"Type": 5,
The type, which determines the behavior of the animation.
"StringData": "shotgun_reload_1_shell_in"
The string of the animation clip.
Note: This formatting and behavior is consistent between reload and firing sequence.
0
WeaponMovementAnim
Animate the first person weapon holder
1
FrontPartAnim
Animate the weapon’s front part
2
LeftHandAnim
Animate the FPS arms (animation layer 5)
3
LeftHandMagAnim
Animate the FPS arms using the magazine’s animation. (No animation clip input required)
4
ReceiverAnim
Animate the weapon’s receiver part
5
Sound
Play a sound event using the animation string as a sound event ID
6
DoUpdateAmmo
Refill the weapon’s magazine. (No animation clip input required)
7
Empty
Do nothing. Typically used at the end of a sequence. (No animation clip input required)
8
StockAnim
Animate the weapon’s stock part
9
RightHandAnim
Animate the FPS arms (animation layer 6)
By default, it is possible to use whatever weapon or tool parts you want on any gun, and to choose what aligns those parts snap to. However, it is not possible to adjust the position, scale, or rotation of parts. To get around this limitation, you can use the GearPartCustomization plugin, which allows you to modify the location, rotation, and scale of parts and get far more mileage out of them. Once the GearPartCustomization plugin is installed, it'll create a new file in your custom folder titled GearPartTransform.json.
Let’s take a look at the composition of this file.
Each entry in the Parts list is an object with the following properties:
Each entry in the Children list is an object with the following properties:
This might seem daunting - you'll potentially be editing a very large amount of data, but thanks to Unity Explorer, this process is heavily simplified and relatively easy.
When you first boot up the game with Unity Explorer, you’ll see something like this.
For now, press F7 to close the Unity Explorer menu. Pick a level, pick the gear you'd like to customize, and start the game. Once you've loaded into the level and are in control, open the Unity Explorer menu by pressing F7. Go to the Object Explorer window and and select Object Search. Set the scope of the search to UnityObject, the class filter to Gear.GearPartHolder, and click Search.
In our search results, you’ll find the GearPartHolder objects for everything in your character's current inventory. To continue, click on the GearPartHolder of the gear you want to customize. In this example, let's modify the Hanaway PSB.
With the GearPartHolder open, you’ll be able to see all of the properties and fields of the GearPartHolder. You can also click Inspect GameObject to view the GameObject itself, where you can move, rotate, and scale the gun to make it easier to view your change while editing - for example, you can move it to the center of the screen so you can see it better. While there are many of fields here, very few of them are useful. Let’s inspect GearPartHolder.FrontPart.
You can now see the FrontPart’s global position, local position, rotation, and scale, as well as its attached child objects. Don't use the sliders to adjust these values - at the scale of this game, even minute adjustments to the sliders can move parts a tremendous distance.
Note: To change where the gun is, don't change the global position, change the local position.
When you change the values for this weapon part, you can see that the weapon part is changed in-game as well. Once you’re happy with how it looks, you can input these values into your entry in the GearPartTransform.json.
To modify the position of weapons in the first person camera, you need to either assign an existing ItemFPSSetting entry (There are plenty of good ones in the base game) or write a custom one. Let’s look at an entry in the ItemFPSSettingsDataBlock:
PersistentIDs: Before you make a new weapon, it's wise to come up with an unused PersistentID and use that for everything associated with your weapon. You can reference the TextDataBlock for ideas on how large PersistentIDs can get, and be sure to search through all existing files to make sure you don't have any collisions.