fw_clothing¶
Worn clothes, saved outfits, and wearable state. Version 1.0.0. Registers with fw_core API 1.
Source: resources/[framework]/fw_clothing.
The shop menu and the murphy_clothing / murphy_clothes event names come from the Murphy clothing resource. This copy does not create murphy_clothes, murphy_outfits, or murphy_wearable tables — everything is stored as one JSON document on fw_characters.clothing, written through exports.fw_characters:SetClothing.
Depends on fw_core and fw_characters. fw_creator must keep Config.murphy_clothing = true — the creator then fires the murphy_clothing events this resource listens for. See fw_creator.
On success:
[fw_clothing] ready. Purchases are not charged until a money resource exists.
After a skin apply, fw_creator fires murphy_clothing:loadclothes; this resource handles that event and dresses the ped from the character's clothing document. The skin guard asks exports.fw_clothing:AreClothesStillApplied() to confirm the dress-up stuck.
There is no money resource yet. Shop prices still appear and a purchase succeeds, but nothing is deducted — see Money, items, and jobs. Job-locked categories stay hidden because there is no job on the character.
The clothing document¶
{
clothes = {
hats = { model = 12, texture = 1 },
},
outfitId = "1234567", -- "0" when no saved outfit is worn
outfits = {
{
outfitId = "1234567",
name = "Town clothes",
clothes = {},
singleitems = {},
price = 0,
gender = "male", -- or "female"
},
},
wearable = {
["1234567"] = {}, -- skin table saved with that outfit
},
}
| Key | Meaning |
|---|---|
clothes |
What the ped is currently wearing. Categories in Config.EssentialsCategories are stripped before every save — hair and beard stay on the barber document, not here. |
outfitId |
The id of the saved outfit currently worn, or "0" for none. |
outfits |
Outfits this character has saved. An outfit id is a unique 7-digit string per character. Deleting an outfit removes it from this array — no row is left behind. |
wearable[outfitId] |
The wearable state saved alongside that outfit. |
There is no offline write — every write requires the online player who currently has that character selected. SetClothesForChar returns false when the target character isn't the one the player has selected right now.
Server exports¶
| Export | Summary |
|---|---|
IsBandanaEquipped(source) |
Whether a mask/bandana category is worn. |
GetPlayerClothes(source) |
Worn clothes, standardized to asset hashes. |
GetPlayerTemperatureProtection(source) |
Warm/cold item counts and protection level. |
SetClothesForChar(charid, clothes, outfitId) |
Writes worn clothes for an online, selected character. |
IsBandanaEquipped(source)¶
Signature
---@param source integer
---@return boolean
exports.fw_clothing:IsBandanaEquipped(source)
Returns true when the worn clothes include masks or masks_large with model > 0.
GetPlayerClothes(source)¶
Signature
---@param source integer
---@return table
exports.fw_clothing:GetPlayerClothes(source)
Returns a category map standardized to asset hashes for integrations like jo_libs: { [category] = { hash, drawable, albedo, normal, material, palette, tint0, tint1, tint2 } }. {} when the character has nothing saved, or the category/model has no matching entry in shared/murphy_assets.lua for the ped's detected gender.
GetPlayerTemperatureProtection(source)¶
Signature
---@param source integer
---@return table
exports.fw_clothing:GetPlayerTemperatureProtection(source)
Returns
{
warmItems = 0, -- count of worn categories flagged "warm" in Config.ClothingTemperature
coldItems = 0, -- count flagged "cold"
coldProtection = 3, -- Config.TemperatureProtection.cold[warmItems], default 3
heatProtection = 3, -- Config.TemperatureProtection.heat[coldItems], default 3
}
SetClothesForChar(charid, clothes, outfitId)¶
Signature
---@param charid integer|string
---@param clothes table
---@param outfitId integer|string|nil
---@return boolean success
---@return string|nil err
exports.fw_clothing:SetClothesForChar(charid, clothes, outfitId)
Persists worn clothes for the online player who currently has charid selected, then re-applies them on their client. The official write path for another resource — e.g. a job script dressing a character in a uniform.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
charid |
integer \| string |
yes | fw_characters.id. Must belong to the character currently selected by an online player. |
clothes |
table |
yes | { [category] = { model = <catalog index>, texture = <number or {palette, tint0, tint1, tint2}> } } — the murphy index format, catalog indexes from shared/murphy_assets.lua. Essential categories (skin, hair, beard, …) are stripped automatically; hair and beard belong to exports.murphy_barber:SetHairForChar instead. |
outfitId |
integer \| string \| nil |
no | Defaults to 0 (no preset) when omitted. |
Returns
| Type | Description |
|---|---|
true |
Saved and re-applied. Fires murphy_clothing:clothesUpdated and tells that client to run murphy_clothing:loadclothes. |
false, err |
See Errors. |
Errors
err value |
Condition |
|---|---|
'SetClothesForChar: charid is required' |
charid is nil or ''. |
'SetClothesForChar: clothes must be a table { category = { model, texture } }' |
clothes is not a table. |
"SetClothesForChar: invalid entry for category '<category>' (expected { model = <number>, texture = <number or table> })" |
An entry's model is missing or not a number. |
"SetClothesForChar: invalid texture for category '<category>'" |
texture is present but not a number or table. |
'SetClothesForChar: that character is not selected by an online player' |
No connected player currently has charid as their active character. |
'SetClothesForChar: could not save clothing' |
The underlying SetClothing write failed. |
Client export¶
| Export | Summary |
|---|---|
AreClothesStillApplied() |
Whether this client's last-applied clothes are still on the ped. |
AreClothesStillApplied()¶
Signature
---@return boolean
exports.fw_clothing:AreClothesStillApplied()
Runs on the client that owns the ped. Returns true when every category this resource last applied is still worn; false when clothes were never loaded this session, or at least one category is missing — used by fw_creator's skin guard to detect a skin reset that stripped clothing.
Callbacks the menu uses¶
These names stay murphy_clothing:... so the existing shop UI can call them unchanged. The server reads and writes the clothing document directly — it does not query a separate clothing table.
| Callback | Parameters | Returns |
|---|---|---|
murphy_clothing:GetCurrentClothes |
source |
Worn clothes table, outfit id. {} and 0 when the character has no clothes. |
murphy_clothing:GetCurrentClothesCharid |
source, characterId |
Same, for a character id owned by that player. |
murphy_clothing:GetCurrentOutfitList |
source |
Array of { outfit_id, name, price, gender, clothes, singleitems }. clothes and singleitems are JSON strings, matching the legacy row shape. |
murphy_clothing:GetOutfit |
source, id |
Clothes table, gender. |
murphy_clothing:SaveOutfit |
source, clothes, name, fee, male, payment? |
true, outfitId on success, false, outfitId / false, nil otherwise. Charges cash by default, or gold when payment = { currency = "gold", gold = n } and Config.OutfitGold.enabled. |
murphy_clothing:ModifyOutfit |
source, clothes, id, fee, payment? |
Replaces that outfit's clothes after the same price check as SaveOutfit. |
murphy_clothing:DeleteOutfit |
source, id |
Removes that outfit from the character. |
murphy_clothing:GiveOutfit |
source, id, name, price, payment? |
Price check for recovering an outfit already owned. |
murphy_clothing:BuySingleItem |
source, clothesTable, price, isMale |
true/false. Splits payment across cash, gold, and item currencies per Config.ItemCurrency, verifying full affordability before taking anything. |
murphy_clothing:SaveWearable / GetWearable |
source, id, data? / source, id, characterId? |
Wearable state for one outfit id. |
murphy_clothing:GetCharIdentifier |
source |
Active fw_characters.id. |
murphy_clothing:GetCharJob |
source |
nil, 0 — job-locked shop categories stay hidden until a job resource exists. |
murphy_clothing:GetCharMoney |
source |
A stand-in balance — see Money, items, and jobs. |
murphy_clothing:IsBandanaEquipped |
source |
Same check as the IsBandanaEquipped export, exposed as a callback for the menu. |
murphy_clothing:GetPlayerTemperatureProtection |
source |
Same shape as the GetPlayerTemperatureProtection export. |
Network events¶
| Event | Direction | Payload | What it does |
|---|---|---|---|
murphy_clothing:loadclothes |
server → client | none | Client re-dresses the ped from the saved document. Fired by fw_creator after a skin apply. |
murphy_clothing:SaveClothesCreator |
— | — | Fired during character creation's clothing step. |
murphy_clothing:ResetClothesMenuCreator |
— | — | Resets the in-creator clothing menu. |
murphy_clothing:OpenClothesMenuCreator |
— | — | Opens the in-creator clothing menu. |
murphy_clothes:ApplyClothesToCharid |
— | — | Applies a specific character's clothes to a ped. |
murphy_clothes:Loadlowerbody / Loadupperbody |
— | — | Partial body/clothing reload. |
murphy_clothes:updateclothes |
client → server | clothes, outfitid |
Strips essential categories, saves through FwClothing.SetCurrent, fires murphy_clothing:clothesUpdated on success. Silently dropped if the character isn't loaded yet. |
murphy_clothes:retrieveClothes |
server local | charid, callback |
Callback receives { charid, clothes, outfit_id } (clothes as a JSON string), or false when that character isn't selected by an online player. |
murphy_clothes:retrieveWearable |
server local | charid, outfit_id, callback |
Callback receives { charid, outfit_id, skin } (skin as a JSON string), or false when there's no saved wearable state. |
murphy_clothing:clothesUpdated |
server local | source, charid, clothes |
Fired after every successful clothes write — from the menu, or from SetClothesForChar. |
murphy_clothing:admin:requestOutfitMenu / requestWearableMenu |
client → server | none | Opens the outfit/wearable management menu — requires fw_players.role of admin or superadmin via GetCharGroup. |
murphy_clothes:updateclothes ignores a raw category list from an untrusted source — essential categories (Config.EssentialsCategories) are always stripped server-side before the save, regardless of what the client sent.
Money, items, and jobs¶
No money, inventory, or job resource exists yet:
GetCharMoneyreturns100000000;RemoveCurrency/AddCurrencydo nothing — a purchase always succeeds and nothing is taken.GetCharGoldreturns0;Config.OutfitGold.enabledisfalse, so the gold payment option stays off.GiveItemreturnstrueand creates nothing;RemoveItem/GetItemAmountare no-ops.Config.OutfitItemisnilandConfig.SingleItemCategoryis empty, so the shop never tries to hand out an item.GetCharJob/GetCharJobGradereturnnil, 0— job-locked categories (Config.JobLocked) stay hidden.
When a money/inventory/job resource exists, replace GetCharMoney, RemoveCurrency, AddCurrency, GetCharGold, RemoveGold, GiveItem, RemoveItem, GetItemAmount, GetCharJob, and GetCharJobGrade in server/adapters/FWAdapter.lua.
Commands¶
| Command | Default | Who | Effect |
|---|---|---|---|
/loadclothes |
Config.LoadClothesCommand |
The player who runs it | Reloads worn clothes onto the current ped. |
/ClothesManagement |
Config.ClothesManagement.Command |
fw_players.role of admin or superadmin |
Opens the clothes management menu. |
Shops use the native prompt in Config.Shops; the prompt thread sleeps until the player is within 2 meters.
Config¶
shared/config.lua. Config.framework must stay 'fw' — that is what loads the adapter.
The starter outfit in fw_creator still dresses a character that has no saved clothes of its own; it does not write clothing. Once the player saves clothes here, the starter outfit leaves that character alone.
Files¶
| File | Purpose |
|---|---|
fxmanifest.lua |
Version 1.0.0. Dependencies fw_core, fw_characters. |
server/adapters/FWAdapter.lua |
Account/character lookups, startup registration, money/item/job stand-ins. |
server/callbacks.lua |
Outfit, wearable, and currency callbacks; SetClothesForChar, GetPlayerClothes, temperature, bandana exports. |
server/clothing_store.lua |
Internal read/write of the clothing document (FwClothing.*). |
server/server.lua |
Admin menu gating, shop routing-bucket instancing. |
shared/config.lua |
Prices, categories, temperature, currency, and shop config. |
client/function.lua, client/client.lua |
Applying clothes to the ped, AreClothesStillApplied. |