Configuration
config.lua is deliberately lean: only the knobs a server owner would realistically change. Ball physics feel, how a dead ball bounces, hit tuning, the shot bands, netcode timings, the animation clip map and the contact measurements are named constants inside the module that owns each of them, not config entries. That is on purpose; they are balance, not settings.
Who gets the tools
Config.Admin = {
aces = { 'vsvb.admin' }, -- ACE permissions
groups = { 'admin', 'superadmin' }, -- ESX / QBCore groups, if you run one
identifiers = {}, -- a hard list
resolve = nil, -- or your own function(src)
}
Per player, enforced on the server: the client gate only decides whether a menu opens, and every write (a saved court, a placed prop, an erased map object) is re-checked over the wire. There is no server-wide dev switch, and nothing has to be turned off for production. See Admin & commands.
Config.Debug = false -- console diagnostics only. It gates no tool and no overlay
Match rules
Config.Rules = {
pointsToWin = 15,
winBy = 2,
cap = 21, -- 0 = no cap
sets = 1, -- best-of = sets * 2 - 1
maxTouches = 3, -- 0 = unlimited / arcade
teamSizes = { 1, 2, 3 }, -- which formats are offered
serveSeconds = 15,
fillWithAI = true, -- fill empty seats with AI
stamina = true,
serveStamina = true, -- price the serve type against the bar
teammateAimAssist = true, -- looking at a team-mate locks the pass onto them
netAssist = false,
rematchSeconds = 20, -- the result screen's ceiling. 0 takes it out
}
Explained in full on Rules, stamina & AI.
fillWithAI = false is strict PvP, and it is the setting that most looks like a bug when it is not. A 3v3 court then needs six real players before anything starts, so "Join a match" appears to do nothing while you wait.
How players start a match
Config.RequireReferee = true
true means matches start only through a placed referee desk. false also allows /vb near a court.
true with no desk placed means nobody can start a match at all. Place one, or set this false while you are authoring a new location.
Training
Config.Training = {
enabled = true,
matchPoints = 5, -- the short bout at the end of a lesson
matchWinBy = 1,
matchCap = 0,
}
Courts, net and ball
Config.Net = {
model = 'wx_volleyball_net',
poles = 'wx_volleyball_poles',
headingOffset = 90.0, -- align the assembly to the court
zOffset = 1.732,
polesZOffset = 1.732,
}
Config.Courts = { floorHeadingOffset = 90.0, floorZOffset = 0.0, floors = { ... } }
Config.Ball = { model = 'prop_beach_volball02', radius = 0.11 }
The net and poles spawn together at every court and are switched off together by the creator's B. Which floor a court uses is stored per court. Config.Courts.floors holds one measured row per floor model, produced by /vb_mark. See Courts & the builder.
The ball model is cosmetic; no physics reads it. Its radius is the one non-cosmetic field; it is how far the ball rests above the sand and how far off the net it stops.
The rest, in one table
| Key | What it controls |
|---|---|
Config.Drinks | The three cans: which item names map to which effect, what each one does and for how long, and the cool box's prices. See Beach circle & drinks |
Config.Freeplay | The beach circle: spacing between neighbours, maxPlayers, invite radius and timeout, the ball prop, whether sprinting costs stamina |
Config.BallCarry | The ball carts: where they stand, the cart and ball models, the load in take order, refillSeconds, the item name, maxCarry |
Config.Teams | enabled, maxMembers, invite timeout, autoSide, partyEnabled, and imageHosts: empty means any https host may supply a banner |
Config.Spectate | Bounds on who sees a live match, a radius and a runaway guard, not a switch |
Config.Sfx | The audio bank, the mix, distances and which clip plays for what |
Config.Builder | The placement catalogue and objectLimit (150 per court) |
Config.Aids | Optional on-screen helpers. The incoming-ball arc is the one that is on as shipped; the reach rings and the diagnostics are off |
Config.CourtLines · Config.HideMinimap | Draw the court lines · hide the minimap during a match |
Config.Theme | NUI colours: the scoreboard, panels and meters all read them |
Sound
The resource ships its own audio bank (21 waves with a dat54), so hits, grunts, the net, the ball on sand and the crowd all go through the game's own mix with real 3D position and distance. The clips rows in Config.Sfx name waves inside that pack, not files on disk.
A name that is not in the pack is simply silent, with no error to catch it. /vb_sound (admin) plays every configured sound by name, printing each before it plays; that is how you check one. Adding a new sound means rebuilding the pack, not copying a file in.
Sound levels are baked into the pack. Config.Sfx.volume and Config.Sfx.mix record the balance the pack was built with; editing them does not change playback. Player volume is the SFX slider in GTA's own audio settings, which this script sits under like any other game sound.
What you can edit
The resource ships under Cfx asset escrow, and the files a buyer has to read or edit are left unencrypted on purpose:
config.lua | every setting on this page |
locales/*.json | translations |
inventory/ox_inventory_items.lua | the item rows you copy into ox_inventory |
install.sql | the schema, for a backup or a manual install |
README.md | the resource's own documentation |
Gameplay tuning that the client and the server both have to agree on, such as the physics, the shot bands and the contact timing, is deliberately not exposed: the two sides disagreeing about it is how a match desyncs.
Localisation
locales/en.json, read through the ox_lib locale system. Every player-facing string is in there: shot prompts, serve types, the referee menu, training, teams, the result screen. Copy the file to your language code rather than editing Lua.