Create a Vault
Step-by-step guide to adding a custom vault to FS-Robberies.
Overview
This guide shows how to add a new vault using Config.CustomLocationRobberies and Config.CustomVaults in config.lua. The vault door interaction and the managed door prop must share the same id.
Interior and Door Limits
Some interiors may not work properly with vaults, and vaults currently only support swinging vault doors. Other door types are not supported at this time. The Paleto Bay default bank also has issues where the door becomes invisible at certain angles, which appears to be a limitation of spawning a custom door in an MLO.
Step 1: Enable admin tools
- Set
Config.PolyBuilderPermissionandConfig.FindVaultPermissioninconfig.lua. - Grant those ACE permissions to your admin group so you can use
/fs_poly_startand/fs_find_closest_vault_door_coord.
Step 2: Capture door data
- Stand at the vault door in-game.
- Run
/fs_find_closest_vault_door_coordand read the printed model, coords, and heading in your F8 console. - If no door is found, add your door model to
Config.VAULT_MODELSinconfig.luaand try again.
Step 3: Add the vault door interaction
Add a new entry to Config.CustomLocationRobberies:
Config.CustomLocationRobberies = {
{
id = "example_vault_door",
isVaultDoor = true,
coords = vec3(123.4567, 456.7890, 21.1234),
heading = 180.0,
interactDist = 1.6,
label = "Example Vault",
markerZ = 0.55,
timerMin = Config.Robbery.Vault.Timer.Min,
timerMax = Config.Robbery.Vault.Timer.Max,
amountMin = 0,
amountMax = 0,
cooldown = Config.Robbery.Vault.Cooldown,
},
}Note: amountMin and amountMax must stay 0 for the vault door because opening the door does not grant loot.
Step 4: Define the vault door
Create a matching entry in Config.CustomVaults. The key must be the same as the location id:
Config.CustomVaults = {
example_vault_door = {
hideOriginal = true,
model = `v_ilev_bk_vaultdoor`,
spawnPos = vec3(123.4567, 456.7890, 21.1234),
closedHeading = 180.0,
openHeading = 50.0,
durationToOpen = 5,
insideSphere = { center = vec3(125.0000, 458.0000, 21.2000), radius = 6.5 },
autoClose = { idleSeconds = 25 },
insideRobberies = {
{
id = "example_deposit_box_1",
coords = vec3(126.0000, 459.0000, 21.2000),
heading = 90.0,
label = "Deposit Box 1",
amountMin = Config.Robbery.Vault.Rewards.MinMoney,
amountMax = Config.Robbery.Vault.Rewards.MaxMoney,
},
},
},
}Notes:
openHeadingis an absolute heading. Values will be wrapped to0-360when applied, but it is best to keep them in range for clarity.closedHeadingfollows the same rule asopenHeading.insideSphereis the fastest way to get a working vault. UseinsidePolyinstead for exact interior shapes.insideRobberiesentries must have uniqueidvalues.
Step 5: (Optional) Use a polygon inside zone
If your vault interior is not circular or you want a tighter fit than a sphere, use a polygon to define the inside zone. The polygon is a 2D outline (top-down) with minZ and maxZ defining the vertical range.
When to use insidePoly
- Your vault is rectangular or irregular.
- You need the trigger area to follow walls/doors closely.
- A sphere would include areas outside the vault.
- Run
/fs_poly_start example_vault_inside. - Left click to add points around the interior.
- Use
Zto setminZandXto setmaxZ. - Press
ENTERto finish and copy the printed Lua table. - Paste the
insidePolyblock into your vault definition, replacinginsideSphere.
Min/Max Z Tuning
The generated minZ and maxZ may need manual tuning to fit your vault interior.
Hysteresis
hysteresis is a buffer (in meters) from the boundary required to flip inside/outside, which prevents rapid toggling when players stand on the edge.
Example output from the poly builder:
insidePoly = {
points = {
vec3(123.1000, 456.2000, 21.10),
vec3(124.5000, 456.2500, 21.10),
vec3(124.4500, 457.8000, 21.10),
vec3(123.0500, 457.7500, 21.10),
},
minZ = 21.10,
maxZ = 24.10,
hysteresis = 0.75,
},Add insidePoly to your vault config
Replace the insideSphere line in your vault with the insidePoly block you generated:
Config.CustomVaults = {
example_vault_door = {
hideOriginal = true,
model = `v_ilev_bk_vaultdoor`,
spawnPos = vec3(123.4567, 456.7890, 21.1234),
closedHeading = 180.0,
openHeading = 50.0,
durationToOpen = 5,
insidePoly = {
points = {
vec3(123.1000, 456.2000, 21.10),
vec3(124.5000, 456.2500, 21.10),
vec3(124.4500, 457.8000, 21.10),
vec3(123.0500, 457.7500, 21.10),
},
minZ = 21.10,
maxZ = 24.10,
hysteresis = 0.75,
},
autoClose = { idleSeconds = 25 },
insideRobberies = {
{
id = "example_deposit_box_1",
coords = vec3(126.0000, 459.0000, 21.2000),
heading = 90.0,
label = "Deposit Box 1",
amountMin = Config.Robbery.Vault.Rewards.MinMoney,
amountMax = Config.Robbery.Vault.Rewards.MaxMoney,
},
},
},
}Step 6: Test and debug
- Set
Config.DebugDrawZones = trueto visualize inside zones. - Use
/openvaultto open the nearest vault and verify inside loot points. - Use
/closevaultto reset it.
Replacing a default vault
If you are replacing a default vault door, set the matching id to false in Config.EnableDefaultVaults and add your custom entries with the same id so you do not get duplicate vault doors.