Agency-Shops Configuration
Every 24/7, LTD, Rob's Liquor, hardware store, Ammu-Nation and gas station on the map in one script for FiveM.

01Configuration
Quick Installation · config.lua · Agency-Shops
--[[
╔══════════════════════════════════════════════════════════════════════╗
║ AGENCY SHOP - CONFIGURATION ║
║ (c) Agency Scripts ║
╚══════════════════════════════════════════════════════════════════════╝
CONTENTS
1. Core Framework, inventory, language, money, debug
2. Interaction Prompt or target, keys, distances, peds, holo markers,
office computer, security cameras
3. Payment Cash, bank, card fee, weapon licences, Agency Pay
4. Store Types Blips, cashier ped, purchase price per type
5. Catalogs What each store type sells
6. Stores Every store on the map and its mode
7. Realism Mode Basket, trolley, shelves, checkout, items in the basket
8. Ownership Buying stores, prices, staff, register, selling to players
9. Deliveries Wholesale orders, NPC drivers or player couriers
10. Gas Stations Pumps, fuel types, moving prices, nozzle, hose, sounds
11. Fuel System Built-in fuel use, or the fuel script you run
12. Admin & Editor Who may edit stores and place shelves
13. Standalone Money and items without a framework
14. Robbery Holding up the cashier, the safe, the police
Discord webhook addresses go into config_server.lua, which is never
sent to players.
]]
Config = {}
--==============================================================================
-- 1 · CORE
--==============================================================================
-- ── Framework ────────────────────────────────────────────────────────────────
-- 'auto' = detect Qbox, QBCore or ESX (no framework found = standalone)
-- 'qb' / 'qbx' = force QBCore / Qbox
-- 'esx' = force ESX
-- 'standalone' = no framework, see 13 · STANDALONE
Config.Framework = 'auto'
-- ── Inventory ────────────────────────────────────────────────────────────────
-- 'auto' = ox_inventory, then qs-inventory, then the framework's own
-- (qb-inventory, ps, lj, jpr and other QB forks, ESX)
-- 'ox' / 'qs' / 'framework' = force one
Config.Inventory = 'auto'
-- Where the item pictures come from. 'auto' reads them from the inventory
-- that runs. A folder link works too: 'nui://my-inventory/html/images/'
-- false = no pictures, the store shows the first letter instead.
Config.Images = 'auto'
-- ── Language ─────────────────────────────────────────────────────────────────
-- 'en' 'de' 'fr' 'es' 'it' 'nl' 'pl' 'pt' 'cs' 'ro' 'ru' 'sv' 'tr' 'da'
-- 'fi' 'el' 'hu' 'hr' 'bg' 'uk' 'ar' 'hi' 'ja' 'ko' 'zh'
Config.Locale = 'en'
-- Your own wording, kept across updates. Any key from locales/en.lua:
-- Config.Text = { notify_title = 'Corner Shop', ui_pay = 'Checkout' }
Config.Text = {}
-- ── Money ────────────────────────────────────────────────────────────────────
Config.Currency = '$' -- shown in front of every price
Config.CurrencyAfter = false -- true = 12.50 € instead of $12.50
-- ── Database ─────────────────────────────────────────────────────────────────
-- Creates the tables from install/agency_shop.sql on start. Leave on.
Config.AutoApplySql = true
-- ── Debug ────────────────────────────────────────────────────────────────────
-- Prints shelf detection, zones and framework checks to the consoles.
-- Meant for support cases, keep false when live.
Config.Debug = false
--==============================================================================
-- 2 · INTERACTION
--==============================================================================
-- Keys use FiveM key names: 'E', 'G', 'F1', 'BACK' ...
-- https://docs.fivem.net/docs/game-references/input-mapper-parameter-ids/keyboard/
-- Players can rebind them under Settings > Key Bindings > FiveM.
-- 'prompt' = the Agency key card at the bottom of the screen
-- 'target' = ox_target or qb-target (falls back to the prompt if none runs)
-- 'auto' = target when ox_target or qb-target runs, else the prompt
-- With target: cashiers, counters without a cashier, shelves, the basket
-- stand, pumps and the depot are all targets. Holding the nozzle stays on
-- the key (text above the fuel cap).
Config.Interaction = 'prompt'
Config.Keys = {
Interact = 'E', -- open a store, take from a shelf, refuel
Secondary = 'G', -- second choice on a prompt (trolley, put back)
Cancel = 'BACK', -- stop refuelling, drop a crate
}
Config.Distance = {
Counter = 2.0, -- metres to the cashier to open the store
Shelf = 1.6, -- metres to a shelf in realism mode
Pump = 2.4, -- metres to a pump
Vehicle = 4.5, -- a vehicle this close to the pump can be filled
}
-- A small floating triangle in shops: at the counter, every shelf and the
-- basket stand, so players see where something can be done. Not at pumps.
Config.Markers = {
Enabled = true,
Type = 2, -- GTA marker type (2 = triangle pointing down, 1 = ring on the floor)
Size = vector3(0.14, 0.14, 0.11),
Height = 0.45, -- metres above the floor
Bob = true, -- floats gently up and down
BobTime = 3.5, -- seconds for one up and down
BobHeight = 0.03, -- metres it moves
Rotate = true, -- turns slowly
Color = { 226, 182, 73, 190 }, -- r, g, b, alpha (the gold of the Agency UI)
Distance = 12.0, -- shown within this many metres
}
-- The owner's panel opens at the computer in the back office. The computer
-- is found by model; for stores without one (custom stores) place an
-- "Office computer" point with /ashops (Points). With neither, the panel
-- stays on the counter.
Config.Office = {
Enabled = true,
Distance = 1.6, -- metres to the computer
MarkerColor = { 220, 55, 55, 200 }, -- the triangle in front of it (owners and staff only)
Models = {
'prop_monitor_01a', 'prop_monitor_01b', 'prop_monitor_01c', 'prop_monitor_01d',
'prop_monitor_02', 'prop_monitor_03b', 'prop_monitor_04a', 'prop_monitor_li',
'prop_monitor_w_large', 'prop_pc_01a', 'prop_pc_02a', 'prop_laptop_01a',
'v_res_monitorwidelarge', 'v_corp_cd_monitor', 'prop_dyn_pc', 'prop_dyn_pc_02',
},
}
-- Security cameras: the "Cameras" tab in the owner's panel shows the store
-- live, the same way as Agency-Housing. The cameras hanging in the store
-- (Models) are used; a store can also list its own spots in 6 · STORES
-- (cameras = { vector4(x, y, z, heading), ... }). With neither, two views
-- are worked out from the counter.
Config.Cameras = {
Enabled = true,
Models = {
'prop_cctv_cam_01a', 'prop_cctv_cam_01b', 'prop_cctv_cam_02a', 'prop_cctv_cam_03a',
'prop_cctv_cam_04a', 'prop_cctv_cam_04b', 'prop_cctv_cam_04c', 'prop_cctv_cam_05a',
'prop_cctv_cam_06a', 'prop_cctv_cam_07a', 'prop_cs_cctv', 'p_cctv_s',
'hei_prop_bank_cctv_01', 'hei_prop_bank_cctv_02', 'v_serv_securitycam_03', 'v_serv_securitycam_1a',
},
Fov = 62.0,
PanSpeed = 0.45, -- degrees per frame with A / D
Filter = 'scanline_cam_cheap', -- the camera look; false = none
Strength = 1.0,
Sound = { name = 'Change_Cam', set = 'MP_CCTV_SOUNDSET', ms = 450 }, -- switching; false = none
PanSound = { name = 'Pan', set = 'MP_CCTV_SOUNDSET' }, -- panning; false = none
}
-- Store cashiers. false on a store type = no ped, only the prompt.
Config.Peds = {
Enabled = true,
Scenario = 'WORLD_HUMAN_STAND_IMPATIENT', -- what the cashier does while waiting
Invincible = true,
SpawnDistance = 60.0, -- peds exist only near players
}
-- Use Agency-Notify when it runs, otherwise the store's own toast.
Config.UseAgencyNotify = true
--==============================================================================
-- 3 · PAYMENT
--==============================================================================
Config.Payment = {
Cash = true, -- pay with cash
Bank = true, -- pay by card from the bank account
CardFee = 0, -- percent added to card payments (0 = none)
}
-- ── Licenses ─────────────────────────────────────────────────────────────────
-- Store types that check a license before they sell. 'weapon' is the weapon
-- license: QBCore/Qbox metadata.licences.weapon, ESX esx_license ('weapon').
-- Standalone servers have no licenses, so nothing is checked there.
Config.Licenses = {
Enabled = true, -- false = no license needed anywhere
StoreTypes = {
ammunation = 'weapon', -- Ammu-Nation: weapon license
},
-- Items anyone may buy in those stores, with or without a license.
-- Everything else there needs the license (guns, ammunition ...).
Ignore = {
'weapon_flashlight', 'weapon_knife', 'weapon_bat', 'weapon_crowbar', 'weapon_hatchet',
'parachute', 'armor', 'armour',
},
}
-- ── Agency Pay ───────────────────────────────────────────────────────────────
-- Pay with Agency Pay from Agency Phone: the phone opens its checkout, the
-- player confirms there, the money comes from the bank account. Offered on
-- its own as soon as agency-phone runs. Nothing else to set up.
Config.AgencyPay = {
Enabled = true,
Resource = 'agency-phone', -- the phone's resource name
Timeout = 90, -- seconds to confirm on the phone
}
--==============================================================================
-- 4 · STORE TYPES
--==============================================================================
-- One entry per kind of store. Every store in 6 · STORES names one of these.
-- label : the name players see
-- catalog : which list in 5 · CATALOGS it sells
-- blip : map icon, false = none
-- ped : cashier model, false = no cashier
-- price : what the store costs to buy (8 · OWNERSHIP), false = not for sale
-- mode : 'ui' or 'realism' for every store of this type (see 6 · STORES).
-- A single store can still override it with its own mode.
Config.StoreTypes = {
['247'] = {
label = '24/7 Supermarket',
mode = 'ui',
catalog = 'convenience',
blip = { sprite = 52, color = 2, scale = 0.7 },
ped = 'mp_m_shopkeep_01',
price = 185000,
},
['ltd'] = {
label = 'LTD Gasoline',
mode = 'ui',
catalog = 'gas_shop',
blip = { sprite = 52, color = 5, scale = 0.7 },
ped = 'mp_m_shopkeep_01',
price = 165000,
},
['liquor'] = {
label = "Rob's Liquor",
mode = 'ui',
catalog = 'liquor',
blip = { sprite = 93, color = 46, scale = 0.7 },
ped = 'mp_m_shopkeep_01',
price = 140000,
},
['hardware'] = {
label = 'Hardware Store',
mode = 'ui',
catalog = 'hardware',
blip = { sprite = 52, color = 47, scale = 0.7 },
ped = 's_m_m_autoshop_01',
price = 160000,
},
['ammunation'] = {
label = 'Ammu-Nation',
mode = 'ui',
catalog = 'ammunation',
blip = { sprite = 110, color = 1, scale = 0.7 },
ped = 's_m_y_ammucity_01',
price = 350000,
},
}
--==============================================================================
-- 5 · CATALOGS
--==============================================================================
-- What a store sells, sorted into categories.
-- name : item name in your inventory
-- price : base price (owners can move it inside 8 · OWNERSHIP limits)
-- ox : optional, the item's name on ox_inventory if it differs
-- label : optional, otherwise the inventory's label is used
--
-- Items your inventory does not know are hidden automatically and named once
-- in the server console, so a list can hold QBCore, ESX and ox names at once.
-- Category icons: food, drink, snack, alcohol, tobacco, health, tech, tools,
-- car, misc.
Config.Catalogs = {
['convenience'] = {
{ id = 'food', icon = 'food', items = {
{ name = 'sandwich', price = 6 },
{ name = 'tosti', price = 5 },
{ name = 'burger', price = 8 },
{ name = 'bread', price = 3 },
}},
{ id = 'snacks', icon = 'snack', items = {
{ name = 'twerks_candy', price = 3 },
{ name = 'snikkel_candy', price = 3 },
}},
{ id = 'drinks', icon = 'drink', items = {
{ name = 'water_bottle', price = 2 },
{ name = 'water', price = 2 },
{ name = 'kurkakola', price = 3 },
{ name = 'cola', price = 3 },
{ name = 'sprunk', price = 3 },
{ name = 'coffee', price = 4 },
}},
{ id = 'health', icon = 'health', items = {
{ name = 'bandage', price = 45 },
{ name = 'painkillers', price = 80 },
{ name = 'firstaid', price = 220 },
}},
{ id = 'misc', icon = 'misc', items = {
{ name = 'lighter', price = 4 },
{ name = 'rolling_paper', price = 2 },
{ name = 'phone', price = 650 },
{ name = 'radio', price = 250 },
{ name = 'binoculars', price = 90 },
}},
},
['gas_shop'] = {
{ id = 'food', icon = 'food', items = {
{ name = 'sandwich', price = 7 },
{ name = 'burger', price = 9 },
{ name = 'twerks_candy', price = 3 },
{ name = 'snikkel_candy', price = 3 },
}},
{ id = 'drinks', icon = 'drink', items = {
{ name = 'water_bottle', price = 3 },
{ name = 'water', price = 3 },
{ name = 'kurkakola', price = 4 },
{ name = 'cola', price = 4 },
{ name = 'coffee', price = 5 },
}},
{ id = 'car', icon = 'car', items = {
{ name = 'weapon_petrolcan', price = 120, ox = 'WEAPON_PETROLCAN' },
{ name = 'repairkit', price = 280 },
{ name = 'cleaningkit', price = 60 },
}},
{ id = 'misc', icon = 'misc', items = {
{ name = 'lighter', price = 4 },
{ name = 'bandage', price = 50 },
}},
},
['hardware'] = {
{ id = 'tools', icon = 'tools', items = {
{ name = 'screwdriverset', price = 350 },
{ name = 'lockpick', price = 200 },
{ name = 'weapon_wrench', price = 250, ox = 'WEAPON_WRENCH' },
{ name = 'weapon_hammer', price = 250, ox = 'WEAPON_HAMMER' },
{ name = 'drill', price = 1200 },
}},
{ id = 'car', icon = 'car', items = {
{ name = 'repairkit', price = 250 },
{ name = 'advancedrepairkit', price = 500 },
{ name = 'cleaningkit', price = 150 },
{ name = 'weapon_petrolcan', price = 120, ox = 'WEAPON_PETROLCAN' },
}},
{ id = 'tech', icon = 'tech', items = {
{ name = 'phone', price = 850 },
{ name = 'radio', price = 250 },
{ name = 'fitbit', price = 400 },
{ name = 'binoculars', price = 50 },
}},
{ id = 'fireworks', icon = 'star', items = {
{ name = 'firework1', price = 50 },
{ name = 'firework2', price = 50 },
{ name = 'firework3', price = 50 },
{ name = 'firework4', price = 50 },
}},
},
['ammunation'] = {
{ id = 'pistols', icon = 'star', items = {
{ name = 'weapon_snspistol', price = 1800, ox = 'WEAPON_SNSPISTOL' },
{ name = 'weapon_pistol', price = 2500, ox = 'WEAPON_PISTOL' },
{ name = 'weapon_vintagepistol', price = 3200, ox = 'WEAPON_VINTAGEPISTOL' },
{ name = 'weapon_combatpistol', price = 3500, ox = 'WEAPON_COMBATPISTOL' },
{ name = 'weapon_heavypistol', price = 4500, ox = 'WEAPON_HEAVYPISTOL' },
{ name = 'weapon_pistol50', price = 5000, ox = 'WEAPON_PISTOL50' },
}},
{ id = 'melee', icon = 'tools', items = {
{ name = 'weapon_flashlight', price = 150, ox = 'WEAPON_FLASHLIGHT' },
{ name = 'weapon_knife', price = 300, ox = 'WEAPON_KNIFE' },
{ name = 'weapon_bat', price = 250, ox = 'WEAPON_BAT' },
{ name = 'weapon_crowbar', price = 300, ox = 'WEAPON_CROWBAR' },
{ name = 'weapon_hatchet', price = 400, ox = 'WEAPON_HATCHET' },
}},
{ id = 'ammo', icon = 'box', items = {
{ name = 'pistol_ammo', price = 60 },
{ name = 'smg_ammo', price = 80 },
{ name = 'shotgun_ammo', price = 90 },
{ name = 'rifle_ammo', price = 110 },
{ name = 'ammo-9', price = 4 },
{ name = 'ammo-45', price = 5 },
{ name = 'ammo-shotgun', price = 6 },
}},
{ id = 'protection', icon = 'health', items = {
{ name = 'armor', price = 1200 },
{ name = 'armour', price = 1200 },
{ name = 'parachute', price = 500 },
}},
},
['liquor'] = {
{ id = 'alcohol', icon = 'alcohol', items = {
{ name = 'beer', price = 7 },
{ name = 'whiskey', price = 22 },
{ name = 'vodka', price = 20 },
}},
{ id = 'drinks', icon = 'drink', items = {
{ name = 'water_bottle', price = 2 },
{ name = 'kurkakola', price = 3 },
}},
{ id = 'tobacco', icon = 'tobacco', items = {
{ name = 'lighter', price = 4 },
{ name = 'rolling_paper', price = 2 },
}},
{ id = 'snacks', icon = 'snack', items = {
{ name = 'twerks_candy', price = 3 },
{ name = 'snikkel_candy', price = 3 },
}},
},
}
--==============================================================================
-- 6 · STORES
--==============================================================================
-- 'ui' = walk to the counter and buy from a menu
-- 'realism' = take a basket or trolley, pick items from the shelves, pay at the
-- counter. Needs shelves: found automatically in the vanilla
-- interiors (7 · REALISM MODE) or placed with /ashops (Points).
-- Which one a store uses, first match wins:
-- 1. mode on the store below 2. mode on its type (4 · STORE TYPES)
-- 3. Config.DefaultMode
-- Gas stations choose their own mode, see Config.GasStations.Mode.
Config.DefaultMode = 'ui'
-- One line per store.
-- id : unique, never change it once players own the store
-- type : a key from 4 · STORE TYPES
-- cashier : where the cashier stands and the way he faces (toward the customer)
-- mode : optional, overrides Config.DefaultMode for this store
-- radius : optional, size of the store in metres (realism mode, default 14)
-- label : optional, own name instead of the type's
-- price : optional, own purchase price instead of the type's
-- delivery : optional, where couriers carry the crates (default: the counter)
Config.Stores = {
-- 24/7
{ id = '247_innocence', type = '247', cashier = vector4(24.47, -1346.62, 29.50, 270.0), mode = 'realism' },
{ id = '247_chumash', type = '247', cashier = vector4(-3040.47, 585.30, 7.90, 17.0) },
{ id = '247_banham', type = '247', cashier = vector4(-3243.97, 1000.72, 12.83, 357.0) },
{ id = '247_paleto', type = '247', cashier = vector4(1727.23, 6416.47, 35.04, 241.0) },
{ id = '247_sandy', type = '247', cashier = vector4(1959.42, 3740.07, 32.34, 297.0) },
{ id = '247_harmony', type = '247', cashier = vector4(548.41, 2670.85, 42.16, 99.0) },
{ id = '247_tataviam', type = '247', cashier = vector4(2677.47, 3280.63, 55.24, 327.0) },
{ id = '247_vinewood', type = '247', cashier = vector4(372.63, 326.42, 103.57, 253.0) },
{ id = '247_palomino', type = '247', cashier = vector4(2556.66, 380.84, 108.62, 356.67) },
-- LTD Gasoline
{ id = 'ltd_davis', type = 'ltd', cashier = vector4(-46.53, -1757.52, 29.42, 48.0) },
{ id = 'ltd_mirror', type = 'ltd', cashier = vector4(1165.03, -322.55, 69.21, 100.0) },
{ id = 'ltd_littleseoul', type = 'ltd', cashier = vector4(-706.13, -913.10, 19.22, 88.0) },
{ id = 'ltd_richman', type = 'ltd', cashier = vector4(-1819.34, 794.06, 138.09, 126.0) },
{ id = 'ltd_grapeseed', type = 'ltd', cashier = vector4(1697.20, 4923.58, 42.06, 323.0) },
-- Liquor
{ id = 'liquor_murrieta', type = 'liquor', cashier = vector4(1135.81, -982.28, 46.41, 278.0) },
{ id = 'liquor_vespucci', type = 'liquor', cashier = vector4(-1222.92, -905.31, 12.33, 30.0) },
{ id = 'liquor_morningwood', type = 'liquor', cashier = vector4(-1486.26, -377.87, 40.16, 139.0) },
{ id = 'liquor_route68', type = 'liquor', cashier = vector4(1165.98, 2710.86, 38.16, 180.0) },
{ id = 'liquor_sandy', type = 'liquor', cashier = vector4(1392.56, 3604.68, 34.98, 202.0) },
{ id = 'liquor_banham', type = 'liquor', cashier = vector4(-2966.42, 391.42, 15.04, 87.0) },
-- Hardware
{ id = 'hardware_megamall', type = 'hardware', cashier = vector4(45.68, -1749.04, 29.61, 53.13) },
{ id = 'hardware_youtool', type = 'hardware', cashier = vector4(2747.71, 3472.85, 55.67, 255.08) },
{ id = 'hardware_paleto', type = 'hardware', cashier = vector4(-421.83, 6136.13, 31.88, 228.2) },
-- Ammu-Nation
{ id = 'ammu_pillbox', type = 'ammunation', cashier = vector4(23.00, -1105.67, 29.80, 162.91) },
{ id = 'ammu_hawick', type = 'ammunation', cashier = vector4(253.63, -51.02, 69.94, 72.91) },
{ id = 'ammu_littleseoul', type = 'ammunation', cashier = vector4(-660.92, -934.10, 21.83, 177.66) },
{ id = 'ammu_morningwood', type = 'ammunation', cashier = vector4(-1304.45, -394.69, 36.70, 74.0) },
{ id = 'ammu_chumash', type = 'ammunation', cashier = vector4(-3172.49, 1088.75, 20.84, 244.0) },
{ id = 'ammu_lamesa', type = 'ammunation', cashier = vector4(841.92, -1035.32, 28.19, 1.56) },
{ id = 'ammu_cypress', type = 'ammunation', cashier = vector4(809.68, -2159.13, 29.62, 1.43) },
{ id = 'ammu_tataviam', type = 'ammunation', cashier = vector4(2567.48, 292.59, 108.73, 349.68) },
{ id = 'ammu_route68', type = 'ammunation', cashier = vector4(-1118.59, 2700.05, 18.55, 221.89) },
{ id = 'ammu_sandy', type = 'ammunation', cashier = vector4(1692.67, 3761.38, 34.71, 227.65) },
{ id = 'ammu_paleto', type = 'ammunation', cashier = vector4(-331.23, 6085.37, 31.45, 228.02) },
}
--==============================================================================
-- 7 · REALISM MODE
--==============================================================================
Config.Realism = {
-- What the player carries. The first model that exists in the game is used.
-- A model can be a name (uses the bone/pos/rot/anim below it) or a table
-- with its own placement, because every model sits differently in the hand.
-- capacity : how many pieces fit in
-- bone/pos/rot : where it sits on the ped
-- anim : played while carrying (dict, name), false = none
--
-- GTA itself has no shopping basket, only shopping bags. The basket below
-- is bzzz_prop_shop_basket from the free bzzz props that come with
-- rpemotes: if your server runs rpemotes, players carry a real basket,
-- otherwise the shopping bag. Any other streamed basket works the same way:
-- add it on top of the list with its own placement.
-- The basket hangs beside the right leg from a relaxed arm (the jerry can
-- carry). bone = 0 is the ped's root: x = right, y = forward, z = up,
-- so the numbers mean what they say. Fine-tune it in game: /ashops >
-- Stores > Adjust basket, or /shopfit basket. That is saved for everyone.
Containers = {
basket = {
models = {
{ model = 'bzzz_prop_shop_basket_a', bone = 57005, -- right hand, by the handle
pos = vector3(0.51, -0.07, -0.03), rot = vector3(-48.0, -36.0, 80.0),
anim = { dict = 'move_weapon@jerrycan@generic', name = 'idle' } },
{ model = 'bzzz_prop_shop_basket_b', bone = 57005, -- right hand, by the handle
pos = vector3(0.51, -0.07, -0.03), rot = vector3(-48.0, -36.0, 80.0),
anim = { dict = 'move_weapon@jerrycan@generic', name = 'idle' } },
'prop_cs_shopping_bag',
},
capacity = 15,
-- What is taken from the shelves shows up in the basket: up to
-- cols x rows x layers pieces, each as a small prop (ItemProps).
fill = { cols = 3, rows = 2, layers = 2, inset = 0.08, floor = 0.05, layerHeight = 0.08 },
bone = 57005,
pos = vector3(0.42, 0.0, -0.02),
rot = vector3(-90.0, 0.0, 80.0),
anim = false,
},
trolley = {
models = { 'prop_rub_trolley01a', 'prop_rub_trolley02a', 'prop_rub_trolley03a' },
capacity = 60,
bone = 11816, -- pelvis, the trolley rolls in front
pos = vector3(0.0, 1.05, -0.45),
rot = vector3(0.0, 0.0, 180.0),
anim = { dict = 'anim@heists@box_carry@', name = 'idle' },
slowWalk = true, -- no sprinting with a trolley
},
},
-- Without an entrance point the first shelf hands out a basket on its own.
-- Trolleys are only at entrance points (placed with /ashops (Points)..
AutoBasket = true,
-- The prop shown in the basket for an item. Items not listed get 'default'.
-- A model that does not exist on the server falls back to 'default' too.
ItemProps = {
default = 'prop_cs_package_01',
sandwich = 'prop_sandwich_01',
tosti = 'prop_sandwich_01',
burger = 'prop_cs_burger_01',
bread = 'v_res_fa_bread03',
twerks_candy = 'prop_choc_ego',
snikkel_candy = 'prop_choc_meto',
water_bottle = 'prop_ld_flow_bottle',
water = 'prop_ld_flow_bottle',
kurkakola = 'prop_ecola_can',
cola = 'prop_ecola_can',
sprunk = 'ng_proc_sodacan_01b',
coffee = 'p_amb_coffeecup_01',
beer = 'prop_cs_beer_bot_01',
whiskey = 'prop_cs_whiskey_bottle',
vodka = 'prop_vodka_bottle',
bandage = 'prop_ld_health_pack',
firstaid = 'prop_ld_health_pack',
painkillers = 'prop_cs_pills',
lighter = 'p_cs_lighter_01',
rolling_paper = 'p_cs_papers_01',
phone = 'prop_npc_phone_02',
radio = 'prop_cs_hand_radio',
binoculars = 'prop_binoc_01',
},
-- Shelves in the vanilla store interiors are found by their model, so the
-- vanilla stores work in realism mode without placing anything. Every
-- shelf found gets the next category of the store's catalog in turn.
AutoDetectShelves = true,
ShelfModels = {
'v_ret_247shelves01', 'v_ret_247shelves02', 'v_ret_247shelves03',
'v_ret_247shelves04', 'v_ret_247shelves05', 'v_ret_247_cereal',
'v_ret_ml_shelfrk', 'v_ret_ml_liqshelfa', 'v_ret_ml_liqshelfb',
'v_ret_ml_liqshelfc', 'v_ret_ml_liqshelfd', 'v_ret_ml_liqshelfe',
'v_ret_ml_beerdus', 'v_ret_ml_beeram', 'v_ret_ml_beerpis',
'v_ret_247_fridge', 'v_ret_fh_fridge', 'v_ret_ml_fridge',
'v_ret_ml_fridge02', 'prop_ff_shelves_01',
},
-- What happens to the basket when the player walks out without paying:
-- 'return' = everything goes back on the shelf, nothing is lost
-- 'steal' = the player keeps it and the police get an alert (see Dispatch)
LeaveAction = 'return',
-- Taking an item plays this short animation.
PickAnim = { dict = 'mp_common', name = 'givetake1_a', duration = 900 },
}
-- Shoplifting alert. 'auto' = ps-dispatch, cd_dispatch, qs-dispatch or
-- core_dispatch when one runs; 'event' = only fires agency-shop:server:shoplift.
Config.Dispatch = {
System = 'auto',
Jobs = { 'police', 'sheriff' },
}
--==============================================================================
-- 8 · OWNERSHIP
--==============================================================================
Config.Ownership = {
Enabled = true, -- players can buy stores and gas stations
MaxPerPlayer = 2, -- stores + stations one character may own
BuyAccount = 'bank', -- paid from 'bank' or 'cash'
-- Selling to another player: he has to stand this close, and has this
-- many seconds to accept. Paid from and to BuyAccount.
TransferDistance = 5.0,
TransferSeconds = 30,
TransferMaxPrice = 10000000,
SellBackPercent = 60, -- percent of the price back when selling to the city
-- Owners set their own prices inside these limits (x base price).
MinPriceFactor = 0.6,
MaxPriceFactor = 2.5,
-- Takings go into the store's register; owners withdraw them.
SalesTaxPercent = 5, -- cut the city keeps from every sale
RegisterAccount = 'cash', -- register pays out to / takes from 'cash' or 'bank'
-- Stock. An owned store sells only what was delivered. Stores nobody owns
-- sell without limit.
StartStock = 20, -- pieces per item when a store is bought
MaxStock = 500, -- pieces per item a store can hold
MaxEmployees = 6, -- staff may order stock and deliver
-- A store that earned nothing this long goes back on the market.
-- 0 = never. Counted in real days.
InactiveDays = 0,
}
--==============================================================================
-- 9 · DELIVERIES
--==============================================================================
-- Owners order goods from the wholesaler. Every order becomes a delivery job:
-- someone drives to the depot, takes the van, loads the crates, drives to the
-- store and carries them in. Only then the stock goes up.
Config.Delivery = {
Enabled = true,
-- Who brings the goods:
-- 'npc' = an NPC driver, after a while (see Npc below). No depot needed.
-- 'player' = a delivery job at the depot that players take
-- 'both' = the owner chooses for every order
Mode = 'npc',
-- What the goods cost from the wholesaler (x base price).
WholesaleFactor = 0.55,
-- The courier's pay, part of every order and paid by the store.
FeePerCrate = 35,
PiecesPerCrate = 20, -- one crate holds this many pieces
MaxCrates = 10, -- a bigger order is split into several jobs
-- Who may take delivery jobs. Empty = everyone. Owners and their staff may
-- always deliver to their own store.
Jobs = {},
-- The wholesale depot: board with the open jobs, van spawn.
Depot = {
coords = vector4(153.68, -3211.88, 5.91, 274.5),
vehicle = vector4(141.12, -3204.31, 5.85, 267.5),
blip = { sprite = 478, color = 5, scale = 0.75 },
ped = 's_m_m_dockwork_01',
},
Vehicle = 'speedo', -- the delivery van
VehiclePlate = 'SHOP', -- first letters of the plate
Crate = {
model = 'prop_cs_cardbox_01',
bone = 60309,
pos = vector3(0.025, 0.08, 0.255),
rot = vector3(-145.0, 290.0, 0.0),
anim = { dict = 'anim@heists@box_carry@', name = 'idle' },
},
TimeLimit = 30, -- minutes before a taken job goes back on the board
ReturnVan = true, -- the van must be brought back to the depot
-- NPC delivery (Mode 'npc' or 'both'): the stock arrives after a while.
-- Players close to the store see the van drive up and the driver carry the
-- crates in.
Npc = {
FeeMultiplier = 1.0, -- x the normal courier pay (e.g. 1.5 with Mode 'both')
BaseMinutes = 2, -- every NPC run takes at least this long
MinutesPerKm = 1.0, -- plus this per km from the depot
Vehicle = 'mule', -- van for goods
FuelVehicle = 'phantom', -- truck for fuel
Driver = 's_m_m_ups_01',
},
}
--==============================================================================
-- 10 · GAS STATIONS
--==============================================================================
Config.GasStations = {
Enabled = true,
-- How filling up works. A station in Stations below can override it with
-- its own mode = '...'.
-- 'simple' = choose fuel and amount at the pump, pay, the tank fills while
-- the player stands at the pump
-- 'realism' = the nozzle comes off the pump on a hose, the player puts it
-- into the fuel cap, the tank fills, then the nozzle goes back
Mode = 'realism',
-- Pumps are found by their model anywhere on the map.
PumpModels = {
'prop_gas_pump_1a', 'prop_gas_pump_1b', 'prop_gas_pump_1c', 'prop_gas_pump_1d',
'prop_vintage_pump', 'prop_gas_pump_old2', 'prop_gas_pump_old3',
},
-- Fuel types. price = per litre. Remove a line to drop that type.
FuelTypes = {
{ id = 'regular', price = 1.65 },
{ id = 'premium', price = 1.95 },
{ id = 'diesel', price = 1.75 },
{ id = 'electric', price = 0.55, electricOnly = true },
},
-- Fuel prices that move. Every few minutes each fuel type goes up or down a
-- little (price above = the middle it swings around). Every station also
-- sits a bit above or below the others, always the same. Owned stations
-- keep the prices their owner set; the wholesale price for the tanker
-- follows the market.
Market = {
Enabled = true,
Interval = 30, -- minutes between price changes
MaxChange = 0.05, -- at most 5 % per change
Range = { 0.80, 1.30 }, -- never below 80 % or above 130 % of the price
Pull = 0.10, -- how strongly it drifts back to the price
StationSpread = 0.06, -- stations differ by up to +/- 6 %
},
-- Litres per full tank by vehicle class (GetVehicleClass). Everything else: Default.
TankSize = {
Default = 60,
[0] = 45, [1] = 55, [2] = 80, [3] = 55, [4] = 70, [5] = 60,
[6] = 65, [7] = 70, [8] = 18, [9] = 85, [10] = 300, [11] = 120,
[12] = 90, [17] = 120, [18] = 90, [20] = 300,
},
-- Holding a jerry can (WEAPON_PETROLCAN) at a pump fills it for this many
-- litres of the given type. false = no refills at the pump.
JerryCan = { litres = 20, type = 'regular' },
RefuelSpeed = 1.6, -- litres per second at the pump
SoundVolume = 0.1, -- nozzle sounds (0.0 - 1.0), 0 = off
Nozzle = {
model = 'prop_cs_fuel_nozle',
bone = 60309, -- left hand
pos = vector3(0.055, 0.05, 0.0),
rot = vector3(-50.0, -90.0, -50.0),
},
Hose = true, -- a black hose from the pump to the nozzle
HoseLength = 7.0, -- metres before the hose tears off
CapText = true, -- text with the key above the fuel cap
-- Height of the hose outlet per pump model (metres above the pump's foot).
HoseHeight = {
prop_gas_pump_1a = 2.3, prop_gas_pump_1b = 2.3, prop_gas_pump_1c = 2.3, prop_gas_pump_1d = 2.3,
prop_vintage_pump = 1.8, prop_gas_pump_old2 = 1.6, prop_gas_pump_old3 = 1.6,
},
Anim = { dict = 'timetable@gardener@filling_can', name = 'gar_ig_5_filling_can' },
-- Electric models: only 'electric' at the pump, and no other type for them.
ElectricModels = {
'voltic', 'voltic2', 'neon', 'raiden', 'cyclone', 'tezeract', 'surge',
'dilettante', 'dilettante2', 'khamelion', 'imorgon', 'iwagen', 'omnisegt',
'virtue', 'buffalo5', 'powersurge', 'envisage', 'caddy', 'caddy2', 'caddy3',
'airtug', 'rcbandito',
},
-- Stations that can be bought. Pumps within `radius` belong to it; pumps
-- outside every station are public and sell at FuelTypes prices.
-- id : unique, never change it once players own the station
-- coords : centre of the station
-- price : purchase price, false = not for sale
Ownable = true,
DefaultPrice = 220000,
StartFuel = 2000, -- litres in the tanks when a station is bought
MaxFuel = 20000, -- litres the tanks hold
Stations = {
{ id = 'gas_grove', coords = vector3(-70.2, -1761.8, 29.53) },
{ id = 'gas_strawberry', coords = vector3(265.6, -1261.3, 29.29) },
{ id = 'gas_lamesa', coords = vector3(819.7, -1028.6, 26.40) },
{ id = 'gas_elburro', coords = vector3(1208.6, -1402.6, 35.23) },
{ id = 'gas_mirror', coords = vector3(1181.4, -330.5, 69.32) },
{ id = 'gas_downtown', coords = vector3(620.8, 269.0, 103.09) },
{ id = 'gas_littleseoul', coords = vector3(-724.6, -935.2, 19.21) },
{ id = 'gas_innocence', coords = vector3(-526.0, -1211.0, 18.18) },
{ id = 'gas_davis', coords = vector3(176.6, -1562.0, 29.26) },
{ id = 'gas_vespucci', coords = vector3(-319.3, -1471.6, 30.55) },
{ id = 'gas_morningwood', coords = vector3(-1437.6, -276.8, 46.21) },
{ id = 'gas_pacific', coords = vector3(-2096.2, -320.3, 13.17) },
{ id = 'gas_richman', coords = vector3(-1799.1, 803.7, 138.65) },
{ id = 'gas_tataviam', coords = vector3(2581.4, 362.1, 108.47) },
{ id = 'gas_route68', coords = vector3(49.4, 2778.8, 58.00) },
{ id = 'gas_harmony', coords = vector3(263.9, 2606.5, 44.98) },
{ id = 'gas_grandsenora', coords = vector3(1039.9, 2671.1, 39.55) },
{ id = 'gas_route68east', coords = vector3(1207.3, 2660.8, 37.90) },
{ id = 'gas_senora', coords = vector3(2539.7, 2594.4, 38.00) },
{ id = 'gas_sandy', coords = vector3(2005.6, 3773.9, 32.40) },
{ id = 'gas_sandyairfield', coords = vector3(1784.3, 3330.3, 41.24) },
{ id = 'gas_tataviam2', coords = vector3(2679.9, 3263.9, 55.24) },
{ id = 'gas_grapeseed', coords = vector3(1687.2, 4929.4, 42.08) },
{ id = 'gas_paleto', coords = vector3(1701.3, 6416.1, 32.76) },
{ id = 'gas_paleto2', coords = vector3(179.9, 6602.8, 31.87) },
{ id = 'gas_paleto3', coords = vector3(-94.5, 6419.5, 31.49) },
{ id = 'gas_zancudo', coords = vector3(-2554.6, 2334.1, 33.08) },
{ id = 'gas_marina', coords = vector3(-735.88, -1348.16, 1.60), label = 'Puerto del Sol Marina' },
},
StationRadius = 32.0,
Blip = { sprite = 361, color = 1, scale = 0.6 },
-- Fuel deliveries for owned stations: a tanker from the depot.
Delivery = {
WholesalePerLitre = 0.85,
FeePerThousand = 120, -- courier pay per 1000 litres
MaxLitres = 8000, -- per tanker run
Vehicle = 'phantom',
Trailer = 'tanker', -- false = the truck alone
UnloadSeconds = 25,
},
}
--==============================================================================
-- 11 · FUEL SYSTEM
--==============================================================================
-- Who keeps track of the fuel level.
-- 'auto' = LegacyFuel, ox_fuel, cdn-fuel, ps-fuel, lc_fuel, Renewed-Fuel or
-- okokGasStation when one runs, otherwise 'builtin'
-- 'builtin' = Agency Shops burns fuel itself (no other fuel script needed)
-- 'none' = only GTA's own fuel level, nothing burns
-- Running another fuel script: switch off its own pump interaction, or both
-- answer the same key at the pump.
Config.FuelSystem = 'auto'
Config.BuiltinFuel = {
-- Litres per minute at full throttle, by class. Idle uses a fraction.
Consumption = 1.0, -- overall multiplier
IdleFactor = 0.08,
ClassFactor = {
[13] = 0.0, [14] = 0.6, [15] = 1.4, [16] = 1.6, [21] = 0.0, -- cycles, boats, heli, planes, trains
},
LowFuelWarning = 12, -- percent, a notice once below it
StallWhenEmpty = true, -- the engine dies at 0
}
--==============================================================================
-- 12 · ADMIN & EDITOR
--==============================================================================
-- /ashops opens the admin panel. Everything there is saved in the database
-- and laid over this file, so nothing here has to be edited by hand:
-- Catalogs categories, icons and products with their prices
-- Stores name, catalog, mode (menu / realism) and price of every store
-- Points shelves, entrances and delivery points, owners, stock
-- "Reset" in the panel brings back what this file says.
Config.Admin = {
Command = 'ashops',
Ace = 'agency.shop', -- add_ace group.admin agency.shop allow
Groups = { 'admin', 'god', 'superadmin' }, -- QBCore permissions / ESX groups
}
--==============================================================================
-- 13 · STANDALONE
--==============================================================================
-- Used with Config.Framework = 'standalone', or 'auto' with no framework.
-- Money: 'auto' takes Agency-Banking when it runs, otherwise a simple wallet
-- saved per Rockstar licence. 'hooks' = the functions below.
-- Items: without ox_inventory or qs-inventory, fill in the item hooks, or
-- only weapons reach the player. Every purchase also fires the server event
-- agency-shop:server:purchased (source, items) for your own scripts.
Config.Standalone = {
money = 'auto', -- 'auto' | 'banking' | 'wallet' | 'hooks'
startCash = 500, -- wallet cash of a new player
admins = {}, -- licences counted as admin: { 'license:abc...' }
getMoney = nil, -- function(source, account) return balance end
removeMoney = nil, -- function(source, account, amount) return true end
addMoney = nil, -- function(source, account, amount) return true end
itemCount = nil, -- function(source, item) return count end
addItem = nil, -- function(source, item, amount) return true end
removeItem = nil, -- function(source, item, amount) return true end
}
--==============================================================================
-- 14 · ROBBERY
--==============================================================================
-- Aim a gun at the cashier for a few seconds and the robbery starts: the
-- alarm goes off, the police are alerted, and the money is in the safe in the
-- back, which has to be cracked. An owned store also loses a small part of
-- its register.
Config.Robbery = {
Enabled = true,
AimSeconds = 4, -- aiming at the cashier this long starts it
Exclude = { 'ammunation' }, -- store types that cannot be robbed
Timeout = 300, -- seconds to crack the safe before it is over
-- Cooldowns in minutes. 0 = none.
Cooldown = {
Store = 30, -- the same store again
Global = 5, -- any store on the server again
Player = 20, -- the same player again
},
-- Who may start a robbery. AllowedJobs empty = everyone (except the
-- blocked jobs). With jobs listed, only those may (e.g. gangs).
AllowedJobs = {},
BlockedJobs = {}, -- e.g. { 'police', 'sheriff', 'ambulance' }
-- Which weapons count. 'all' = any weapon, melee too. {} = every firearm.
-- With weapons listed only those, melee weapons included if you list them.
Weapons = 'all',
-- Weapons = { 'WEAPON_PISTOL', 'WEAPON_COMBATPISTOL', 'WEAPON_KNIFE' },
MinPolice = 0, -- police on duty needed
PoliceJobs = { 'police', 'sheriff' },
-- 'auto' = ps-dispatch or cd_dispatch when one runs, else the built-in
-- alert (a message and a flashing blip for every police officer).
-- 'builtin' | 'ps-dispatch' | 'cd_dispatch' | 'none'
Dispatch = 'auto',
Safe = {
-- The cracking game: turn the dial (A / D), stop where it clicks and
-- set the number (SPACE). A wrong number costs time.
Minigame = true,
Numbers = 3, -- numbers in the combination
TimeLimit = 60, -- seconds for the whole combination
CrackSeconds = 30, -- without the game: a plain progress bar this long
-- The safe in the store's back office. GTA's office safes are part of
-- the building, so they are listed by position (the vanilla stores).
-- Other stores: a "Safe" point with /ashops (Points), or a safe prop
-- found by model. No safe, no robbery.
Spots = {
vector3(-43.43, -1748.3, 29.42),
vector3(-1478.94, -375.5, 39.16),
vector3(-1220.85, -916.05, 11.32),
vector3(-709.74, -904.15, 19.21),
vector3(28.21, -1339.14, 29.49),
vector3(1126.77, -980.1, 45.41),
vector3(1159.46, -314.05, 69.2),
vector3(378.17, 333.44, 103.56),
vector3(-1829.27, 798.76, 138.19),
vector3(-2959.64, 387.08, 14.04),
vector3(-3047.88, 585.61, 7.9),
vector3(-3250.02, 1004.43, 12.83),
vector3(546.41, 2662.8, 42.15),
vector3(1169.31, 2717.79, 37.15),
vector3(2672.69, 3286.63, 55.24),
vector3(1959.26, 3748.92, 32.34),
vector3(1734.78, 6420.84, 35.03),
vector3(-168.40, 6318.80, 30.58),
vector3(168.95, 6644.74, 31.70),
},
Models = { 'prop_ld_int_safe_01', 'p_v_43_safe_s', 'v_ilev_gangsafe', 'v_ilev_gangsafedoor', 'prop_ld_int_safe_02', 'prop_ld_safe_01' },
},
-- What the safe holds. item = false pays into the account; with an item
-- name (e.g. 'markedbills') the amount is given as that many items.
Reward = { min = 1500, max = 4500, account = 'cash', item = false },
-- An owned store loses this part of its register (percent, at most Max).
OwnerLoss = { Percent = 5, Max = 2500 },
}
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 SHOP - database tables
-- Created automatically on start (Config.AutoApplySql = true). Run this file by
-- hand only if your database user may not create tables.
-- =============================================================================
CREATE TABLE IF NOT EXISTS `agency_shop_owned` (
`id` VARCHAR(64) NOT NULL,
`kind` VARCHAR(16) NOT NULL DEFAULT 'store',
`owner` VARCHAR(80) NOT NULL,
`owner_name` VARCHAR(120) NOT NULL DEFAULT '',
`name` VARCHAR(60) NULL DEFAULT NULL,
`balance` INT NOT NULL DEFAULT 0,
`prices` LONGTEXT NULL,
`stock` LONGTEXT NULL,
`staff` LONGTEXT NULL,
`fuel` INT NOT NULL DEFAULT 0,
`fuel_prices` LONGTEXT NULL,
`sales_total` INT NOT NULL DEFAULT 0,
`revenue_total` BIGINT NOT NULL DEFAULT 0,
`last_sale` TIMESTAMP NULL DEFAULT NULL,
`bought_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `owner` (`owner`)
);
CREATE TABLE IF NOT EXISTS `agency_shop_orders` (
`id` INT NOT NULL AUTO_INCREMENT,
`shop` VARCHAR(64) NOT NULL,
`kind` VARCHAR(16) NOT NULL DEFAULT 'goods',
`items` LONGTEXT NULL,
`crates` INT NOT NULL DEFAULT 0,
`litres` INT NOT NULL DEFAULT 0,
`cost` INT NOT NULL DEFAULT 0,
`fee` INT NOT NULL DEFAULT 0,
`status` VARCHAR(16) NOT NULL DEFAULT 'open',
`courier` VARCHAR(80) NULL DEFAULT NULL,
`courier_name` VARCHAR(120) NULL DEFAULT NULL,
`eta` INT NULL DEFAULT NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `shop` (`shop`),
KEY `status` (`status`)
);
CREATE TABLE IF NOT EXISTS `agency_shop_points` (
`id` INT NOT NULL AUTO_INCREMENT,
`shop` VARCHAR(64) NOT NULL,
`kind` VARCHAR(16) NOT NULL,
`x` DOUBLE NOT NULL,
`y` DOUBLE NOT NULL,
`z` DOUBLE NOT NULL,
`h` DOUBLE NOT NULL DEFAULT 0,
`category` VARCHAR(40) NULL DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `shop` (`shop`)
);
CREATE TABLE IF NOT EXISTS `agency_shop_ledger` (
`id` INT NOT NULL AUTO_INCREMENT,
`shop` VARCHAR(64) NOT NULL,
`kind` VARCHAR(24) NOT NULL,
`amount` INT NOT NULL DEFAULT 0,
`note` VARCHAR(160) NULL DEFAULT NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `shop` (`shop`)
);
-- What admins change with /ashops: catalogs and store settings, laid over config.lua.
CREATE TABLE IF NOT EXISTS `agency_shop_overrides` (
`kind` VARCHAR(16) NOT NULL,
`id` VARCHAR(64) NOT NULL,
`data` LONGTEXT NULL,
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`kind`, `id`)
);
-- Every sale of an owned store or station, line by line: the owner's analytics.
CREATE TABLE IF NOT EXISTS `agency_shop_sales` (
`id` INT NOT NULL AUTO_INCREMENT,
`shop` VARCHAR(64) NOT NULL,
`sale` VARCHAR(24) NOT NULL,
`item` VARCHAR(64) NOT NULL,
`qty` INT NOT NULL DEFAULT 0,
`amount` INT NOT NULL DEFAULT 0,
`account` VARCHAR(16) NOT NULL DEFAULT 'cash',
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `shop_time` (`shop`, `created_at`)
);
+Good to know
Every option in config.lua does something, in 14 sections from the framework to the robbery. Most of it can also be changed in game with /ashops, which is saved in the database and laid over this file.
- Core and Interaction
- Config.Framework, Config.Inventory, Config.Images, Config.Locale, Config.Currency and Config.AutoApplySql set how the script runs. Config.Interaction chooses the key prompt or ox_target and qb-target, Config.Keys sets E, G and BACKSPACE, and Config.Office and Config.Cameras set the back office computer and the security cameras.
- Payment
- Config.Payment switches cash and card and sets the card fee. Config.Licenses names the store types that check the weapon licence, with an ignore list for flashlights, knives and armour. Config.AgencyPay sets the resource name and the seconds to confirm on the phone.
- Store Types, Catalogs and Stores
- Config.StoreTypes sets blip, cashier and purchase price per type, Config.Catalogs sets what each type sells, and Config.Stores lists every store with its mode and optional camera spots. Config.DefaultMode is the fallback between menu and realism.
- Realism Mode and Ownership
- Config.Realism covers basket, trolley, shelves, item props and walking out. Config.Ownership sets how many stores one player may own, the price limits, the sales tax, the stock, the staff and selling to other players.
- Deliveries and Gas Stations
- Config.Delivery chooses NPC driver, courier job or both and sets the wholesale prices, the courier fee and the vehicles. Config.GasStations sets the fuel types, the moving prices, the nozzle, the hose and the sounds.
- Fuel, Admin, Standalone and Robbery
- Config.FuelSystem and Config.BuiltinFuel choose your fuel script or the built-in one. Config.Admin names the command and the permissions, Config.Standalone holds the money and item functions for servers without a framework, and Config.Robbery sets cooldowns, jobs, weapons, police, safe, dial game, reward and owner loss.
?Frequently asked questions
How do I change a single text?
Put it into Config.Text with a key from locales/en.lua, for example Config.Text = { notify_title = 'Corner Shop' }. Those changes survive updates.
How do I add my own store or an MLO?
Create it in /ashops (Creator) or add it to Config.Stores. For realism mode place a shelf per category and the entrance in Shelves & points, set the office computer for the owner panel and the safe for robberies.