Shp File - torilmud/docs GitHub Wiki

Shp File

The *.shp file, or shop file, contains all the information to make any shops in your zone functional.

The shp file is not required for any zones. Note that anything preceded by ;; will be treated as a comment by the code.

Shp file format

Shop format Comment
SHOP: 12345 ;; Keeper's Vnum 12345
ROOM: 23456 ;; Shop's room Vnum or ROAMING:, the first of these two that is specified will override the other one (and cause a warning message at boot time).
CASTING: ;; anyone can cast spells in this shop
KILLABLE: ;; this shopkeeper can be attacked
GREED: 140 ;; sale prices will be 140% of an object's value.
PROFIT 90 ;; buy prices will be 73% of object's value. calculation: 140 / (100 + 90) = .7368 (truncated)
DEADBEAT: 1 ;; not used.
OFFENSE: 2 ;; 0 or 1. set to 0 for the reply of "Don't ever try that again, %s!" or set to 1 for the reply of "Scram - %s, you midget!" when attacked. pretty much only used with 'hitall all'.
CHEATS: ALIEN ;; everyone not of the shopkeeper's race. Buy price for ALIENs 280%, Sale price 36% of object's value.
HATES: NPC EVILS PM PG ;; won't trade with NPCs, Drow, Duergar, Trolls, Ogres, Illithids, Dwarves or Gnomes.
HOURS CCCCCCCCOOOOCOOOOCOOOCCC ;; Closed from 9pm to 8am, open from 8am to 9pm, with 1 hour closings at noon and 5pm, this could also have been done as: HOURS: 8-12 13-17 18-20
PO: 1234 ;; produces object with Vnum 1234
PO: 2345 ;; produces object with Vnum 2345
PO: 3456 ;; produces object with Vnum 3456
BT: 2 ;; shop will buy scrolls
BT: 3 ;; shop will buy wands
BT: 4 ;; shop will buy staves
BT: 10 ;; shop will buy potions
MBCASH: $n says 'Begone pauper!'
MBHAVE: $n says 'Bah! Try selling something you actually HAVE $N'
MBIGOT: $n yells 'GET OUT OF MY SHOP SCUM!'
MBUY: $n says 'Done! Here's your %s.'
MCLOSE: $n says 'OK, we are closed, come back after %s'
MNBUY: $n says 'I'm sure that's a fine $p you have there $N, but I don't want it.'
MOPEN: $n says 'OK, we are open again, don't push, form a line.'
MCASH: $n blushes furiously.\n$n says 'Ah, I seem to be a little short right now, sorry.'
MSELL: $n says 'Sold $N, here's your $p, you won't find better anywhere!'
MSHAVE: $n looks around quickly.$n says 'Where do you see that $N? I don't have any!'
;; Optional end comment ;; End of Shop 12345

Shop Flags

This is a collection of flags used in your shops presented alphabetically.

BT:

Format: BT: #

Example: BT: 5

This is the 'Buy Types' entry, and each type must be on its own line. Use this to specify the types of objects This shop will buy. There is no limit on how many types a shop may buy, and you MUST place them on separate lines, duplicates don't matter either, code will ignore duplicates.

Notes:

  • If you don't want your shop to buy anything, don't include any.
  • Stick to item types that make sense, do not make your shops buy keys and switch type objects.
  • General stores are discouraged, if you have a weapon shop, don't make it buy food if you can help it.
  • The following item types are not allowed to be bought by shopkeepers without staff approval and even then are only allowed in specialty shops, never in general stores: 13 TRASH, 14 TRAP, 16 NOTE, 23 BOOK, 24 CORPSE, 25 TELEPORT, 28 SHIP
  • Item types that will never be allowed to be bought by shopkeepers under any circumstance: 18 KEY 29 SWITCH 40 DISTRO 43 PET 44 MOVE_BLOCK 45 RANDOM_ENCOUNTER 46 FORCED_MOVE 47 HELPER 48 GEOBOOK

CASTING:

Format: CASTING:

Example: CASTING:

This flag is special, as it has no arguments, and if set, will allow players to cast spells in the room where the shopkeeper is. The default for ALL shops is 'no CASTING', so unless you specifically want to change that, leave this out of the shop definition.

CHEATS:

Format: CHEATS: code

Example: CHEATS: ALIEN EVILS

The format on CHEATS: and HATES: is identical, because they work exactly the same.

Any code listed after CHEATS: will result in the shop doubling it's sell prices and halving it's buy prices when dealing with anyone matching ANY of the codes.

Any match with a code listed after HATES: will stop the shop from dealing with that customer at all. (see MBIGOT:).

HATES: overrides CHEATS:, and duplicates are ignored. As with PO: and BT, you can list all the codes on one line, or list them one per keyword, or any combination.

DEADBEAT:

Format: DEADBEAT: #

Example: DEADBEAT: 1

These used to be the 'temper' values, for when a buyer didn't have enough money or tried to attack the shopkeeper. They were never really implemented, and still aren't, they both default to 0. Until we actually do something with them, probably best to leave them out.

GREED:

Format: GREED: #

Example: GREED: 120

This determines the shopkeepers prices, the default value is 100 (which means this shop sells things for 100% of their value). If you do not include a GREED entry, it will be set to 100. Valid values range from 10 to 1000, and you had better have a damn good reason to ever set it below 100. Multiple entries will override each other. Notes:

  • Make sure your shops have at least some greed factor, even if there are no CHEATS: flags set. Shopkeepers who sell items at cost not only make no sense, but they also destroy one of the uses for MAX_CHARISMA items.

HATES:

Format: HATES: code

Example: HATES: NPC GOODS PO

The format on CHEATS: and HATES: is identical, because they work exactly the same.

Any code listed after CHEATS: will result in the shop doubling it's sell prices and halving it's buy prices when dealing with anyone matching ANY of the codes.

Any match with a code listed after HATES: will stop the shop from dealing with that customer at all. (see MBIGOT:).

HATES: overrides CHEATS:, and duplicates are ignored. As with PO: and BT, you can list all the codes on one line, or list them one per keyword, or any combination.

HOURS:

Format: HOURS: #,# or HOURS: #-# or HOURS: #,# #,# ... or HOURS: OOOCCC...

Example: HOURS: 7,18 or HOURS: 7-18 or HOURS: 7,12 13-18

This entry specifies the shop's operating hours. If you leave out all HOURS: entries, the shop is assumed to be always open. This is a keyword where multiple lines are fine. Valid hours are from 0 (midnight) to 23 (11 pm). This keyword has a special, optional case. Rather than using numbers, you may use a string of 'O' (open) and 'C' (closed), one per hour. Example: HOURS: CCCCCCCOOOOOOCOOOOOCOOOC

In the above example, the entry would mean that the shop is closed from 11pm to 7am, open from 7am to 1pm, closed from 1pm to 2pm, and open again from 2pm until 11pm. If you use this format, multiple entries do NOT make sense.

KILLABLE:

Format: KILLABLE:

This flag is special, as it has no arguments, and if set, will allow players to attack and kill the shopkeeper. The default for ALL shops is 'not KILLABLE', so unless you specifically want to change that, leave this out of the shop definition. Note: Killable shopkeepers are not allowed unless in very specific circumstances, check with your areas supervisor before setting this flag in a shop.

Shop Responses

Format: keyword: [applicable text]

Example: MBIGOT: I don't deal with your kind $N!

MBCASH, MBHAVE, MBIGOT, MBUY, MCLOSE, MNBUY, MOPEN, MSCASH, MSELL, MSHAVE These are all grouped, because they share the same basic format. They will allow you to personalize your shopkeeper's responses to common situations, as the examples below will show.

The $N is what's referred to as a pronoun variable, a useful set of variables that you will use extensively here and in other areas of your zone. Refer to the chart for a list and explanation of them.

MBCASH:

Default: $n says 'Sorry $N, but you don't have enough money for $p.'

This message comes out looking like:

<keeper name> says 'Sorry <customer name>, but you don't have enough money for <object name>.'

MBHAVE:

Default: $n says 'You'll have to show it to me first, $N!'

This message comes out looking like:

<keeper name> says 'You'll have to show it to me first, <customer name>!'

This message is triggered when the customer tries to sell something they either don't have in their inventory or that the shopkeeper can't see (ex: objects flagged INVISIBLE).

MBIGOT:

Default: $n says 'I don't deal with your kind $N! Begone!'

This message comes out looking like:

<keeper name> says 'I don't deal with your kind <customer name>! Begone!'

This is triggered when someone the shopkeeper HATES: tries to interact with the shop.

MBUY:

Default: $n says 'Here's your money $N, thanks.'

This message comes out looking like:

<keeper name> says 'Here's your money <customer name>, thanks.'

Triggered when shop buys something from the player.

MCLOSE:

Default: $n says 'We are closed, we'll reopen at %s.'

This message comes out looking like:

<keeper name> says 'We are closed, we'll reopen at <hour><am/pm>.'

The %s here is replaced with a time string (like midnight, noon, 7am), none of the 'buyer/seller' options are valid for this keyword (IE: $N $S $M $E $H), nor are the object options ($p $o).

This message is triggered by the HOURS: setting.

MNBUY:

Default: $n says 'I don't handle those kinds of things $N, try somewhere else.'

This message comes out looking like:

<keeper name> says 'I don't handle those kinds of things <customer name>, try somewhere else.'

Triggered when someone tries to sell the shop something it won't buy (see BT:).

MOPEN:

Default: $n says 'We are open for business, step right up!'

This message comes out looking like:

<keeper name> says 'We are open for business, step right up!'

None of the 'buyer/seller' options are valid for this keyword (IE: $N $S $M $E $H), nor are the object options ($p $o). This message is triggered by the HOURS: setting.

MSCASH:

Default: $n says 'Too rich for my blood $N, maybe you'd like to buy something first?'

This message comes out looking like:

<keeper name> says 'Too rich for my blood <customer name>, maybe you'd like to buy something first?'

Triggered when someone tries to sell the shop something it won't can't afford.

NOTE: at present, all shops have an infinite money supply, but this state of affairs will NOT last indefinitely, be prepared, and include this if the shop buys anything at all.

MSELL:

Default: $n says 'Here you go $N, and only %s too!'

This message comes out looking like:

<keeper name> says 'Here you go <customer name>, and only 13 platinum, 4 gold and 3 copper coins too!'

Triggered when the shop sells something to the player. The %s here will be replaced with a 'coins' string # plat, # gold, # silver and # copper coins with 0 for any suppressing the word too (You'll never see 0 platinum, 3 gold, 0 silver...).

MSHAVE:

Default: $n says 'Sorry $N, but I don't have any $p to sell!'

This message comes out looking like:

<keeper name> says 'Sorry <customer name>, but I don't have any <object name> to sell!'

Triggered when someone tries to buy something the shop doesn't have for sale.

OFFENSE:

Format: OFFENSE: #

Example: OFFENSE: 1

DEADBEAT: and OFFENSE: used to be the 'temper' values, for when a buyer didn't have enough money or tried to attack the shopkeeper. They were never really implemented, and still aren't, they both default to 0. Until we actually do something with them, probably best to leave them out.

PO:

Format: PO: #

Example: PO: 364

This is the 'Produces Objects' entry, and each entry must have its own line. Use this to specify the Vnum of the objects you wish this shop to produce in endless quantities. If you just want your shop to sell only what you load onto it, or what some character sells it, don't use any of these entries. Note that you must load one copy of an object you wish the shop to produce into the shopkeeper's inventory, before they will start producing that item. This is deliberate and will not change, since removing an object from a shopkeeper's inventory via the .zon file is much more difficult than loading one.

In general, shops tend to produce items from their own zone, but in approved cases, they do not have to. Either use lookup on the testmud to get the Vnum you want, or ask a higher level god what the Vnum of a desired object is.

In most cases (though not all) a shop should be willing to buy back anything it produces, some examples: A smithy, that produces armor and weapons, should be willing to buy armor and weapons (though prices will vary, see PROFIT:). On the other hand, a restaurant that sells food and drinks, very well might not buy anything at all, just think about what you are doing with this shop.

PROFIT:

Format: PROFIT: #

Example: PROFIT: 150

This determines the prices that a shop will PAY for objects sold to it. The default is 100, which is a 100% markup, meaning the selling price is twice what the shop will pay to buy it back.

A shop has default GREED 100 and PROFIT 100 (the defaults), then: Object valued at 1000 coins, shop sells it for 1000 coins (100%) and would buy it back for 500 coins. (Assuming the shop WILL buy it back, see BT:)

ROAMING:

Format: ROAMING:

Example: ROADMING:

This flag is special, as it has no arguments, and if set, will allow the shopkeeper to move around the zone and still peddle it's merchandise, (assuming the mob is not flagged ACT_SENTINEL) The default for ALL shops is 'no ROAMING', so unless you specifically want to change that, leave this out of the shop definition.

ROOM:

Format: ROOM: #

Example: ROOM: 3546

This keyword only applies to non-roaming shops. Basically if a shop is not roaming, the shop proc will be disabled when the keeper is not in his shop. The number is the Virtual Number of the room the shopkeeper loads into. Multiple entries of this keyword might not work, so if you want your mob to load in different areas at different times make your shop ROAMING:.

SHOP:

Format: SHOP: #####

Example: SHOP: 98546 ;; start a new shop, the shopkeeper's Vnum is 98546.

This is the only keyword that cannot be used multiple times within a shop entry, as its presence means 'finish the previous shop and start a new one'. Each Vnum may have only one shop associated with it, and each shop can only have one keeper associated with it, of course you can copy a shop and just change the SHOP: line for another shop. It is a good idea to add a ;; comment before starting a new shop, as it will make your life easier later, when debugging your zone.

The Cheat / Hate Codes

These are the codes that CHEATS: and HATES: will use to determine who they will and will not interact with.

Code Target Code Target Code Target
CA WARRIOR CB RANGER CC BERSERKER
CD PALADIN CE ANTIPALADIN CF CLERIC
CU ILLUSIONIST CH DRUID CI SHAMAN
CS INVOKER CK NECROMANCER CL CONJURER
CM THIEF/ROGUE CN ASSASSIN CT ENCHANTER
CP BARD CQ PSIONICIST CR LICHCLASS
CZ ELEMENTALIST CV DIRERAIDER
PH HUMAN PB BARBARIAN PL DROW ELF
PE GREY ELF PM MOUNTAIN DWARF PD DUERGAR
PF HALFLING PG GNOME PO OGRE
PT TROLL P2 HALF ELF PI ILLITHID
PY YUANTI PZ LICHRACE PR ORC
NPC Mobs in general OWN Shopkeeper's own race ALIEN Not of shopkeeper's race
EVILS Evilraces not alignment GOODS Goodraces not alignment ALL Everyone

Almost any combination of the above is possible and legal, but note that there is no way to negate a code, so make sure you pick the ones you really want.

The class codes are primarily for guild shops, as telling a person's class outside of a guild is more than a tad difficult. DON'T abuse them. (Due to recent bugs, you should NOT string these all on one line. Is this still true??) The following is the correct format:

HATES: EVILS

HATES: PB

HATES: NPC

For now, all shops default to HATES: NPC, mainly because we don't want to deal with NPCs buying/selling things from each other. If your shop doesn't hate or cheat anyone, just leave them off.

⚠️ **GitHub.com Fallback** ⚠️