QBESXStandalone
Agency-Gangs Configuration
The complete gang system for FiveM in one script.
v1.0.0Paid5 Pages

01Configuration
Quick Installation · config.lua · Agency-Gangs
--[[
╔══════════════════════════════════════════════════════════════════════╗
║ AGENCY GANGS - CONFIGURATION ║
║ (c) Agency Scripts ║
╚══════════════════════════════════════════════════════════════════════╝
CONTENTS
1. Core Framework, language, permissions, commands
2. Gangs & Ranks Creation, colours, emblems, ranks, permissions
3. Money Gang bank, dirty money, laundering
4. Levels & Upgrades XP, levels, what upgrades cost and do
5. Hideout Stash, garage, outfits, gang shop, boss menu
6. Territories Capture rules, income, racketeering, presets
7. Turf Wars Scheduled city wide wars with a live scoreboard
8. Gang Wars One gang against another, with a wager
9. Graffiti Spray can, spray remover, influence
10. Corner Selling Selling to locals, protection money
11. Missions Contracts that earn XP and money
12. Street Tools Zip ties, head bag, escort, search
13. Police & Logs Dispatch alerts, Discord webhooks
14. Apps & Scripts Agency Phone, Pad, Housing, Blackmarket
Server owners only need to touch this file. Texts players see live in
locales/ (copy _template.lua for a new language).
]]
Config = {}
--==============================================================================
-- 1 · CORE
--==============================================================================
-- 'auto' finds QBCore (qb-core), QBox (qbx_core) or ESX (es_extended) by
-- itself and runs standalone when none of them is installed.
-- 'qbcore' | 'esx' | 'standalone' force one of them.
Config.Framework = 'auto'
-- Language file from locales/. 25 languages ship with the script.
Config.Locale = 'en'
-- Extra console output for support cases. Keep false on a live server.
Config.Debug = false
-- Heading on every notification.
Config.NotifyTitle = 'Gangs'
-- Notifications. 'auto' picks the first one that is running:
-- Agency-Notify > ox_lib > QBCore / ESX > GTA notification.
-- 'agency' | 'ox' | 'qbcore' | 'esx' | 'native' force one of them.
-- Agency-Notify, matching design: https://agencyscripts.dev/en/product/notify
Config.Notify = 'auto'
-- Progress bar. 'auto' picks the first one that is running:
-- Agency-Progressbar > ox_lib > the bar built into this script.
-- 'agency' | 'ox' | 'builtin' force one of them.
-- Agency-Progressbar, matching design: https://agencyscripts.dev/en/product/progressbar
Config.Progressbar = 'auto'
-- Accent colour of every menu, HUD and app. Gold is the Agency default.
-- Any hex colour works, e.g. '#3d8bfd' for blue or '#e04646' for red.
Config.AccentColor = '#e2b649'
-- Who counts as an admin for /agangs. ACE 'agency.gangs' always works too.
Config.AdminGroups = { 'admin', 'god', 'superadmin' }
Config.Commands = {
menu = 'gang', -- opens the gang menu
admin = 'agangs', -- opens the admin panel
corner = 'corner', -- starts / stops corner selling
}
-- Key for the gang menu (players can change it in GTA settings > Key Bindings > FiveM).
-- Set to false to only use the command.
Config.MenuKey = 'F6'
-- Players may open the gang menu anywhere. false = only at the hideout's boss point.
Config.MenuAnywhere = true
-- Money shown in the UI. Symbol and position only, no conversion.
Config.Currency = { symbol = '$', position = 'before' }
-- Standalone servers (no framework): money and admin hooks. Leave as nil to
-- run gang money purely inside the gang bank (deposits disabled).
Config.Standalone = {
-- getMoney = function(src, account) return 0 end,
-- removeMoney = function(src, account, amount) return true end,
-- addMoney = function(src, account, amount) return true end,
admins = {}, -- 'license:xxxx' entries
}
--==============================================================================
-- 2 · GANGS & RANKS
--==============================================================================
Config.Gangs = {
-- Players may found their own gang from the gang menu.
playerCreation = {
enabled = true,
price = 50000, -- paid by the founder
account = 'bank', -- 'cash' | 'bank'
item = 'gang_contract',-- also needs this item (consumed). false = no item
minMembersToKeep = 0, -- 0 = gangs are never removed for being small
},
nameMin = 3, nameMax = 24, -- display name length
tagMax = 5, -- short tag shown on graffiti and above heads
mottoMax = 80,
maxRanks = 12,
baseMembers = 12, -- member slots before the "members" upgrade
-- Colours a gang can pick. Hex only.
colors = {
'#e2b649', '#e04646', '#35d6a6', '#3d8bfd', '#a855f7', '#f97316',
'#ec4899', '#22c55e', '#eab308', '#14b8a6', '#f5f5f5', '#64748b',
},
-- Emblems drawn by the UI (no image files needed).
emblems = { 'crown', 'skull', 'star', 'flame', 'diamond', 'bolt', 'spade', 'eye', 'snake', 'rose', 'dragon', 'wolf' },
-- Ranks every new gang starts with. Grade 0 is the lowest. The highest
-- grade is the leader and always has every permission.
defaultRanks = {
{ name = 'Prospect', perms = {} },
{ name = 'Soldier', perms = { 'stash', 'garage', 'bank_deposit', 'shop' } },
{ name = 'Lieutenant', perms = { 'stash', 'garage', 'bank_deposit', 'shop', 'invite', 'missions', 'wardrobe', 'launder' } },
{ name = 'Underboss', perms = { 'stash', 'garage', 'bank_deposit', 'bank_withdraw', 'shop', 'invite', 'kick', 'promote', 'missions', 'wardrobe', 'launder', 'dirty', 'logs', 'war' } },
{ name = 'Boss', perms = {} },
},
-- Keep QBCore / QBox PlayerData.gang in sync, so every other script that
-- checks gangs (doors, garages, jobs) sees Agency Gangs.
syncFramework = true,
-- Import from the admin panel (/agangs > Import), members included. Found
-- by themselves: qb-core / qbx gangs, Agency Pad gangs and families, and
-- the tables of other gang scripts in your database.
allowImport = true,
-- ESX has no gangs; servers that ran them as jobs list those jobs here.
importJobs = { 'ballas', 'vagos', 'families', 'grove', 'marabunta', 'lost', 'aztecas', 'bloods', 'crips', 'triads', 'cartel', 'mafia', 'yakuza', 'bratva' },
}
-- Every permission a rank can hold. Order = order in the rank editor.
Config.Permissions = {
'invite', 'kick', 'promote', 'ranks', 'settings',
'bank_deposit', 'bank_withdraw', 'dirty', 'launder',
'stash', 'garage', 'wardrobe', 'shop',
'upgrades', 'war', 'relations', 'missions', 'logs',
}
--==============================================================================
-- 3 · MONEY
--==============================================================================
Config.Bank = {
account = 'cash', -- player account used for deposits and withdrawals
minAmount = 1,
maxHistory = 150, -- transactions kept per gang
}
-- Dirty money. 'item' = an inventory item counted 1 per dollar (black_money).
-- 'account' = an ESX style account (black_money). false switches it off.
Config.DirtyMoney = {
enabled = true,
type = 'item', -- 'item' | 'account'
name = 'black_money',
}
-- Laundering at the hideout's laundry point: dirty from the gang vault in,
-- clean into the gang bank out, minus the fee.
Config.Laundering = {
enabled = true,
fee = 0.30, -- 30 %, lowered by the "laundering" upgrade
dailyLimit = 250000, -- per gang and real day
}
--==============================================================================
-- 4 · LEVELS & UPGRADES
--==============================================================================
-- XP needed for each level. Level 1 is where every gang starts.
Config.Levels = { 0, 1000, 2500, 5000, 9000, 15000, 24000, 36000, 52000, 75000 }
-- What gives XP.
Config.XP = {
capture = 250, -- territory taken
holdIncome = 20, -- every income tick per territory held
turfWarWin = 1000,
gangWarWin = 600,
kill = 10, -- killing a rival member during a war
graffiti = 15,
cornerSale = 2,
mission = 150,
racket = 25,
}
-- Upgrades bought from the gang bank. Each level needs the gang level shown.
Config.Upgrades = {
stash = {
label = 'Stash', icon = 'box',
levels = {
{ price = 0, level = 1, slots = 50, weight = 250000 },
{ price = 25000, level = 2, slots = 70, weight = 400000 },
{ price = 60000, level = 4, slots = 90, weight = 600000 },
{ price = 120000, level = 6, slots = 120, weight = 1000000 },
},
},
members = {
label = 'Members', icon = 'users',
levels = {
{ price = 0, level = 1, bonus = 0 },
{ price = 30000, level = 2, bonus = 6 },
{ price = 80000, level = 5, bonus = 14 },
{ price = 150000, level = 8, bonus = 28 },
},
},
income = {
label = 'Territory income', icon = 'coins',
levels = {
{ price = 0, level = 1, bonus = 0.0 },
{ price = 40000, level = 3, bonus = 0.15 },
{ price = 90000, level = 5, bonus = 0.30 },
{ price = 180000, level = 8, bonus = 0.50 },
},
},
capture = {
label = 'Capture speed', icon = 'flag',
levels = {
{ price = 0, level = 1, bonus = 0.0 },
{ price = 35000, level = 3, bonus = 0.10 },
{ price = 85000, level = 6, bonus = 0.20 },
},
},
garage = {
label = 'Garage', icon = 'car',
levels = {
{ price = 0, level = 1, slots = 2 },
{ price = 30000, level = 2, slots = 4 },
{ price = 75000, level = 5, slots = 7 },
},
},
laundering = {
label = 'Laundering', icon = 'wash',
levels = {
{ price = 0, level = 1, fee = 0.30 },
{ price = 50000, level = 3, fee = 0.22 },
{ price = 120000, level = 6, fee = 0.15 },
},
},
territories = {
label = 'Territory limit', icon = 'map',
levels = {
{ price = 0, level = 1, max = 2 },
{ price = 45000, level = 3, max = 4 },
{ price = 110000, level = 6, max = 7 },
},
},
}
--==============================================================================
-- 5 · HIDEOUT
--==============================================================================
-- Points are placed per gang in game (/agangs > gang > Hideout, or by the
-- leader when allowLeaderPlacement is on).
Config.Hideout = {
allowLeaderPlacement = false,
maxDistanceFromFirst = 150.0, -- all points of one hideout stay this close together
interactDistance = 2.0,
drawDistance = 12.0,
marker = { type = 21, size = 0.35, bob = true }, -- used when no target script runs
useTarget = true, -- ox_target / qb-target when running
blip = { enabled = true, sprite = 84, scale = 0.75, label = 'Hideout' },
}
-- Stash. Size comes from the "stash" upgrade.
Config.Stash = {
id = function(gangName) return 'gang_' .. gangName end,
-- Override with your own opener: function(gangName, stashId, slots, weight) end
open = nil,
}
-- Gang garage. Two things live at the garage point of the hideout:
-- 1. the gang fleet below: shared cars in the gang colour with a gang plate
-- 2. the garage script of your server, where members park their OWN cars
Config.Garage = {
-- Which garage script handles the members' own cars at the gang garage.
-- 'auto' the first one that is started: Agency-Garage, jg-advancedgarages
-- 'agency' Agency-Garage
-- 'jg' jg-advancedgarages (v3 garage API, older versions by event)
-- 'custom' the function in `custom` below (qb-garages, cd_garage, ...)
-- 'none' only the gang fleet
script = 'auto',
-- Resource names, for a server that renamed a folder.
resources = { agency = 'Agency-Garage', jg = 'jg-advancedgarages' },
-- For script = 'custom'. Runs on the client when a member opens the garage.
custom = {
open = function(gangName, garageId, point)
-- e.g. TriggerEvent('my-garage:open', garageId, vector4(point.x, point.y, point.z, point.w))
end,
},
platePrefix = 'GNG', -- plate = prefix + 5 random characters
vehicles = {
{ model = 'baller', label = 'Baller', level = 1, grade = 0 },
{ model = 'gburrito', label = 'Gang Burrito', level = 1, grade = 1 },
{ model = 'manchez', label = 'Manchez', level = 1, grade = 0 },
{ model = 'buccaneer2', label = 'Buccaneer', level = 2, grade = 1 },
{ model = 'chino2', label = 'Chino Custom', level = 3, grade = 2 },
{ model = 'schafter3',label = 'Schafter V12', level = 4, grade = 2 },
{ model = 'kuruma', label = 'Kuruma', level = 6, grade = 3 },
},
-- Called after a vehicle spawns, e.g. to hand out keys. Runs on the client.
giveKeys = function(vehicle, plate)
if GetResourceState('Agency-Vehiclekeys') == 'started' then
TriggerServerEvent('agency-vehiclekeys:server:compat', plate)
elseif GetResourceState('qb-vehiclekeys') == 'started' or GetResourceState('qbx_vehiclekeys') == 'started' then
TriggerEvent('vehiclekeys:client:SetOwner', plate)
elseif GetResourceState('wasabi_carlock') == 'started' then
exports.wasabi_carlock:GiveKey(plate)
elseif GetResourceState('qs-vehiclekeys') == 'started' then
exports['qs-vehiclekeys']:GiveKeys(plate, GetDisplayNameFromVehicleModel(GetEntityModel(vehicle)), true)
end
end,
-- Called right after spawning, for fuel scripts. Runs on the client.
setFuel = function(vehicle)
if GetResourceState('LegacyFuel') == 'started' then
exports['LegacyFuel']:SetFuel(vehicle, 100.0)
elseif GetResourceState('ox_fuel') == 'started' then
Entity(vehicle).state.fuel = 100.0
else
SetVehicleFuelLevel(vehicle, 100.0)
end
end,
}
-- Gang shop at the hideout, paid from the gang bank.
Config.Shop = {
enabled = true,
items = {
{ item = 'spraycan', label = 'Spray Can', price = 250, level = 1, grade = 0 },
{ item = 'spray_remover', label = 'Spray Remover', price = 150, level = 1, grade = 0 },
{ item = 'zipties', label = 'Zip Ties', price = 400, level = 2, grade = 1 },
{ item = 'head_bag', label = 'Head Bag', price = 600, level = 3, grade = 1 },
{ item = 'lockpick', label = 'Lockpick', price = 300, level = 1, grade = 0 },
{ item = 'armor', label = 'Body Armor', price = 1500, level = 2, grade = 1 },
{ item = 'weapon_bat', label = 'Baseball Bat', price = 800, level = 1, grade = 0 },
{ item = 'weapon_knife', label = 'Knife', price = 1200, level = 2, grade = 1 },
{ item = 'weapon_pistol', label = 'Pistol', price = 12000,level = 5, grade = 2 },
},
}
--==============================================================================
-- 6 · TERRITORIES
--==============================================================================
Config.Territories = {
enabled = true,
tick = 5, -- seconds between server checks
captureTime = 240, -- seconds of presence to take a territory
minMembers = 2, -- attackers needed inside at once
decay = 2.0, -- progress lost per second while nobody attacks
contestedPauses = true, -- defenders inside pause the capture
cooldown = 45, -- minutes a fresh capture is safe from attacks
heightRange = 60.0, -- metres above / below the centre that still count
countDead = false, -- dead or downed players do not count
onlyDuringTurfWar = false, -- true = territories can only change hands in a turf war
minPolice = 0, -- police on duty needed for captures
alertOwner = true, -- tell the owning gang when someone moves in
incomeInterval = 30, -- minutes between payouts
incomeNeedsOnline = true, -- pay only gangs with at least one member online (stops AFK farming)
-- Linked territories: a preset with linked = { 'grove' } can only be taken
-- by a gang that already holds one of the listed territories.
-- Racketeering: shops inside a territory that the owning gang collects from.
racket = { enabled = true, cooldown = 120, distance = 2.5 }, -- minutes per shop
-- Map: 'all' = everyone sees territories, 'members' = only gang members,
-- 'none' = no blips at all.
blips = 'all',
blipAlpha = 90,
-- Preset territories, created on the first start. Change them in game
-- afterwards (/agangs > Territories). Radius in metres, income per payout.
presets = {
{ name = 'grove', label = 'Grove Street', coords = vec3(-118.0, -1585.0, 33.0), radius = 150.0, income = 2500,
racket = { vec3(-47.6, -1757.5, 29.4) } },
{ name = 'chamberlain', label = 'Chamberlain Hills', coords = vec3(-170.0, -1650.0, 33.0), radius = 120.0, income = 2000,
linked = { 'grove', 'davis' } },
{ name = 'davis', label = 'Davis', coords = vec3(110.0, -1940.0, 20.8), radius = 140.0, income = 2500,
racket = { vec3(25.7, -1347.3, 29.5) } },
{ name = 'rancho', label = 'Rancho', coords = vec3(425.0, -1850.0, 27.5), radius = 150.0, income = 2500 },
{ name = 'cypress', label = 'Cypress Flats', coords = vec3(830.0, -2150.0, 29.6), radius = 170.0, income = 3000 },
{ name = 'elburro', label = 'El Burro Heights', coords = vec3(1310.0, -1680.0, 52.0), radius = 150.0, income = 2000 },
{ name = 'mirror', label = 'Mirror Park', coords = vec3(1160.0, -560.0, 64.0), radius = 160.0, income = 3500,
racket = { vec3(1163.4, -323.8, 69.2) } },
{ name = 'vespucci', label = 'Vespucci Canals', coords = vec3(-1050.0, -1030.0, 2.1), radius = 150.0, income = 3000 },
{ name = 'sandy', label = 'Sandy Shores', coords = vec3(1800.0, 3740.0, 33.6), radius = 220.0, income = 2500,
racket = { vec3(1961.5, 3740.7, 32.3) } },
{ name = 'paleto', label = 'Paleto Bay', coords = vec3(-200.0, 6300.0, 31.5), radius = 220.0, income = 2500 },
},
}
--==============================================================================
-- 7 · TURF WARS (scheduled)
--==============================================================================
-- City wide turf wars at fixed times. While one runs, every territory can be
-- taken, every capture and rival kill scores, and a live scoreboard shows
-- the standings. The top gangs get paid when it ends.
Config.TurfWars = {
enabled = true,
-- Server time. day: 1 = Sunday ... 7 = Saturday.
schedule = {
{ day = 6, hour = 20, minute = 0, duration = 60 }, -- Friday 20:00
{ day = 7, hour = 20, minute = 0, duration = 60 }, -- Saturday 20:00
},
announceBefore = { 30, 10, 1 }, -- minutes before the start
points = { capture = 25, kill = 3, holdPerMinute = 1 },
rewards = {
{ money = 75000, xp = 1000 }, -- 1st
{ money = 40000, xp = 600 }, -- 2nd
{ money = 20000, xp = 300 }, -- 3rd
},
-- During a turf war captures go faster.
captureTimeMultiplier = 0.75,
}
--==============================================================================
-- 8 · GANG WARS (gang against gang)
--==============================================================================
Config.Wars = {
enabled = true,
mustAccept = true, -- the other gang has to accept
prepareMinutes = 10, -- time between acceptance and the first shot
duration = 45, -- minutes
minWager = 0, maxWager = 500000,
fee = 0.10, -- the city keeps 10 % of the pot
cooldown = 120, -- minutes before the same two gangs can fight again
points = { kill = 1, capture = 5 },
expireRequest = 15, -- minutes before an unanswered declaration lapses
}
-- Alliances: allies never contest each other's territories.
Config.Relations = { enabled = true, maxAllies = 2 }
--==============================================================================
-- 9 · GRAFFITI
--==============================================================================
Config.Graffiti = {
enabled = true,
item = 'spraycan',
removerItem = 'spray_remover',
consumeSpray = true, -- one spray can per tag
consumeRemover = true,
sprayTime = 7000, -- ms
removeTime = 9000,
maxPerGang = 40,
minDistance = 6.0, -- metres between two tags
lifetimeDays = 7, -- tags fade after this long (0 = forever)
drawDistance = 35.0,
-- Players write their own text (prefilled with the gang tag). false = always the tag.
customText = true,
maxLength = 12,
-- Words that are refused anywhere in a tag, lower case.
blockedWords = { 'nigger', 'nigga', 'faggot', 'hitler', 'nazi', 'kkk' },
-- Styles players can pick: block letters, script, bubble.
styles = { 'block', 'script', 'bubble' },
-- Widths in metres for small, medium and large.
sizes = { s = 1.4, m = 2.2, l = 3.2 },
-- Each own tag in a territory speeds up captures there, rival tags slow
-- them down. Capped at maxBonus.
captureBonus = 0.06, maxBonus = 0.30,
-- Jobs that may remove any tag without being in a gang.
cleanerJobs = { 'police', 'sheriff' },
}
--==============================================================================
-- 10 · CORNER SELLING
--==============================================================================
Config.Corners = {
enabled = true,
territoryOnly = true, -- only inside territories
minPolice = 0,
pedInterval = { 12, 25 }, -- seconds between buyers walking up
cooldown = 6, -- seconds between two sales
payout = 'cash', -- 'cash' | 'dirty'
ownTurfBonus = 0.15, -- +15 % in your own territory
protectionTax = 0.20, -- 20 % of a sale in a rival territory goes to its owner
rejectChance = 0.18, -- buyer walks away
alertChance = 0.12, -- buyer calls the police
drugs = {
{ item = 'weed_brick', label = 'Weed', min = 1, max = 3, price = { 140, 220 } },
{ item = 'weed_baggy', label = 'Weed', min = 1, max = 5, price = { 40, 70 } },
{ item = 'coke_baggy', label = 'Cocaine', min = 1, max = 3, price = { 90, 150 } },
{ item = 'crack_baggy', label = 'Crack', min = 1, max = 3, price = { 70, 120 } },
{ item = 'meth', label = 'Meth', min = 1, max = 2, price = { 120, 200 } },
{ item = 'oxy', label = 'Oxy', min = 1, max = 3, price = { 60, 110 } },
},
}
--==============================================================================
-- 11 · MISSIONS
--==============================================================================
Config.Missions = {
enabled = true,
cooldown = 30, -- minutes per gang between two missions
timeLimit = 20, -- minutes to finish
types = {
delivery = {
label = 'Package Run', reward = { 6000, 9000 }, xp = 150, grade = 1,
pickups = { vec4(1240.5, -3168.3, 7.1, 270.0), vec4(-1146.1, -2002.0, 13.2, 315.0), vec4(717.8, -962.9, 30.4, 180.0) },
drops = { vec4(-1153.4, -1517.7, 4.4, 30.0), vec4(1391.3, 3606.2, 35.0, 200.0), vec4(-415.5, 6067.2, 31.5, 315.0), vec4(166.5, -1290.6, 29.3, 240.0) },
prop = 'prop_cs_cardbox_01',
},
vehicle = {
label = 'Boost a Car', reward = { 8000, 12000 }, xp = 200, grade = 1,
models = { 'sultan', 'jester', 'comet2', 'buffalo2', 'felon' },
spawns = { vec4(-338.6, -754.8, 33.9, 270.0), vec4(-1654.8, -1027.4, 13.0, 50.0), vec4(259.1, -1158.4, 29.2, 90.0), vec4(-799.2, 307.2, 85.7, 180.0) },
drops = { vec4(479.8, -1317.1, 29.2, 290.0), vec4(-196.6, -1307.7, 31.1, 90.0) },
alertChance = 0.5,
},
tagging = {
label = 'Tag the Block', reward = { 4000, 6000 }, xp = 120, grade = 0,
tags = 3, -- graffiti to spray in a rival or free territory
},
},
}
--==============================================================================
-- 12 · STREET TOOLS
--==============================================================================
Config.Restrain = {
enabled = true,
gangOnly = true, -- only gang members may use them
ziptieItem = 'zipties',
headBagItem = 'head_bag',
consumeZipties = true,
freeItems = { 'weapon_knife', 'weapon_switchblade', 'weapon_dagger' }, -- cut someone free
-- Victims must have their hands up or be downed.
needHandsUp = true,
allowSearch = true, -- open the victim's inventory
distance = 2.0,
}
-- Small gang tag above members of your own gang and allies.
Config.Overhead = { enabled = true, distance = 18.0 }
-- Supply drops: a crate falls somewhere in a territory, every gang sees it on
-- the map, the first gang to crack it open takes the money and the loot.
Config.Airdrops = {
enabled = true,
interval = { 60, 120 }, -- minutes between two drops
minGangsOnline = 2, -- gangs with someone online needed for a drop
openTime = 20000, -- ms to crack the crate
alertPolice = true,
money = { 8000, 20000 }, -- into the gang bank
xp = 200,
loot = { -- each line rolls on its own
{ item = 'weapon_pistol', count = 1, chance = 0.25 },
{ item = 'pistol_ammo', count = 2, chance = 0.6 },
{ item = 'armor', count = 2, chance = 0.5 },
{ item = 'spraycan', count = 3, chance = 0.7 },
{ item = 'zipties', count = 2, chance = 0.4 },
},
}
-- Gang chat in the menu and in the app.
Config.Chat = { enabled = true, keep = 60, maxLength = 240 }
--==============================================================================
-- 13 · POLICE & LOGS
--==============================================================================
Config.Police = {
jobs = { 'police', 'sheriff', 'state' },
-- 'auto' picks ps-dispatch, cd_dispatch, tk_dispatch, qs-dispatch, core_dispatch
-- or falls back to a blip for every officer on duty.
dispatch = 'auto',
-- Police raids: officers break into a gang's hideout stash and seize part
-- of the dirty money vault. /raid next to the stash point.
raids = {
enabled = true,
command = 'raid',
minOfficers = 3, -- officers on duty, and this many within 30 m
breachTime = 45000, -- ms
seize = 0.35, -- 35 % of the vault
cooldown = 24, -- hours per gang
hours = { from = 16, to = 2 }, -- server time window (wraps past midnight)
},
}
-- Discord webhooks. Leave empty to disable. One URL can serve every category.
Config.Webhooks = {
default = '',
gangs = '', -- created, deleted, renamed, leader changes
members = '', -- invites, kicks, promotions
bank = '', -- deposits, withdrawals, laundering
territory = '', -- captures and losses
wars = '', -- turf wars and gang wars
admin = '', -- every admin action
}
--==============================================================================
-- 14 · APPS & SCRIPTS
--==============================================================================
Config.Integrations = {
-- The Gangs app on Agency Phone and Agency Pad. Shows up by itself.
phone = true,
pad = true,
-- Gang house: a gang picks one of its members' houses, every member then
-- gets access to it.
housing = {
-- 'auto' Agency Housing when it runs
-- 'agency' Agency Housing
-- 'custom' your housing script, through the three functions below
-- false no gang house
script = 'auto',
resource = 'Agency-Housing',
-- For script = 'custom'. All three run on the server. Your housing
-- script asks exports['Agency-Gangs']:HasHouseAccess(houseId, identifier)
-- to let gang members in.
custom = {
-- Houses owned by this character: { { id = 1, name = 'Grove St 4', x = 0.0, y = 0.0, z = 0.0 } }
housesOf = function(identifier) return {} end,
-- One house: { id = 1, name = 'Grove St 4', owner = 'identifier' } or nil
getHouse = function(houseId) return nil end,
-- The members of a gang house changed, refresh your access cache.
refresh = function(houseId) end,
},
},
-- Agency Blackmarket: gang members get a discount per gang level and can
-- pay from the gang bank (permission 'bank_withdraw').
blackmarket = { enabled = true, discountPerLevel = 0.01, maxDiscount = 0.10 },
}
02SQL File
Optional: the resource creates these tables on its own when it starts. Import this file only if you set up the database by hand:
-- Agency Gangs: the script creates these tables by itself on the first start.
-- Run this file only if your database user may not create tables.
CREATE TABLE IF NOT EXISTS `agency_gangs` (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
`label` VARCHAR(64) NOT NULL,
`leader` VARCHAR(64) NULL,
`bank` BIGINT NOT NULL DEFAULT 0,
`dirty` BIGINT NOT NULL DEFAULT 0,
`xp` INT NOT NULL DEFAULT 0,
`data` LONGTEXT NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `agency_gang_members` (
`identifier` VARCHAR(64) NOT NULL,
`gang_id` INT NOT NULL,
`grade` INT NOT NULL DEFAULT 0,
`name` VARCHAR(100) NULL,
`joined_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`last_seen` TIMESTAMP NULL DEFAULT NULL,
PRIMARY KEY (`identifier`),
KEY `gang_id` (`gang_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `agency_gang_logs` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`gang_id` INT NOT NULL,
`category` VARCHAR(20) NOT NULL,
`actor` VARCHAR(100) NULL,
`message` VARCHAR(255) NOT NULL,
`amount` BIGINT NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `gang_id` (`gang_id`, `id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `agency_gang_territories` (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
`label` VARCHAR(64) NOT NULL,
`x` DOUBLE NOT NULL, `y` DOUBLE NOT NULL, `z` DOUBLE NOT NULL,
`radius` DOUBLE NOT NULL DEFAULT 150,
`income` INT NOT NULL DEFAULT 0,
`owner` INT NULL DEFAULT NULL,
`captured_at` INT NULL DEFAULT NULL,
`data` LONGTEXT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `agency_gang_graffiti` (
`id` INT NOT NULL AUTO_INCREMENT,
`gang_id` INT NOT NULL,
`x` DOUBLE NOT NULL, `y` DOUBLE NOT NULL, `z` DOUBLE NOT NULL,
`nx` DOUBLE NOT NULL, `ny` DOUBLE NOT NULL, `nz` DOUBLE NOT NULL,
`territory` INT NULL DEFAULT NULL,
`created_at` INT NOT NULL,
`text` VARCHAR(24) NULL,
`style` VARCHAR(12) NULL,
`size` VARCHAR(2) NULL,
PRIMARY KEY (`id`),
KEY `gang_id` (`gang_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `agency_gang_wars` (
`id` INT NOT NULL AUTO_INCREMENT,
`kind` VARCHAR(10) NOT NULL,
`attacker` INT NULL, `defender` INT NULL,
`wager` BIGINT NOT NULL DEFAULT 0,
`status` VARCHAR(12) NOT NULL,
`started` INT NULL, `ends` INT NULL,
`winner` INT NULL,
`data` LONGTEXT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- ESX only: the new items (QBCore / QBox get them automatically, ox_inventory see README).
-- INSERT IGNORE INTO `items` (`name`, `label`, `weight`) VALUES
-- ('spraycan', 'Spray Can', 1), ('spray_remover', 'Spray Remover', 1), ('zipties', 'Zip Ties', 1),
-- ('head_bag', 'Head Bag', 1), ('gang_contract', 'Gang Contract', 1);