These modding use cases provide example process, code and ideas for how you might tackle a mod that aims to complete a certain goal - such as add new weapons, rebalancing armor or adding new storylines altogether.
To demonstrate the use of the different methods you could use, the first Use Case below shows the same modification from 3 different input files.
Use Case: Add or Modify Weapons[edit | edit source]
This use case demonstrates three ways to add a new weapon and update an existing weapon with the mod toolkit. Each approach produces the same result in the game database. Choose the approach that fits your workflow but note that Method C is the recommended path as it is the simplest and requires the least knowledge of the game's database.
- Method A — Write raw SQL and JSON by hand. Method A is included here to demonstrate that it can be done this way but not as a recommended path. Use Method A if and only if you have written your own authoring tool to produce this output.
- Method B — Use RawSQL and RawText blocks inside the JSON Data Parser. Like Method A, we have included Method B to show that it can be done this way but it is not recommended unless you have a tool to help you create produce this output.
- Method C — Use the JSON Data Parser's native table format. The preferred approach for most cases but if your mod is heavily modifying data-tables like adding or creating many weapons, it may be better to create and manage this mod in Excel and use its formulas to output the required text.
Task 1: Modifying the Defensor[edit | edit source]
The Defensor (WeaponId=64) is a pistol. Our use case will:
- Set its
BallisticDamage1to200 - Rename it to
SUPER Defensorin the localization file
Task 2: Add a New Weapon: The Rhino Raptor[edit | edit source]
We are creating the Rhino Raptor (WeaponId=300200), a heavier close-range variant of the Heavy Raptor (WeaponId=7010). It hits harder but has a shorter optimal range. All stats not listed below are identical to the Heavy Raptor.
Changes from the Heavy Raptor[edit | edit source]
- BallisticDamage1: 185 → 240
- OptimalRangeA1: 4 → 3
- OptimalRangeB1: 20 → 14
- Cost: 910 → 1200
Method A: Hand-Written SQL and JSON[edit | edit source]
In this method you write directly into data.sql and en-US.json . These files are placed into your upload_content\_data folder of your mod as described in Modding Data.
data.sql
-- Action 1: Update the Defensor
UPDATE Weapon SET BallisticDamage1=200 WHERE WeaponId=64;
-- Action 2: Add the Rhino Raptor
INSERT INTO Weapon (WeaponId, Rarity, Locked, ServiceOptionId, FactionId, WeaponClass, Asset3DTypeId, ShotVFXCount, MuzzleVFX, ShotVFX, HitVFX, PowerLevel, PrecisionRule, SpecialRule, WeaponEffect, Cost, CritMultiBase, CritMultiStealth, ShotVolume, FAShots, ReloadActionPoints, ReloadClipMax, ReloadSize, MaxRange, ModeType1, AmmoUsed1, Accuracy1, AngleFire1, PureDamage1, PhysicalDamage1, BallisticDamage1, ActionPoints1, RecoilRate1, ArmorCritRate1, OptimalRangeA1, OptimalRangeB1, ModeType2, AmmoUsed2, Accuracy2, AngleFire2, PureDamage2, PhysicalDamage2, BallisticDamage2, ActionPoints2, RecoilRate2, ArmorCritRate2, OptimalRangeA2, OptimalRangeB2, GunTypeSFX) VALUES (300200,1,0,-1,2,2,16,3,"Weapons/WeaponVFX_Pistol","","",6,0,3,0,1200,0,180,32,0,10,0,4,29,2,1,80,50,40,0,240,20,11,0,3,14,-1,0,0,0,0,0,0,0,0,0,0,0,"Pistol");
en-US.json
{
"WeaponName.64": "SUPER Defensor",
"WeaponName.300200": "Rhino Raptor"
}
Pros and Cons[edit | edit source]
Pros: No tooling is required. Full control over every field.
Cons: You should have a tool or write your own. Easy to make mistakes in the long INSERT column list. No validation. Must manually manage field ordering. Must know all the correct default field vaules. JSON and SQL are in separate files with no cross-checking.
Method B: RawSQL and RawText Inside the JSON Data Parser[edit | edit source]
In this method, you write a single .json input file and run it through the Data Parser. The raw SQL and text are passed through verbatim with no schema processing.
Input JSON file[edit | edit source]
{
"Metadata": {
"StoryKey": "WeaponUpdate",
"StartingId": 300200
},
"RawSQL": [
"UPDATE Weapon SET BallisticDamage1=200 WHERE WeaponId=64;",
"INSERT INTO Weapon (WeaponId, Rarity, Locked, ServiceOptionId, FactionId, WeaponClass, Asset3DTypeId, ShotVFXCount, MuzzleVFX, ShotVFX, HitVFX, PowerLevel, PrecisionRule, SpecialRule, WeaponEffect, Cost, CritMultiBase, CritMultiStealth, ShotVolume, FAShots, ReloadActionPoints, ReloadClipMax, ReloadSize, MaxRange, ModeType1, AmmoUsed1, Accuracy1, AngleFire1, PureDamage1, PhysicalDamage1, BallisticDamage1, ActionPoints1, RecoilRate1, ArmorCritRate1, OptimalRangeA1, OptimalRangeB1, ModeType2, AmmoUsed2, Accuracy2, AngleFire2, PureDamage2, PhysicalDamage2, BallisticDamage2, ActionPoints2, RecoilRate2, ArmorCritRate2, OptimalRangeA2, OptimalRangeB2, GunTypeSFX) VALUES (300200,1,0,-1,2,2,16,3,\"Weapons/WeaponVFX_Pistol\",\"\",\"\",6,0,3,0,1200,0,180,32,0,10,0,4,29,2,1,80,50,40,0,240,24,11,0,3,14,-1,0,0,0,0,0,0,0,0,0,0,0,\"Pistol\");"
],
"RawText": {
"Generic": {
"WeaponName.64": "SUPER Defensor",
"WeaponName.300200": "Rhino Raptor"
}
}
}
Data Parser output: data.sql
UPDATE Weapon SET BallisticDamage1=200 WHERE WeaponId=64;
INSERT INTO Weapon (WeaponId, Rarity, Locked, ..., GunTypeSFX) VALUES (300200,1,0,...,"Pistol");
Data Parser output: en-US.json
{
"WeaponName.64": "SUPER Defensor",
"WeaponName.300200": "Rhino Raptor"
}
Pros and Cons[edit | edit source]
Pros: Single input file. SQL and text stay together. The parser handles file output.
Cons: Same verbosity as Method A for the INSERT — you still write every column by hand. No schema validation on the raw content.
Method C: Data Parser JSON[edit | edit source]
In this method, both weapons are expressed in the Data Parser's schema. Field names are validated, aliases can be used, defaults are filled automatically, and the parser generates both the SQL and JSON output. The UPDATE action uses the "SQL": "update" field.
Input JSON file[edit | edit source]
{
"Metadata": {
"StoryKey": "WeaponUpdate",
"StartingId": 300200
},
"Weapon": [
{
"#": "Task 1: Update the Defensor - only BallisticDamage1 appears in the SET clause",
"WeaponId": 64,
"BallisticDamage1": 200,
"SQL": "update"
},
{
"#": "Task 2: Add the Rhino Raptor - a heavier close-range variant of the Heavy Raptor",
"WeaponId": 300200,
"Rarity": "Common",
"Service": -1,
"Faction": 2,
"Class": 2,
"Asset": 16,
"ShotVFXCount": 3,
"MuzzleVFX": "Weapons/WeaponVFX_Pistol",
"ShotVFX": "",
"HitVFX": "",
"PowerLevel": 6,
"PrecisionRule": 0,
"SpecialRule": 3,
"Cost": 1200,
"CritMultiStealth": 180,
"ShotVolume": 32,
"Reload": 10,
"ClipMax": 0,
"ClipSize": 4,
"MaxRange": 29,
"ModeType1": 2,
"AmmoUsed1": 1,
"Accuracy1": 80,
"AngleFire1": 50,
"PureDamage1": 40,
"BallisticDamage1": 240,
"ActionPoints1": 20,
"RecoilRate1": 11,
"OptimalRangeA1": 3,
"OptimalRangeB1": 14,
"ModeType2": -1,
"GunTypeSFX": "Pistol",
"Name": "Rhino Raptor"
}
],
"RawText": {
"Generic": {
"WeaponName.64": "SUPER Defensor"
}
}
}
Notes on the JSON format[edit | edit source]
- The update item for the Defensor only needs
WeaponId(the WHERE key) and the exact fields to change. All other fields are ignored — the parser generatesUPDATE Weapon SET BallisticDamage1=200 WHERE WeaponId=64;with no defaults applied. - The new Rhino Raptor uses short aliases where available:
Service→ServiceOptionId,Class→WeaponClass,Asset→Asset3DTypeId,Reload→ReloadActionPoints,ClipMax→ReloadClipMax,ClipSize→ReloadSize,Effect→WeaponEffect,Faction→FactionId. - The
Namefield on the new weapon routes directly toWeaponName.{WeaponId}in the localization JSON output — no separate RawText entry needed. - The Defensor rename uses
RawTextbecause the parser only appends to the localization file — it cannot update keys that already exist in the database.
Data Parser output: data.sql
UPDATE Weapon SET BallisticDamage1=200 WHERE WeaponId=64;
INSERT INTO Weapon (WeaponId, Rarity, Locked, ServiceOptionId, FactionId, WeaponClass, Asset3DTypeId, ShotVFXCount, MuzzleVFX, ShotVFX, HitVFX, PowerLevel, PrecisionRule, SpecialRule, WeaponEffect, Cost, CritMultiBase, CritMultiStealth, ShotVolume, FAShots, ReloadActionPoints, ReloadClipMax, ReloadSize, MaxRange, ModeType1, AmmoUsed1, Accuracy1, AngleFire1, PureDamage1, PhysicalDamage1, BallisticDamage1, ActionPoints1, RecoilRate1, ArmorCritRate1, OptimalRangeA1, OptimalRangeB1, ModeType2, AmmoUsed2, Accuracy2, AngleFire2, PureDamage2, PhysicalDamage2, BallisticDamage2, ActionPoints2, RecoilRate2, ArmorCritRate2, OptimalRangeA2, OptimalRangeB2, GunTypeSFX) VALUES (300200,1,0,-1,2,2,16,3,"Weapons/WeaponVFX_Pistol","","",6,0,3,0,1200,0,180,32,0,10,0,4,29,2,1,80,50,39.775,0,240,24,10.5,0,3,14,-1,0,0,0,0,0,0,0,0,0,0,0,"Pistol");
Data Parser output: en-US.json
{
"WeaponName.300200": "Rhino Raptor",
"WeaponName.64": "SUPER Defensor"
}
Pros and Cons[edit | edit source]
Pros: Schema validation catches unknown fields and type errors before any output is written. Aliases keep the file readable. The Name field on new records routes automatically to localization. Comments ("#") can annotate intent. Only the fields you intend to change appear in an UPDATE.
Cons: Requires familiarity with the parser's field names and aliases. The tool must be run to produce output.
Adding an Item[edit | edit source]
This use case relies on Modding Data toolset and may require the Modding Example Project.
Rebalancing the Game[edit | edit source]
This use case relies on Modding Data toolset.
Writing a Storyline[edit | edit source]
This use case relies on Modding Data toolset.
Adding an Underworld Hub Recruit[edit | edit source]
This use case relies on Modding Data toolset.
Adding a Proc-gen Legwork[edit | edit source]
This use case relies on Modding Data toolset.
Adding a Cosmetic[edit | edit source]
This use case relies on Modding Data toolset and the Modding Example Project.
Adding Weapons[edit | edit source]
This use case relies on Modding Data toolset and may require the Modding Example Project.
Modding: Home · Quick Start Guide · Modkit Uploader · Example Project · Data Modding · Data Parser Schema · Use Cases · Download Modding Resources