Documentation

Clothing store documentation

A clothing store with saved outfits, company wardrobes and an editor that prices the catalogue from inside the game. Every component and every prop, bought one garment at a time or as a whole look, with a server-side ledger that stops anyone wearing what they never paid for.

  • ESX
  • QBCore
  • vRP
  • Standalone
  • oxmysql
01

Installation

  1. Drop the resource

    Grab the script from your Tebex account, then copy the avenida_clotheshops/ folder into your resources directory and add ensure avenida_clotheshops to your server config, after ensure oxmysql.

  2. Run the SQL

    Run section [A] of INSTALL.sql on your database. Section [B] is conditional, the file header says when you need it.

  3. Grant the admin permissions

    Add add_ace group.admin avenida_clotheshops.admin allow and add_ace group.admin avenida_clotheshops.vip allow to your server config. The first one opens the catalogue editor, the second unlocks whatever you put behind the VIP list.

  4. Price the catalogue from in game

    Set Config.DevMode.Enabled = true, walk into a store and open the editor. Set prices, hide what you do not sell, restrict what belongs to a job. Everything lands in config/clothes_overrides.lua. Turn DevMode back off when you are done, it is checked again server side on every save.

  5. Verify the integrations

    Set Config.Debug = true, restart, and read the console: one line per bridge category names the target that was picked. Config.Debug only controls logging, it is not the editor switch.

02

Configuration

Price a section three different ways

Each store declares its own sections, and each section its own pricing mode. A flat rate for a whole section, a multiplier that makes later drawables dearer, or a table when only a handful of pieces deserve their own price.

lua
-- config/clothes_shops.lua
categories = {
    tops = {
        enabled = true,
        price   = { mode = 'fixed', base = 300 },
    },
    pants = {
        enabled = true,
        -- price = base + index * mult
        price   = { mode = 'multiplier', base = 100, mult = 2 },
    },
    mask = {
        enabled = true,
        price   = { mode = 'table', map = { [12] = 900, [45] = 1500 } },
        -- only these drawables are offered
        whitelist = { 12, 45, 51 },
    },
}
03

Exports

Client

  • GetSkinData
    exports['avenida_clotheshops']:GetSkinData()

    The outfit the player wears, component by component, props included. This is what the store writes on purchase, so it is always in step with what the wardrobe shows.

  • ApplySkin
    exports['avenida_clotheshops']:ApplySkin(data, ped)

    Applies a complete appearance to a ped. Applying an outfit clears the decoration slot, so this call puts the barber and tattoo work back afterwards rather than leaving a bare skin.

  • ApplyClothing
    exports['avenida_clotheshops']:ApplyClothing(data, ped, temporary)

    Changes the clothes and nothing else. With temporary set to true the outfit lives for the session only, which is how a uniform handed out by a job should behave.

Server

  • GetBagStorage
    exports['avenida_clotheshops']:GetBagStorage(sex, drawable) --> { weight, slots } | nil

    The capacity a backpack drawable grants, weight and slots, or nil when that drawable carries nothing. Call it from your inventory resource so a bag bought in the store actually holds something.

04

Recipes

Open a store with its own tax and discount

A store is one entry. It carries its display name, its payment method, its currency symbol, an optional tax and discount applied to the cart total, and the sections it offers. Keep the key stable: it is the store id saved inside outfits, and renaming it after players have shopped there breaks their data.

lua
-- config/clothes_shops.lua
Config.Clothes.Shops[22] = {
    name       = 'Ponsonbys - Rockford Hills',
    payment    = 'bank',
    currency   = '$',
    tax        = 0.20,        -- +20% on the cart
    discount   = 0.00,
    outfitMode = true,
    blip = { sprite = 73, color = 4, scale = 0.7, coords = vec3(-708.2, -152.2, 37.4) },
    categories = {
        tops  = { enabled = true, price = { mode = 'fixed', base = 900 } },
        shoes = { enabled = true, price = { mode = 'fixed', base = 450 } },
    },
}

Keep a uniform for one job

A restricted piece is hidden from anyone who does not pass the check, so a civilian never sees the police jacket in the grid. Company wardrobes go further: the boss edits a shared list and every member wears it without paying, which is what you want for a new recruit on their first shift.

lua
-- config/clothes_overrides.lua, or write it from the in-game editor
Overrides['tops'] = {
    [56] = { job = 'police', label = 'LSPD jacket' },
    [12] = { hidden = true },
    [31] = { restricted = true },   -- ACE permission
}

Turn the ownership ledger off

It is on by default and it is what stops a tampered client from wearing the catalogue for free. Turn it off only if another resource of yours dresses players in pieces they never bought and you would rather not seed them. Existing characters are seeded from what they already wear, so switching it on later takes nothing away.

lua
-- config/clothes.lua
Config.Clothes.RequireOwnership = false

-- how far from a store the server still accepts a purchase
Config.Clothes.PurchaseRange = 30.0

-- saved outfits per character, enforced server side
Config.Clothes.MaxOutfits = 30
Config.Clothes.MaxOutfitsRestricted = 50

Redraw decorations from your own script

Applying a full outfit clears the ped decoration slot, which is shared by the whole server. If your script dresses a player, read what this resource owns first and hand it back afterwards, otherwise the tattoos and the hair base go with the change.

lua
local hairbase = exports['avenida_clotheshops']:GetHairbase()
local tattoos  = exports['avenida_clotheshops']:GetTattoos()

-- your own clothing work here

if hairbase then
    AddPedDecorationFromHashes(PlayerPedId(), hairbase.c, hairbase.t)
end
for _, dec in ipairs(tattoos) do
    AddPedDecorationFromHashes(PlayerPedId(), dec.c, dec.t)
end
05

Questions

A player says they lost clothes they owned

Check Config.Clothes.RequireOwnership. The ledger seeds a character from what they are already wearing the first time it sees them, so turning it on does not take a wardrobe away. What it does refuse is a write for a garment with no purchase behind it, which is also what a tampered client sends. If a resource of yours dresses players in pieces they never bought, either register those purchases or set the flag to false.

The catalogue editor does not open

It needs two things at once: the ACE permission avenida_clotheshops.admin and Config.DevMode.Enabled = true. Config.Debug is a different switch and only controls logging. Every save is checked again server side, so granting yourself the permission in game is not enough on its own.

The same jacket appears several times

That is GTA. The game repeats a drawable across several indices, and most stores list every one of them. Phantom drawables are filtered here, so if you still see a duplicate it is usually a clothing pack that ships the same asset twice. Hide the extra one from the in-game editor, it lands in config/clothes_overrides.lua.

Hair goes through a helmet

The cut is declared per item, so a helmet or a mask you added yourself has no rule yet. Set its hair behaviour from the catalogue editor, and remember the player override exists: someone who prefers keeping their hairstyle can say so, and their choice wins over the automatic cut.

Do outfit pictures need anything installed?

They need screenshot-basic, and only for that. It is the one optional integration in the requirements table whose absence is visible to the player: without it, saved outfits work exactly the same but the list shows names instead of previews.

Which frameworks does it actually support?

QBCore, ESX and vRP, plus a standalone mode that needs no framework at all and a custom branch in bridges/framework.lua for anything else. Detection runs at startup and probes the real export. Qbox and ox_core have no dedicated branch: they run through the standalone or custom path, not through a tested target.

Can I run it next to avenida_barber and avenida_tattoo?

Yes, that is what they are built for. This one is the most disruptive of the three, since applying an outfit clears the decoration slot, so it puts back what the other two own after every change. What you must not do is run the separate resources and the avenida_skin bundle at the same time. The resource detects the overlap and says so in the console at startup.

What does it cost when nobody is shopping?

0.00ms. The interaction points share one thread that parks at one second when nobody is nearby, blips are created once, and every session thread is killed on exit. The preview debounce only exists while a menu is open, and it is tunable for weaker machines.

Cart
Spirit RP
Discord