Features
How every part of oxide-gangs works — creation, ranks, recruiting, the dashboard, treasury, bases, fleet, territory, the turf map, wars, capture objectives, and integrations.
Everything oxide-gangs does, explained from the server owner's side: what players see, what staff control, and which setting changes it.
Every setting named here is edited in game from /gangs settings — see Configuration for the full list.
How Gangs Get Created
There are two ways gangs come into existence, and you pick one with Config.Creation.creationMode.
| Mode | What happens |
|---|---|
request (default) | Players run /gangs request, fill in a form, and wait for staff to approve it |
admin_only | Only staff create gangs, from the admin panel or with /gangs create. /gangs request tells players requests are off |
The request flow
- A player runs
/gangs request. A form opens on screen. - They enter a display name (what everyone sees, e.g. "The Ballas"), optionally pick a gang colour, and answer whatever questions you have set up.
- They submit. The request is checked immediately — a player already in a gang, or one still inside their cooldown, is turned away with a clear message rather than filing a request staff would have to bin.
- Staff see the request in
/gangs admin→ Requests, or list them in chat with/gangs requests. - A staff member assigns the internal name (lowercase, e.g.
ballas— this is the name other scripts use) and approves. Approving with/gangs approve <id> <name>does the same thing. - The gang is created, the requester is seated at the highest boss rank, and any creation fee is taken from their bank account.
If the requester joined some other gang while the request was sitting there, approval fails safely and the request is closed as rejected instead.
Building the request form
The questions are yours. Config.RequestForm is a list of rows you edit in /gangs settings — add a row, give it an ID, a question, and a type:
| Type | What the player sees |
|---|---|
text | A single-line box (default limit 120 characters) |
textarea | A multi-line box (default limit 1000 characters) |
select | A dropdown of choices you list |
number | A number box |
toggle | A yes / no switch |
The display name is always asked and is not a row you have to add. One ID is special: motto — whatever the player types there becomes the gang's motto when the request is approved.
The form ships with five questions: motto, backstory, Discord name, expected starting members, and roleplay plans. Delete the ones you do not want.
If you half-edit a row (blank question, a dropdown with no choices, a duplicate ID) that single row is skipped and the rest of the form still works — a typo can never brick the form for your players.
Name rules
Internal gang names must be 3 to 40 characters, lowercase letters, numbers, and underscores only, starting with a letter. Names in Config.NameBlocklist are rejected — add any job names you want kept off-limits. A gang can never get at a job's money regardless of its name: gang bank accounts are created under a gang_ prefix, so they cannot collide with a job account.
Other limits: Config.Creation.maxGangs caps how many gangs can exist at once (0 = unlimited), maxMembersPerGang caps each gang's size, requestCooldownMins is how long a player waits between requests, and creationFee is charged from the requester's bank account on approval.
Ranks and Permissions
Every gang has its own ladder of ranks. New gangs start with the four ranks in shared/config/grades.lua:
| Rank | Name | Permissions it gets |
|---|---|---|
| 0 | Member | deposit, stash |
| 1 | Enforcer | deposit, stash, garage, invite |
| 2 | Underboss | deposit, stash, garage, invite, kick, promote, demote, withdraw, war, announce |
| 3 | Boss | everything (marked as a boss rank) |
That table is only the starting template. Once a gang exists, anyone with the manage ranks permission renames its ranks, changes what each one may do, and adds or removes ranks from the dashboard's Ranks tab. Staff can do the same from the admin panel.
The twelve permissions
| Permission | Lets a member... |
|---|---|
invite | Invite nearby players, and accept or reject applications |
kick | Remove members below their own rank |
promote | Raise a member's rank |
demote | Lower a member's rank |
manage_ranks | Edit the gang's rank ladder |
deposit | Put money into the treasury |
withdraw | Take money out of the treasury |
stash | Open the gang stash at the base |
garage | Take gang vehicles out and store them |
war | Declare wars, respond to declarations, offer and answer ceasefires |
announce | Reserved for gang announcements |
edit_gang | Change the gang's display name, colour, motto, and logo |
A rank marked is boss holds every permission automatically, regardless of what is ticked.
Rank safety rules
These are enforced by the server, not just hidden in the UI:
- Nobody can kick, promote, or demote themselves.
- A non-boss can only act on members below their own rank, and can never promote someone to their own rank or above.
- A boss can act on anyone but themselves.
- A rank editor can never grant themselves boss status from the dashboard — only staff can create a boss rank.
- A rank still held by members cannot be deleted.
- A gang must keep at least one boss rank.
- The last remaining boss cannot leave a gang that still has other members. They must promote another boss first, or disband. If they are the only member, leaving disbands the gang.
Joining a Gang
In-person invites
A member with the invite permission opens their dashboard's Roster tab, types the target's server ID, and clicks Invite. Both players must be within Config.Invites.inviteDistance of each other (10 metres by default).
The target gets a notification and has Config.Invites.expireSeconds (60 by default) to run /gangs accept or /gangs decline. After that the invite lapses. Invites are also dropped if the target disconnects.
Written applications
A player runs /gangs apply <gang> [message] — for example /gangs apply ballas I've been running with them for weeks. The application sits in the gang's dashboard under Members → Applications, where anyone with the invite permission accepts or rejects it. Accepted applicants join at rank 0.
A player can only have one pending application per gang at a time.
Leaving
/gangs leave, or the Leave button on the dashboard's Overview screen. The boss rules above apply.
The Gang Dashboard
Members open it with /gangs dashboard. /gangs wars opens the same panel on the Wars screen.
| Screen | What's on it |
|---|---|
| Overview | Member count, treasury balance, territories held, and war status at a glance; the gang identity editor (display name, colour, motto, logo) for anyone with edit_gang; the gang activity feed (boss ranks only); the Leave button |
| Members → Roster | Everyone in the gang with rank, join date, and who is online, plus invite / kick / rank controls |
| Members → Ranks | The rank editor (requires manage_ranks) |
| Members → Applications | Pending applications to review (requires invite) |
| Treasury | Balance, deposit and withdraw, and the transaction history |
| Garage | The gang's fleet with plate, condition, fuel, and status |
| Territory | A map of every active territory with owner, contest state, standings, and your gang's influence in each |
| Wars | Declare wars, answer incoming declarations, the live scoreboard, ceasefires, and war history |
| Wars → Leaderboard | Server-wide gang standings |
Every button re-checks permission on the server when it is pressed. Hiding a button in the UI is never the only thing stopping someone from using it.
Treasury
Every gang has one shared pot of money.
- Deposits move money out of the depositing member's bank account into the treasury. Needs the
depositpermission. - Withdrawals move it back to the member's bank. Needs the
withdrawpermission. - Staff funding adds or removes money without touching any player's account —
/gangs fund <gang> <amount>, or the admin panel. A negative amount removes. - Every movement is written to a transaction history with the amount, the resulting balance, a description, and who did it. The dashboard shows the most recent Config.Logs.transactionLogLimit entries.
Two safety rules matter:
- Overdrafts are impossible. A withdrawal that would take the balance below zero is rejected outright, and two members clicking withdraw at the same moment cannot both succeed.
- Failed money moves are undone. If money leaves a player's bank but the treasury update then fails, the money is put straight back.
Optional: real bank accounts
Set Config.Treasury.useBankingAccount to on and balances live in your banking resource instead, as an account named gang_<name> (for example gang_ballas). This only works if you run a banking resource o-link supports, such as oxide-banking. The gang_ prefix means a gang can never collide with a job account of the same name.
Config.Treasury.startBalance is the balance a newly created gang starts with.
Gang Bases
A base is placed by staff from /gangs admin → pick a gang → Base. Each gang can have exactly one.
A base is made of up to four things:
| Part | What it does |
|---|---|
| Base position | Where the base is. Anchors the blip |
| Stash point | Where members open the gang stash |
| Garage point | Where members take vehicles out and return them |
| Spawn bays | Where those vehicles physically appear. Add as many as you want |
Placing any of them uses an in-world picker: the panel hides, you aim at the spot with a crosshair, and you confirm. Stash and garage points also offer an Entity picker that snaps to whatever prop you are looking at (handy for putting a stash on an existing crate or locker). Spawn bays are placed with a ghost vehicle so you can see and set the exact heading a car will spawn at.
The blip
Gang members see a map blip on their own base and nobody else's. Turn it off globally with Config.Bases.blipsEnabled, or per base from the admin panel. Sprite, colour, and scale are configurable both globally and per base.
The stash
A shared inventory container at the stash point. Its size comes from Config.Stash.defaultSlots and Config.Stash.defaultMaxWeight, and can be overridden per base.
Opening it checks, on the server, that the player is in the gang, holds the stash permission, meets the stash's minimum rank, and is physically close enough. The stash requires an inventory resource o-link supports; without one, members are told the stash is unavailable instead of getting a silent failure.
Changing the stash size in /gangs settings re-registers every gang stash immediately — no restart needed.
Minimum ranks
A base can require a minimum rank overall. A member below the base's minimum rank does not even see the base blip.
Gang Vehicle Fleet
Fleet cars belong to the gang, not to a player. Staff add them from /gangs admin → pick a gang → Fleet, by entering a vehicle model (for example buccaneer), a display name, and a minimum rank.
Each vehicle gets its own unique 8-character plate, and remembers its modifications, fuel, body damage, and engine damage between sessions.
Taking one out
A member with the garage permission stands at the garage point, opens the garage menu, and picks a vehicle. It spawns in a free bay.
- One vehicle out per player at a time.
- A vehicle already out cannot be taken again.
- A member below the vehicle's minimum rank cannot take it.
- If every bay is occupied by the gang's own out vehicles (or reserved by a spawn in progress), the take-out is refused with "All garage bays are blocked."
Gang cars are spawned by the server and stay in the world after the player who took them out walks away, disconnects, or goes to the other side of the map. A car left in the street stays there until somebody returns it.
Returning one
Any member with the garage permission can return any gang vehicle they are standing next to or sitting in — not just the one they took out. The car's current mods, fuel, and damage are saved back, and the car is removed from the world.
By default a car must be returned near the base garage point (Config.Garage.storeRequiresAtBase). Turn that off to let members return gang cars from anywhere.
Config.Garage.maxFleetSize caps how many vehicles a gang can own.
If a car gets stranded
If a vehicle ends up stuck as "out" — the player crashed, the car fell through the map — staff use the Recover button in the admin panel's fleet list. It deletes whatever is left of the car and puts the row back to stored.
Gang cars do not survive a server restart. Any car still marked out when the server comes back up is returned to the garage automatically.
Territory
Territory is the long game. Influence is earned by doing things inside a zone, not by shooting people in it, and ownership changes hands over days of play rather than in one firefight.
Turn the whole system off with Config.Territory.enabled.
Where influence comes from
| Source | Setting | Earned when |
|---|---|---|
| Drug sales | Config.Territory.saleGainPerDollar | A gang member completes a drug sale inside the zone. Sale value × this number |
| Base activity | Config.Territory.baseActivityGain | A member opens the stash, or takes out / returns a vehicle, at a base that sits inside the zone |
| Presence | Config.Territory.presenceGainPerTick | A member is physically standing in the zone when the presence check runs (every presenceTickMinutes) |
| War kills | Config.Territory.killGain | A member lands a war kill inside the zone. Only during an active war |
| War captures | Config.Territory.captureGain | The gang captures a war objective inside the zone |
| External scripts | — | Another resource reports activity through the developer API (robberies, rackets, graffiti) |
The kill rule
Kills can never buy turf. Influence earned from kills during one war is capped at Config.Territory.killShareOfInfluence (25% by default) of the influence the gang has already earned in that zone through actual activity. A gang with no footprint in a district earns nothing there no matter how many people it kills. Kills amplify standing; they cannot replace it.
Anti-farm caps
Two limits run on every gain:
- Per gang, per zone, per hour, split by source —
Config.Territory.hourlyCaphas a separate number for sales, base activity, presence, war kills, war captures, and external scripts. Once a gang hits the hourly cap for a source in a zone, further gains from that source score nothing until the hour rolls over. - Per character — one character can only supply Config.Territory.charHourlyShare (50% by default) of each hourly cap. Farming a zone with alt accounts standing in a circle does not work.
Decay
Influence bleeds away constantly. Every (zone, gang) pairing loses Config.Territory.decayPerHour influence per hour, checked every decayTickMinutes.
The important part: decay scales with holdings. Each territory a gang owns beyond the first raises its decay rate by Config.Territory.decayPerHolding (35% by default). Holding two districts is comfortable. Holding eight bleeds faster than most gangs can top up. This is the rubber band that stops one gang quietly owning the map by week three.
How ownership changes
| Situation | What happens |
|---|---|
Zone is unowned, a gang crosses ownershipThreshold | It claims the zone immediately |
| Zone is owned, a rival's influence overtakes the owner's | A contest window opens for contestWindowHours real hours. Nothing changes yet |
| Contest window closes | Standings are compared. If the challenger is still ahead and above the threshold, the zone flips. Otherwise the owner keeps it |
| A contest just settled | No new contest can open on that zone for contestCooldownHours |
| Owner's influence decays to zero | The zone goes neutral |
Contest windows survive restarts — they settle on their real-time clock whether the server was up or not.
Config.Territory.maxInfluence is the hard ceiling on how much influence one gang can hold in one zone.
The shipped map
34 Los Santos districts ship pre-drawn: Textile City, Mission Row, Strawberry, Downtown, Pillbox Hill, Chamberlain Hills, Davis, Maze Bank Arena, Banning, Elysian Island, Rancho, Cypress Flats, Terminal, La Mesa, Murrieta Heights, Mirror Park, East Vinewood, Vinewood Racetrack, Vinewood, Alta, Hawick, Downtown Vinewood, West Vinewood, Burton, Rockford Hills, Little Seoul, Vespucci Canals, La Puerta, Los Santos International Airport, Vespucci Beach, Del Perro Beach, Del Perro, Morningwood, and Richman.
They are seeded once, the first time the resource starts against an empty territory table. After that the database is authoritative — the shipped map can never come back and overwrite your edits, and a district you delete stays deleted.
Reshape, rename, recolour, disable, or delete any of them from /gangs admin → Territories. You draw new zones either by clicking points on the in-panel map or by walking the outline in the world.
Zone modifiers
Each territory carries four multipliers that the Oxide drug resources read:
| Modifier | Affects |
|---|---|
| Production yield | How much product an operation produces in that zone |
| Growth rate | How fast plants grow in that zone |
| Sale price | What dealers pay in that zone |
| Buyer density | How many buyers turn up in that zone |
A value of 1 is neutral. 1.15 is +15%, 0.9 is −10%. Edit them per territory in the admin panel. Resources that do not know about gangs simply see a multiplier of 1 everywhere, so nothing breaks if you do not run them.
Territory blips
Every territory can carry a map blip named after its owner ("Downtown — The Ballas", or "Downtown — Unclaimed", with "(Contested)" appended while a contest is running). These are public — turf is common knowledge, not member-only intel. Master switch: Config.Territory.blipsEnabled. Sprite, colour, and scale are per territory, and blips are off by default on the shipped districts.
The Turf Map
Gang members see every territory as a translucent filled area on both the minimap and the pause map, coloured by whichever gang owns it. Unclaimed zones show in their own colour, dimmer.
Only gang members see it. A player with no gang sees nothing.
| Setting | Controls |
|---|---|
Config.Territory.turfMap.enabled | The whole overlay |
Config.Territory.turfMap.alpha | How solid owned zones look (0–255) |
Config.Territory.turfMap.unownedAlpha | How solid unclaimed zones look (0–255) |
This is drawn with a hidden browser page painted into a map texture and anchored using the stock GTA minimap file (MINIMAP_LOADER.gfx) that ships in the resource folder. Do not delete that file — see Installation → The Minimap File.
Gang Wars
A war is a scored, staked contest between two gangs on a real-hours clock. Turn the system off entirely with Config.Wars.enabled.
Declaring
From the dashboard's Wars screen, a member with the war permission picks a target gang and a stake — an amount of treasury money. The defender must match that stake to accept, and the winner takes the whole pot.
Rules checked at declaration:
- You cannot declare on your own gang.
- Your gang cannot already be at war, or already have an outgoing declaration (withdraw it first).
- The target cannot already be at war.
- The stake cannot exceed Config.Wars.maxStake (a stake of 0 is always allowed).
- Your treasury must currently cover the stake.
- The two gangs cannot have fought within Config.Wars.rematchCooldownHours.
An unanswered declaration lapses after Config.Wars.pendingExpiryHours.
Accepting
The defender accepts or rejects from their own Wars screen. On accept:
- The defender's stake is taken first — their click is the commitment.
- Then the attacker's. If the attacker has since spent the money, the defender is refunded in full and the declaration is cancelled.
- The war goes active and its end time is locked in at Config.Wars.durationHours from now. Changing that setting later only affects wars accepted afterwards.
- Both gangs are notified, and police may get an alert (see Police Alerts).
Scoring
| Action | Points | Setting |
|---|---|---|
| Validated kill | 1.0 per kill | Config.Wars.killScore |
| Objective capture | 5.0 to every member standing on the point | Config.Wars.captureScore |
Scores are tracked per member and shown on a live scoreboard, so bosses can see who actually turned up.
What makes a kill count
A kill only scores if all of this is true, checked on the server:
- Both killer and victim are in gangs, and those gangs are the two at war.
- The killer's gang has an active war.
- The two players are no more than Config.Wars.killMaxDistance apart (300 m by default). Set it to 0 to switch the check off.
- The killer has not already killed that same victim within Config.Wars.killRepeatCooldownSeconds (180 s by default). This is what stops two friends trading kills in an alley.
Duplicate death reports from the same player inside a few seconds are ignored.
Ending a war
| Ending | How it happens | Stakes |
|---|---|---|
| Clock | The war runs its full duration. Higher score wins | Winner takes the whole pot. Tie = draw |
| Draw | Clock runs out with equal scores | Both sides refunded |
| Ceasefire | One side offers, the other accepts | Both sides refunded |
| Disband | One gang disbands mid-war | The surviving gang wins and takes the pot |
| Staff force-end | An admin ends it from the panel | Settled as a draw, both stakes refunded |
A ceasefire scores nobody any points, so ending early to protect a record earns nothing on the leaderboard.
Wars settle on their stored clock even across a restart — the server catches up when it comes back.
Capture Objectives
While a war is running, king-of-the-hill capture points spawn inside the warring gangs' territory. Turn them off with Config.Wars.objectives.enabled.
How they work
- A point spawns Config.Wars.objectives.intervalMinutes after the war starts (or after the last point ended).
- It spawns inside territory owned by one of the two gangs, alternating sides. If a gang owns nothing, its highest-influence zone is used instead. If neither gang has any territorial footprint at all, the war simply runs on kills only.
- Both gangs get a notification and a flashing map blip. A circle marker appears on the ground.
- Standing inside the circle, with nobody from the other gang in it, fills a progress bar on screen. Both sides present freezes the bar and shows "CONTESTED". A change of holder resets it.
- Holding it uncontested for Config.Wars.objectives.holdSeconds captures the point. Every member standing on it scores.
- If nobody captures it within Config.Wars.objectives.durationMinutes, it disappears and the next one is scheduled.
| Setting | Default | Controls |
|---|---|---|
intervalMinutes | 20 | Time between points |
durationMinutes | 10 | How long an uncaptured point stays up |
radius | 25.0 | Size of the capture circle in metres |
holdSeconds | 60 | Uncontested hold needed to capture |
Leaderboard
A server-wide ranking of every gang, on the dashboard's Wars screen. Points are:
wins × 100 + draws × 25 + territories held × 50 + (total influence ÷ 10)Ties break on wins, then on territories held, then alphabetically. The table also shows each gang's win / loss / draw record and how many ceasefires it has agreed. It is recalculated at most once a minute.
Gang Radio Channels
If you run oxide-radio, every gang can get its own private channel. Nothing happens if oxide-radio is not installed.
| Setting | Controls |
|---|---|
Config.Radio.enabled | Whether gang channels exist at all |
Config.Radio.frequencyBase | A gang's channel number is this plus its gang ID. Default 900, so gang #1 is on 901 |
Config.Radio.minRank | The lowest gang rank allowed on the channel (0 = every member) |
Config.Radio.autoJoin | Tune members in automatically at login and when they join the gang |
Only members of that gang can tune in — the lock is enforced inside oxide-radio, not by hiding the number.
Pick a frequency base clear of your job channels. If another resource already holds a frequency a gang would land on, that gang's channel is skipped and a warning is written to your server console naming the clash. Restricted channels are allowed to sit outside oxide-radio's open dial range, so a base like 900 works fine even if your civilian dial stops earlier.
Auto-tune also needs auto-join switched on in oxide-radio's own settings.
Channels re-sync automatically when a gang is created, renamed, or disbanded, when you change the radio settings, and when oxide-radio itself restarts.
Police Alerts
Two separate alert groups, both optional, both off with a single toggle.
Territory alerts
Config.TerritoryDispatch
| Event | Default message |
|---|---|
| A territory becomes contested | "Reports of rising gang tension in <zone>" |
| A territory changes hands | "<zone> has been claimed by a new crew" |
War alerts
Config.WarDispatch
| Event | Default message |
|---|---|
| A war goes active | "Word on the street: <gang> and <gang> are at war" |
| A capture point spawns | "Armed gang activity reported in <zone>" |
War-start alerts are anchored on the defender's base. If the defending gang has no base, the alert is skipped rather than dropped at map coordinates 0,0.
For both groups you set which jobs receive the alert, the radio code, the priority, and the message text itself. Coordinates always come from the server — the zone centre, or the base — never from a player's game.
If you run oxide-dispatch, these become proper dispatch calls with a blip and a response list. With another dispatch resource, or none at all, the alert is relayed through an on-duty player of a receiving job instead. If nobody with a receiving job is online, the alert is quietly dropped.
Activity Logs
Everything that happens in a gang is written to its own activity log: members joining and leaving, rank changes, treasury movements, base and fleet changes, territory claims and contests, and the whole war lifecycle.
- Boss ranks see the activity feed on the dashboard Overview; other members do not see it.
- Staff see it per gang in the admin panel.
Config.Logs.retentionDays controls how long entries are kept (30 days by default; set 0 to keep forever). The cleanup runs at boot and then every six hours.
Working With Other Resources
All of these are optional. Nothing here needs configuring in oxide-gangs — install the other resource and it lights up.
| Resource | What you get |
|---|---|
| oxide-police | A Gang Intel tab in the MDT listing every gang with its member count, every territory with its owner, contest state, and influence standings, and every active and recent war with stakes, scores, and clocks. Officers never see treasury balances, mottos, or zone geometry |
| oxide-blackmarket | Selling to a black-market dealer standing on your own gang's turf multiplies the reputation earned. Those sales also feed territory influence, through the same capped channel street sales use. Black market tiers can also be unlocked per gang |
| oxide-drugselling | Street drug sales feed influence to the seller's gang in the zone where the sale happened, and the zone's sale price and buyer density modifiers apply |
| oxide-weed / oxide-meth / oxide-cocaine | Zone yield and growth modifiers apply to operations run inside a territory |
| oxide-dispatch | Territory and war alerts become full dispatch calls |
| oxide-radio | Private per-gang radio channels |
| oxide-banking | Gang treasuries held as real bank accounts |
Any other script can feed influence in and read gang and territory data out — see the API Reference.
Framework Behaviour
oxide-gangs keeps its own gang registry in the database and treats it as the single truth. What it does with your framework depends on which one you run.
| Framework | Behaviour |
|---|---|
QBCore (qb-core) | Every gang is pushed into QBCore.Shared.Gangs at boot, and each member's gang and rank is written into their player data. Scripts that read PlayerData.gang keep working with no changes |
QBX (qbx_core) | Same, through qbx_core's own gang API. The push is runtime-only, so nothing is written to your qbx_core files — the full set is re-pushed every boot |
ESX (es_extended) | ESX has no gang concept, so there is nothing to mirror into. This registry is the gang system, and any resource asking o-link about gangs is answered from it |
On every framework, the registry wins. When a player loads in, their gang is re-applied from the database — so a gang kick that happened while they were offline sticks, and a third-party script that changed their gang behind the resource's back is corrected on their next login.
Next Steps
- Installation — getting it running
- Configuration — every setting
- Admin — commands and the admin panel
- Exports — API reference for developers
- Troubleshooting — when something is not working