Game Modes
Four game modes, four config files. They share the same building blocks — a centre, a radius, a list of spawn points — so once you have placed one map you can place all of them.
| Mode | File | Shipped content | Dimension |
|---|---|---|---|
| FFA | config/ffa.lua | 16 maps | 5000 + map index |
| Lobbies | config/lobby.lua | 9 maps, 2 teams | per lobby |
| Arena modes | config/arena.lua | BF mode, Air Fight | 999 / 888 |
| Gungame | config/gungame.lua | 5 arenas, 25 levels | 6000 + map index |
Each mode also has a tab in the menu that can be switched off entirely with Config.Tabs in config.lua.
FFA
Free for all: everybody against everybody inside one zone. Config.FFA.maps is a plain list — one entry per map.
{
name = "rooftop_1",
label = "Rooftop",
image = "rooftop",
coords = vec3(339.4624, -41.4019, 153.2948),
radius = 50.0,
maxPlayers = 10,
spawnPoints = {
vector4(349.5204, -72.9325, 153.2951, 22.0677),
vector4(310.5954, -58.6632, 153.2977, 299.0320),
…
},
weapons = {
[`weapon_pistol50`] = {
`COMPONENT_PISTOL50_CLIP_02`
}
}
}
| Field | Type | Description |
|---|---|---|
name | string | Internal id. Must be unique across all maps |
label | string | Name shown in the menu |
image | string | File name in frontend/images/ffa/, without the extension |
coords | vec3 | Centre of the zone |
radius | number | Zone radius in metres. Leaving it ends the fight |
maxPlayers | number | Slots on this map |
spawnPoints | list of vector4 | Where players spawn; the fourth value is the heading |
weapons | table | Optional. Loadout for this map only |
Spawn points decide how a map plays. Give a map enough of them for its player count — the shipped maps run from 5 points at 10 players (Rooftop) up to 15 points at 15 players.
Per-map loadouts
Without a weapons table a map uses the global Config.Weapons from config.lua. With one, it uses exactly what is listed there.
That is how the shipped config builds variants of the same location: 5 of the 16 maps carry their own loadout, which is why the list has both Ölfelder and Ölfelder 50. — same coordinates, but the second one is restricted to the Pistol .50.
To build such a pair, copy the entry, give it a new name, change the label, and add or remove the weapons table.
Lobbies
Private matches: a player creates a lobby, others join, two teams fight several rounds inside a shrinking zone. Config.Lobby holds the rules, Config.Lobby.maps the locations.
Rules and limits
limits = {
minPerTeam = 1,
maxPerTeam = 10,
minRounds = 1,
maxRounds = 10,
passwordLen = 32,
},
scoreboard = {
delay = 2000,
duration = 5000,
gap = 1000,
maxRows = 5,
},
limits is the range a player can pick from when creating a lobby — team size, number of rounds, and the maximum length of the password. The scoreboard values control the board between rounds: delay before it appears, duration on screen, gap until the next round starts, maxRows players listed.
The zone
zone = {
shrinkInterval = 3000,
shrinkAmount = 3.0,
minRadius = 50.0,
orbitSpeed = 6.0,
orbitRadiusFactor = 0.35,
startPadding = 35.0,
damagePerTick = 5,
tickInterval = 1000,
blipColor = 1,
blipAlpha = 128,
},
| Option | Default | Description |
|---|---|---|
shrinkInterval | 3000 | Milliseconds between two shrink steps |
shrinkAmount | 3.0 | Metres the radius loses per step |
minRadius | 50.0 | The zone never gets smaller than this |
startPadding | 35.0 | Extra metres the zone starts with on top of the map radius |
orbitSpeed | 6.0 | How fast the zone centre drifts |
orbitRadiusFactor | 0.35 | How far it drifts, as a fraction of the map radius |
damagePerTick | 5 | Damage per tick outside the zone |
tickInterval | 1000 | Milliseconds between two damage ticks |
blipColor / blipAlpha | 1 / 128 | Colour and transparency of the zone on the map |
The pace of a match comes out of the first two values: 3.0 metres every 3 seconds is 60 metres per minute. Halve shrinkInterval for a faster round, raise minRadius if the endgame gets too cramped.
Spectating
spectate = {
keyPrev = 174, keyPrevLabel = "PFEIL LINKS",
keyNext = 175, keyNextLabel = "PFEIL RECHTS",
keyFreecam = 22, keyFreecamLabel = "LEERTASTE",
refresh = 1000,
},
Dead players spectate. The three keys are FiveM control ids, each with the label shown on screen next to it — change both together, otherwise the hint lies to your players. refresh is how often the spectator list updates, in milliseconds.
Weapons, teams and clothing
weapons = {
{
name = "weapon_pistol",
label = "Pistole",
components = { "COMPONENT_PISTOL_CLIP_02" }
},
…
},
colors = {
["blue"] = { 0, 0, 255 },
["red"] = { 255, 0, 0 },
},
weapons is what the lobby creator can choose from — the weapon, the label shown in the UI, and the attachments handed out with it. Pictures come from frontend/images/lobbys/weapons/.
colors defines the two teams as RGB triplets, used for blips, markers and the scoreboard.
clothing = {
enabled = true,
["blue"] = {
male = { ["torso_1"] = 47, ["tshirt_1"] = 15, ["pants_1"] = 5, … },
female = { ["torso_1"] = 608, ["pants_1"] = 231, … }
},
["red"] = { male = { … }, female = { … } },
},
Team outfits, keyed by team colour and gender. The keys are the ESX skin component names (torso_1, pants_1, helmet_1, …) with the drawable number as the value, and the _2 variants for the texture. Set enabled = false to let players keep their own clothes.
vehicles = {
{ name = "revolter", label = "Revolter" },
{ name = "schafter3", label = "Schafter" },
{ name = "komoda", label = "Komoda" },
},
The cars a lobby can be played with. Images come from frontend/images/lobbys/cars/.
Lobby maps
{
name = "mirrorpark",
label = "Mirrorpark",
image = "mirrorpark_lobby",
coords = vec3(1166.6749, -602.2207, 63.9432),
radius = 1000.0,
points = {
{ players = vec4(955.1973, -127.5772, 74.3719, 213.7775), garage = vec4(962.7661, -135.5553, 74.3968, 147.3366) },
{ players = vec4(1202.9913, -1305.4982, 35.2255, 358.0665), garage = vec4(1203.9659, -1288.2582, 35.2243, 262.9063) },
}
},
| Field | Description |
|---|---|
coords / radius | Centre and size of the playing field. The zone starts at radius + startPadding |
points | One entry per team. players is where that team spawns, garage where their vehicle is handed out |
All nine shipped maps have exactly two points, because a lobby is always two teams. Their radius runs from 30.0 (Würfelparkdach, a rooftop) up to 1000.0 (Mirrorpark, a whole district).
A map without vehicles simply parks the garage out of the way — Würfelparkdach uses vec4(0, 0, 0, 199.4724) for both points.
Arena modes
config/arena.lua holds the two fixed modes. Both share the same frame:
| Field | BF mode | Air Fight |
|---|---|---|
enabled | true | true |
label | BF Modus | Air Fight |
image | bfmode | airfight |
dimension | 999 | 888 |
maxPlayers | 30 | 30 |
radius | 200.0 | 400.0 |
center | vec3(1358.78, 3128.79, 40.97) | vec3(263.93, 6484.48, 30.67) |
description is the text on the card in the Arena tab, image a file in frontend/images/modes/.
BF mode
bfMode = {
vehicle = "bf400",
spawnPoints = {
vec4(1545.0197, 3082.7642, 40.6412, 107.0504),
… 17 points in a ring around the centre
}
}
A motorcycle deathmatch — everybody spawns on a bf400, and going down off the bike is what kills you. The 17 spawn points form a ring around the centre so nobody starts in the middle. vehicle takes any model name.
Air Fight
airFight = {
dropOffset = 10.0,
dropSpread = 15.0,
}
A parachute drop: the fight starts in the air. Air Fight has no spawnPoints — players are placed above center instead.
| Option | Default | Description |
|---|---|---|
dropOffset | 10.0 | Height above the centre where players are released |
dropSpread | 15.0 | How far they are spread horizontally, so nobody drops onto somebody else |
Gungame
Everybody starts on level 1, a kill moves you up a level and hands you the next weapon, and whoever clears the last level wins the round.
Config.Gungame.enabled = true
Config.Gungame.baseDimension = 6000
Config.Gungame.roundTime = 15 * 60
Config.Gungame.spawnProtection = 1000
Config.Gungame.resultTime = 8
Config.Gungame.freezeOnEnd = true
| Option | Default | Description |
|---|---|---|
enabled | true | Master switch for the whole mode |
baseDimension | 6000 | Routing bucket base, plus the map index |
roundTime | 15 * 60 | Round length in seconds — written as minutes × 60 for readability |
spawnProtection | 1000 | Spawn protection after a respawn, in milliseconds |
resultTime | 8 | Seconds the result screen stays up before the next round |
freezeOnEnd | true | Freezes players while the result is shown |
Arenas
Config.Gungame.maps = {
{ ffaMap = 7, maxPlayers = 20 }, -- Oelfelder
{ ffaMap = 8, maxPlayers = 20 }, -- Alienberg
{ ffaMap = 9, maxPlayers = 15 }, -- Hafen
{ ffaMap = 12, maxPlayers = 15 }, -- Skaterpark
{ ffaMap = 14, maxPlayers = 20 }, -- Windpark
}
Gungame does not define its own maps — it reuses the FFA ones. ffaMap is the position in Config.FFA.maps, counted from 1, so ffaMap = 7 is the seventh entry in ffa.lua.
This is the one place where two config files depend on each other. If you insert or remove an FFA map above index 14, every number below it shifts and Gungame silently starts on the wrong map. Add new FFA maps at the end of the list, or re-check these five numbers afterwards.
maxPlayers overrides the player limit of the FFA map for the Gungame round.
Levels
Config.Gungame.levels = {
{ name = "WEAPON_CARBINERIFLE", label = "Carbine Rifle" },
{ name = "WEAPON_SPECIALCARBINE", label = "Special Carbine" },
…
{ name = "WEAPON_KNIFE", label = "Messer" },
}
The ladder, in order: rifles first, then MGs, SMGs, shotguns, pistols, snipers, and the knife as the final level. 25 levels ship by default.
name is the weapon, label the text shown in the level-up message. Add, remove or reorder entries freely — the number of levels is simply the length of this list, and clearing the last entry wins the round.
Gungame text
Config.Gungame.locales = {
joined = "Du bist dem Gungame auf %s beigetreten",
levelUp = "Level %s von %s - %s",
roundWinner = "Gungame vorbei: %s gewinnt mit Level %s",
…
}
Gungame keeps its strings here instead of in Config.Translations. An English set:
Config.Gungame.locales = {
joined = "You joined the Gungame on %s",
left = "You left the Gungame",
levelUp = "Level %s of %s - %s",
roundWinner = "Gungame over: %s wins on level %s",
roundNobody = "Gungame over: nobody got a kill",
roundNew = "New round - everyone back to level 1",
finished = "%s cleared all %s levels and wins",
full = "This Gungame arena is full",
disabled = "The Gungame is currently disabled",
}
Mind the placeholders: levelUp takes three (current level, total, weapon), roundWinner and finished take two.
Adding a map
The same four steps for every mode:
- Fly to the spot and write down the centre as
vec3and the spawn points asvector4— the fourth value is the heading the player faces. - Copy an existing entry in the matching config file and replace
name,label,coords,radiusandspawnPoints. - Drop a picture into the folder for that mode —
frontend/images/ffa/for FFA,frontend/images/lobbys/for lobbies — and put the file name without the extension intoimage. - Restart the resource and check the zone in game.
Config.Debug = truehelps while you align the radius.