OPX//77
opx_infinityshops

shops

Last updated on

Clothing shops that open the fitting room, bill per changed clothing slot, offer ready-made looks and keep saved outfits with share codes.

Places clothing shops in the world. At a shop a player picks "Try clothes on" on the target eye and the appearance fitting room opens. When the player keeps the new clothes, they pay for each clothing slot that changed, before the look is saved. Inside the room the shop adds four groups: ready-made looks (uniforms), saved outfits, "Save outfit" and "Outfit code". Saved outfits can be shared with an 8-character code another player types in a shop's fitting room, where it is billed at that shop's prices. Use it to sell clothes; it stocks no garments of its own.

Sideboth
Requirescharacter, appearance (hard)
Optionaltarget (the shop row), menu (looks and outfit lists), form (outfit name and code entry)
Contractnone
Configconfig/shops.lua (shared)
Dataopx77_saved_outfits

How a bill works

The server cannot see the clothing catalogue (it is client-only), so it prices slots, not garments.

  • The shop opens a priced room (OpenWardrobe with a charge).
  • When the room's save arrives, the server compares it with the stored record and lists the slots that changed: Head, Face, InnerChest, OuterChest, Legs, Feet, Outfit, UnderwearTop, UnderwearBottom. Taking a garment off counts as a change. The client reports nothing.
  • The server adds up the shop's price for each changed slot and takes it from CURRENCY before the look is written. A slot without a price is free. Underwear is free by default.
  • If the bill cannot be paid, the save is refused (clothing.unpaid) and the stored look goes back on. If the write fails after payment, the money is refunded.
  • A uniform is billed on Save, not when picked. Its COST rides on the save permission and is charged once, by the save that keeps it; Cancel costs nothing. The slots it covers are not billed again by the room. If its bill is refused, the save is refused, every charge of that save is refunded, and the uniform can still be saved later.
  • The bill is shown before Save. The room's status line reads On Save: 1,050 €$: the changed slots at this shop's prices, plus any uniform picked here. The shop's price list arrives with its looks. Display only: the server bills from its own tables.
  • A long browse does not lose the save: while the room is open it is kept alive every 2 minutes, up to 30 minutes.
  • The server re-checks reach, bucket, the job gate and that the player is not down before opening the room, billing, or dressing.

Ready-made looks

A look from LOOKS is a partial outfit with its own COST. It sets the slots it names and leaves the others as they are; false empties a slot. Looks are filtered by job before the list is sent, so a player only sees what they may take.

Saved outfits and share codes

  • "Save outfit" stores the clothing currently saved for the character (not the unsaved preview) under a name. If the room is open, the save happens when the room closes.
  • A character keeps up to OUTFITS.MAX_PER_CHARACTER outfits.
  • "Get a share code" gives the outfit a code made from 23456789ABCDEFGHJKLMNPQRSTUVWXYZ (no I, O, 0, 1). Typing is case-insensitive and ignores dashes and spaces. A code is not a secret.
  • Wearing one of your saved outfits is free. It grants one save of exactly that look, not a free room.
  • A share code is redeemed only inside a shop's fitting room, at that shop's counter (reach, bucket, job gate, not down) with that shop's room open (shops:<key>, read through PricedRoom). The outfit goes onto the room's draft with no free grant: on Save, the changed pieces are billed at this shop's PRICES, like rack pieces. Cancel costs nothing. Elsewhere the code answers redeemAtShop; at the counter without the room, redeemInRoom.
  • The save, list, load, delete and share doors accept one press per 750 ms per player; typing a code, one per 2 s.
  • Deleting a character deletes its saved outfits.

Configuration

config/shops.lua sets OPX.Config.MODULES.shops.

KeyDefaultEffect
enabledtruefalse switches the module off.
PRICESHead 250, Face 250, InnerChest 400, OuterChest 600, Legs 450, Feet 300, Outfit 900Price per changed slot. A slot not listed is free. Unknown slot names are dropped with a boot warning.
CHARGEtruefalse makes every shop free (prices and look costs).
CURRENCY'EDDIES'Money type a bill is taken from.
REACH3.0Metres from the shop. Re-measured on the server, which allows REACH_SLACK (1 m) more. Also the target sphere radius.
SHOPSjinguji, thrift_watsonThe shops, keyed by slug. See below.
OUTFITS{ MAX_PER_CHARACTER = 24, MAX_NAME_BYTES = 48, SHARING = true, CODE_LENGTH = 8 }Saved outfits. SHARING = false stops minting and redeeming codes. CODE_LENGTH 4–16.
LOOKSncpd_patrol, corpo_blackReady-made looks. See below.
config/shops.lua — one SHOPS entry
thrift_watson = {
  LABEL = 'Second-hand, Watson',
  X = -1180.0, Y = 1550.0, Z = 25.0,
  PRICES = { Head = 80, Face = 80, InnerChest = 120, OuterChest = 180,
    Legs = 140, Feet = 100, Outfit = 300 },
},
  • LABEL: name used in bills and audit. Defaults to the key.
  • X, Y, Z: position. Required.
  • BUCKET: routing bucket, 0 when omitted. A shop serves its own bucket only (there is no "every bucket").
  • PRICES: override merged over the default PRICES; it can only add or change slots, never remove one. {} changes nothing; a slot set to 0 is free at that shop. A free shop is 0 for every slot (or CHARGE = false frees every shop).
  • JOBS: { job = minimumGrade }. nil = anybody.
  • ON_DUTY: true = the job must be on duty.
config/shops.lua — one LOOKS entry
corpo_black = {
  LABEL = 'Corporate black',
  COST = 2500,
  WEAR = { InnerChest = 'Items.Formal_Shirt_01', OuterChest = 'Items.Formal_Jacket_01',
    Legs = 'Items.Formal_Pants_01', Feet = 'Items.Formal_Shoes_01', Head = false, Face = false },
},
  • LABEL: shown in the list.
  • COST: one price for the whole look. 0 is free.
  • JOBS, ON_DUTY: same as a shop.
  • AT: list of shop keys that offer it. nil = every shop.
  • WEAR: { Slot = 'Items.Record' | false }. Slots not named are left unchanged.

Refusal codes

Every refusal is a toast with locale key shops.<code>. The bill and look purchase can also show the character module's money key (for example money.insufficient).

CodeMeaning
no_such_shopNo shop with that key.
too_farOut of reach, or another bucket.
position_unknownThe server cannot read the player's position.
not_for_youThe shop's job gate refused.
downedThe player is down (Nobody serves you from the floor.).
redeemAtShopA share code typed away from a clothing shop's counter.
redeemInRoomA share code typed at the counter without that shop's fitting room open.
unavailableappearance cannot open the room or dress the player.
cannotPayThe bill or look cost could not be taken.
noSuchLookNo look with that key.
notForYouThe look's job gate refused.
notHereThis shop does not carry that look.
noCharacterNo character loaded.
nameNeededEmpty outfit name.
tooManyOutfit limit reached.
nothingWornNo stored clothing to save.
saveFailedDatabase write failed.
listFailedDatabase read failed.
noSuchOutfitNot one of this character's outfits.
outfitUnreadableThe stored outfit could not be decoded.
sharingOffOUTFITS.SHARING is off.
badCodeNot a valid code.
noSuchCodeNo outfit has that code.
codeFailedNo unique code after five tries.

On this page