STG ScriptsDocumentation
Vanaheim Market

Configuration

Every option in STG Vanaheim Market, from language, target and blips to staff, the supplier, NPC customers, thefts, ranks, stores, products and decorations.

Most settings live in stg-vanaheimmarket/shared/config.lua. Stores are in shared/shops.lua, notifications and integrations in shared/functions.lua, the product catalog in shared/products.lua and the decorations in shared/decorations.lua. These files stay editable in the escrow version. Restart the resource after a change.

Language

Config.Language = 'en'

Available: en, de, fr, es, pt, it, nl, pl, sv, no, fi, cs, ar, he, jp, ko, zh. To change a text, edit the matching file in stg-vanaheimmarket/locales/. The blip name, the staff, shelf and permission names are in the same files.

Target system

Config.Target = 'auto'

Prop

Type

Blips

Config.Blips = {
    Enabled = true,
    UseStoreName = true,
    Sprite = 52,
    Color = 2,
    OwnedSprite = 52,
    OwnedColor = 5,
    Scale = 0.8,
    ShortRange = true,
    NearestOnly = false,
}

Prop

Type

Vanaheim Fuel

Config.FuelStorePrice = true

A store with a fuelStation key in shared/shops.lua belongs to whoever owns that Vanaheim Fuel gas station. It cannot be bought, sold or transferred on its own, and the safes of the store and the station stay separate.

Prop

Type

Stores without an owner

Config.UnownedShop = {
    Enabled = true,
    PriceMultiplier = 1.0,
    Items = { 'water', 'sprunk', 'ecola', 'coffee', 'sandwich', 'burger', 'hotdog', 'donut', 'chips', 'egochaser', 'bread', 'firstaid', 'painkillers', 'lighter', 'cigarettes' },
}

Until someone buys a store, a clerk stands behind the counter and sells the basics, so players can always buy food and drinks. The clerk leaves as soon as the store is bought. Money from these sales goes to no one.

Prop

Type

Economy

Config.WithdrawTax = 5

Config.Business = {
    SellbackRate = 60,
    PayrollIntervalMinutes = 60,
}

Prop

Type

Deposits, withdrawals and salaries always use the player's bank account. Customers pay at the register with cash or bank.

NPC staff

Config.Staff = {
    cashier = { hireCost = 5000, wage = 750 },
    stocker = { hireCost = 4000, wage = 600 },
}

The owner hires staff in the Staff tab. hireCost is paid once from the safe, wage on every payroll cycle. If the safe cannot pay a wage, that NPC quits and the owner is told.

  • Cashier: serves NPC customers at the register on their own. Without a cashier, a member behind the counter serves every customer with the barcode scanner.
  • Shelf Stocker: carries boxes from the storage room and refills slots that have Auto on, even while the store is closed.

Supplier

Config.Supplier = {
    DeliveryFee = 15,
    DeliveryMinutes = 5,
    Pickup = vec4(153.04, -3077.83, 5.9, 88.52),
}

Members with stock permission build an order list in the Stock tab. The order is paid from the safe, then they either drive to the supplier and bring the cargo back for free, or pay a fee and wait for delivery. Delivered stock lands in the store warehouse.

Prop

Type

/cancelmarketorder cancels a running pick up and refunds the order cost to the safe.

Warehouse and shelves

Config.WarehouseCapacity = 2000

Config.Shelves = {
    MaxPrice = 100000,
    RestockThreshold = 25,
}

Prop

Type

NPC customers

Config.Simulation = {
    Customers = { Min = 1, Max = 1 },
    ItemsPerVisit = 2,
    MaxUnitsPerItem = 3,
    QueueMax = 4,
    QueuePatience = 120,
    ServeTip = 5,
    VisualCustomers = {
        Enabled = true,
        Group = { Min = 1, Max = 1 },
        WaveCooldown = { Min = 30, Max = 30 },
    },
}

Every minute, customers visit each open store that has a cashier or a member inside. Prices below the market price of a product sell faster, prices above it sell slower. Without a cashier, customers line up at the register and a member behind the counter serves them with the barcode scanner, then the customer pays by card and leaves a tip.

Prop

Type

Customers who find the shelves empty leave upset, and online members get an out of stock alert.

Thefts

Config.Events = {
    Enabled = true,
    TheftChance = 4,
    TheftUnits = { Min = 5, Max = 15 },
}

While a member is inside an open store, a thief can sneak into the storage room, grab a box from the warehouse and run. The store alarm rings, the thief shows on the map and hired staff join the chase. Knock the thief down and carry the box back to the storage point, or let the shelf stocker do it. If the thief gets away, the stock is lost.

Prop

Type

Layout editor

Config.Editor = {
    MaxFurniture = 10,
    MaxDecorations = 20,
}

Prop

Type

Owners open the editor from Shelves > Edit Layout in the management menu. Controls, rebindable in the FiveM key settings:

KeyAction
GShow or hide the cursor
Left mouseDrag the gizmo
E / RMove or rotate mode
QWorld or local axes
FFreecam
Left / RightSelect the previous or next piece, or change the type of a new piece
BSnap to the floor
DeleteRemove the piece
EnterSave
BackspaceCancel

Ranks

Config.DefaultRanks = {
    { name = 'Owner', level = 100, salary = 0, owner = true,
      permissions = { manage = true, hire = true, manageStock = true, manageMembers = true, withdraw = true, viewFinance = true } },
    { name = 'Manager', level = 50, salary = 1000, owner = false,
      permissions = { manage = true, hire = true, manageStock = true, manageMembers = true, withdraw = false, viewFinance = true } },
    { name = 'Employee', level = 10, salary = 500, owner = false,
      permissions = { manage = false, hire = false, manageStock = true, manageMembers = false, withdraw = false, viewFinance = false } },
}

Ranks every store starts with. In the management menu, members with Manage Members can add custom ranks, rename them and move members between ranks below their own. Only the owner can change salaries and permissions, so these only set the starting point. The owner rank always holds every permission and is never paid, and new members join on the lowest rank.

PermissionAllows
manageRename the store, open or close it and edit the layout
hireHire or dismiss the cashier and shelf stocker
manageStockSet shelf products and prices, restock and order from the supplier
manageMembersInvite, remove and change the rank of members
withdrawWithdraw money from the safe
viewFinanceSee sales, transactions and business statistics

Stores

The script ships with 14 stores in shared/shops.lua. The key, for example strawberry, is how the store is saved in the database, so never rename it once the server is live.

KeyStoreGas station
strawberryStrawberry 24/7
grove_streetGrove Street LTDstation_26
banham_canyon_24_7Banham Canyon 24/7
chumash_24_7Chumash 24/7
mount_chiliad_24_7Mount Chiliad 24/7station_17
sandy_shores_24_7Sandy Shores 24/7station_15
harmony_24_7Harmony 24/7
grand_senora_desert_24_7Grand Senora Desert 24/7station_14
tataviam_mountains_24_7Tataviam Mountains 24/7station_6
downtown_vinewood_24_7Downtown Vinewood 24/7
little_seoul_ltdLittle Seoul LTDstation_24
richman_glen_ltdRichman Glen LTDstation_21
mirror_park_ltdMirror Park LTDstation_4
grapeseed_ltdGrapeseed LTDstation_16

Every store sells for $150,000. Strawberry uses every option:

Config.Shops = {
    ['strawberry'] = {
        label = 'Strawberry 24/7',
        salePrice = 150000,
        center = vec3(28.6, -1344.6, 29.5),
        radius = 14.0,
        hideModels = { 'v_66_fridge' },
        placeSpawn = vec4(28.6, -1344.6, 29.5, 0.0),
        management = vec4(25.2683, -1345.1144, 29.4971, -85.75),
        register = vec4(25.75, -1346.35, 29.5, 90.0),
        cashier = vec4(24.47, -1346.62, 29.5, 271.66),
        stocker = vec4(27.3567, -1348.5425, 29.4971, 2.9121),
        storage = vec3(29.9, -1338.9, 29.5),
        dropoff = vec4(31.2, -1337.5, 29.5, 0.0),
        storageProp = nil,
        entrance = vec4(29.3, -1350.6, 29.33, 0.0),
        customerSpawns = {},
        fuelStation = nil,
        lights = {
            brightness = 1.5,
            range = 8.0,
            color = { 255, 241, 222 },
            points = {
                vec3(27.5, -1347.5, 30.7),
                vec3(31.0, -1347.5, 30.7),
                vec3(27.5, -1342.5, 30.7),
                vec3(31.0, -1342.5, 30.7),
            },
        },
        doors = {
            { model = 1196685123, coords = vec3(27.82, -1349.17, 29.65) },
            { model = 997554217, coords = vec3(30.42, -1349.17, 29.65) },
        },
    },
    -- ...
}

Prop

Type

Adding a store

Admins with the command.marketsetup ace can add a store in game:

  1. Stand inside the store and type /marketsetup.
  2. Walk to every point it asks for and press E: the middle of the store, the office desk, behind the counter, the customer side of the counter, the stocker spot, the storage point and the entrance door. Backspace goes back a step, X cancels.
  3. Enter the store name and sale price, and tick the box pile option if the store has no stock room look.
  4. The finished block is copied to your clipboard. Paste it inside Config.Shops in shared/shops.lua and restart the resource.

The default name, the hidden fridge models and the doors are filled in for you, and the store is linked to the nearest Vanaheim Fuel gas station when one is close by.

Products

Every product is defined in shared/products.lua. Only items listed here can be ordered from the supplier and placed on the shelves.

Config.Products = {
    ['water'] = { label = 'Water', category = 'Drinks', wholesale = 3, market = 8, demand = 1.3, prop = 'prop_ld_flow_bottle' },
    ['burger'] = { label = 'Burger', category = 'Food', wholesale = 7, market = 18, demand = 1.1, prop = 'prop_cs_burger_01',
        hold = { Bone = 18905, Offset = vec3(0.13, 0.05, 0.02), Rotation = vec3(-50.0, 16.0, 60.0) } },
    -- ...
}

Prop

Type

The key is the inventory item the customer receives, so it must exist in your inventory. The product image in the menus is loaded from web/assets/img/products/<key>.png. When you add a product, add its image there too.

Decorations

Decorations are in shared/decorations.lua. They hold no stock, they only make the store look lived in. The Decor tab lists them in the order of this file.

Config.Decorations = {
    { id = 'plant_tall', label = 'Indoor Plant', model = 'prop_plant_int_01a', price = 350 },
    { id = 'atm', label = 'ATM', model = 'prop_atm_01', price = 2500 },
    -- ...
}

Prop

Type

Notifications and integrations

In shared/functions.lua:

Config.Functions = {
    CustomNotify = false,

    Notify = function(type, message)
        lib.notify({ type = type, description = message })
    end,

    ShowHelpNotify = function(message)
        lib.showTextUI(message, { position = 'left-center' })
    end,

    HideHelpNotify = function()
        lib.hideTextUI()
    end,
    -- ...
}
  • CustomNotify: false uses the script's own notifications, prompts and progress bar. true sends them through Notify, ShowHelpNotify and HideHelpNotify and uses the ox_lib progress bar. Replace the bodies to use your own notification system.
  • HideHud / ShowHud: hide the HUD while the management screen, the barcode scanner or the layout editor is open. They support stg-hud and jg-hud, otherwise the minimap is hidden.
  • CanCarryItem: checks whether a player can carry what they buy. It supports ox_inventory, qb-inventory and qs-inventory.
  • AddEntityTarget, RemoveEntityTarget, AddBoxTarget, RemoveBoxTarget: connect the store to ox_target, qb-target or the floating prompt, following Config.Target.

Still having trouble?

Open a ticket on our Discord. Our team answers around 15 hours a day.

Get help on Discord

On this page