Shop System

Configure NPC shops with custom items, pricing, and options

The Shop system controls what items NPCs sell in their shops. It uses a two-file pattern: a central registry (ShopManager.xml) that maps NPCs to shop files, and individual shop files (Shop/*.xml) that define item inventories.

File Locations

  • Registry: GameServer/Data/ShopManager.xml

  • Shop Files: GameServer/Data/Shop/NNN - ShopName.xml

Where NNN is a 3-digit shop index (000-999).

Configuration Pattern

Step 1: Register Shop in ShopManager.xml

Define which NPC uses which shop file.

<ShopList>
    <Shop Index="0" Npc="251" Map="*" X="*" Y="*"/>
</ShopList>
Attribute
Type
Description

Index

int

Shop index (0-99, limited by MAX_SHOP=100). Must match the shop file name prefix (e.g., 000, 001)

Npc

int/string

NPC class ID that opens this shop. Use "*" to match any NPC (converted to -1 internally)

Map

int/string

Map number where this shop is available. Use "*" to match any map (converted to -1 internally)

X

int/string

X coordinate where this shop is available. Use "*" to match any X (converted to -1 internally)

Y

int/string

Y coordinate where this shop is available. Use "*" to match any Y (converted to -1 internally)

Step 2: Create Shop File

Create GameServer/Data/Shop/NNN - Description.xml where NNN matches the Index from ShopManager.xml.

circle-info

The filename format is strict: NNN - Description.xml where the first 3 characters are digits, followed by - (space-dash-space).

Shop File Structure

Individual shop files define the items available for purchase.

Item Attributes

Attribute
Type
Default
Description

Cat

int

-

Item category (0-15). See Item.txt for categories

Index

int

-

Item index within category. Together with Cat, identifies the item

Level

int

0

Item level (0-15). Adds stats and level requirement

Durability

int

0

For regular items: durability (0 = use default). For stackable items: stack count (0 = 1)

Skill

int

0

Has skill (1 = yes, 0 = no). Adds +skill option and enables special attacks

Luck

int

0

Has Luck (1 = yes, 0 = no). Adds critical damage chance

Option

int

0

Additional option level (0-7). Each level adds 4 to primary stat

Excellent

int

0

Excellent option flags (bitwise). See Excellent Options section

Ancient

int

0

Ancient item ID (0 = none). See Ancient item configuration

JOH

int

0

Jewel of Harmony option index (0 = none)

OpEx

int

0

380 item option index (0 = none)

Socket1

int

255

Socket 1 option index (255 = empty socket)

Socket2

int

255

Socket 2 option index (255 = empty socket)

Socket3

int

255

Socket 3 option index (255 = empty socket)

Socket4

int

255

Socket 4 option index (255 = empty socket)

Socket5

int

255

Socket 5 option index (255 = empty socket)

Excellent Options (Bitwise Flags)

The Excellent attribute uses bitwise flags (0-63). Add values together for multiple options:

Bit
Value
Description

0

1

Excellent option 1

1

2

Excellent option 2

2

4

Excellent option 3

3

8

Excellent option 4

4

16

Excellent option 5

5

32

Excellent option 6

Example: Excellent="48" (32 + 16) = Options 5 and 6 enabled

Actual option effects are defined in ItemOption.xml and vary by item type:

  • Weapons: Typically include Mana/HP per kill, attack speed, damage bonuses

  • Armor/Shields: Typically include HP/Mana boosts, defense, damage reduction

  • Wings: May include max HP%, attack speed, or other special effects

circle-info

The Excellent field in the shop configuration is a bitmask that enables option slots. The actual stat bonuses applied depend on the item's category and are looked up in ItemOption.xml at indices 3-8 (corresponding to bits 0-5).

circle-exclamation

Shop Matching Algorithm

When a player clicks an NPC, the server uses a two-pass algorithm to find the correct shop:

Pass 1: Exact Match

Finds the first shop where ALL four fields match exactly:

  • Npc == NPC class ID

  • Map == map number

  • X == X coordinate

  • Y == Y coordinate

Wildcards ("*") are converted to -1 during loading, so a shop with Map="*" will only match if the actual map number is -1 (invalid), not "any map".

Pass 2: NPC-Only Match

If Pass 1 fails, finds the first shop where:

  • Npc == NPC class ID

  • Npc is NOT -1 (not a wildcard)

  • Map, X, Y are completely ignored

No Match

If neither pass succeeds, the NPC has no shop and the interaction fails.

circle-info

How to use wildcards correctly:

  • Use Map="*" X="*" Y="*" to create a global NPC shop that works anywhere

  • This works because Pass 2 ignores position entirely

  • Pass 1 will fail (map/position don't match -1), then Pass 2 succeeds (NPC class matches)

circle-exclamation
circle-exclamation

Item Pricing

Shop items use pricing defined in ItemValue.xml. The currency system works as follows:

Currency Selection (priority order, highest first):

  1. GoblinPoints - If Coin3 toggle is set in ItemValue.xml

  2. WCoinP (Premium coins) - If Coin2 toggle is set

  3. WCoinC (Cash shop coins) - If Coin1 toggle is set

  4. Zen (default) - If no coin toggles are set

circle-info

The Coin1, Coin2, and Coin3 fields in ItemValue.xml are toggles (0 or 1), not currency amounts. They select which currency to use. The actual price is stored in the BuyPrice and SellPrice fields.

Price Multipliers:

  • Stackable items: Buy/sell prices multiply by stack count automatically

  • Non-stackable items: Use base prices from ItemValue.xml

  • Items without ItemValue.xml entries use calculated prices from item properties

See ItemValue documentation for details on configuring custom prices and currency types.

Dependencies

File
Purpose

Defines all available items, categories, and base stats

Defines custom buy/sell prices and currency types (Zen/WCoinC/WCoinP/GP)

Defines which items are stackable and their maximum stack sizes

Defines which items can have sockets and maximum socket count

Defines socket option effects

Defines ancient set bonuses

Examples

Important Behavior

Filename Parsing

The server only loads shop files matching the pattern NNN - Name.xml:

  • First 3 characters MUST be digits (000-999)

  • Must have space-dash-space (-) separator after digits (character positions [3] = space, [4] = dash, [5] = space)

  • Must have .xml extension

Files like 1 - Shop.xml, 01 - Shop.xml, or Shop001.xml will NOT load.

circle-exclamation

Shop Capacity and Layout

Each shop has 120 slots arranged in a grid:

  • 8 columns (X: 0-7)

  • 15 rows (Y: 0-14)

  • Total: 120 slots (SHOP_SIZE=120)

Item Placement:

  • Items auto-arrange left-to-right, top-to-bottom during loading

  • Items occupy multiple slots based on their size (width × height from Item.txt)

  • Example: A 2×3 item occupies 6 adjacent slots in the grid

  • The server validates that items fit within grid boundaries (8 columns wide, 15 rows tall)

  • If an item cannot fit in the remaining space, it's skipped

Slot Calculation: Slot = (Y × 8) + X

  • Slot 0 = position (0, 0) - top-left

  • Slot 7 = position (7, 0) - top-right

  • Slot 119 = position (7, 14) - bottom-right

Stackable Items

For stackable items (potions, jewels, etc.), the Durability attribute controls the stack count:

  • Durability="0" = 1 item (default)

  • Durability="10" = stack of 10 items

  • Durability="255" = stack of 255 items (maximum)

Price behavior:

  • Buy price: ItemValue.xml price × stack count

  • Sell price: ItemValue.xml sell price × stack count

  • Prices automatically scale when buying/selling stacked items from shops

circle-info

The server detects stackable items using ItemStack.xml configuration. Items not defined as stackable will use Durability as actual durability value instead of stack count.

Socket Slots

Set Socket1-Socket5 to 255 for empty sockets.

Important behavior:

  • The server validates socket support using SocketItemType.xml before assigning sockets

  • Only items that support sockets (defined in SocketItemType.xml) will have socket slots allocated

  • Socket slots are only assigned up to the maximum socket count for that item type

  • Example: If an item supports 3 sockets, only Socket1-Socket3 are used; Socket4 and Socket5 are ignored

If an item doesn't support sockets, all socket attributes are ignored regardless of configuration values.

NPC Matching Priority

Always use specific Map/X/Y when possible. Wildcard shops (Map="*") can cause unexpected behavior if multiple NPCs share the same class ID.

Common Issues

circle-exclamation
circle-exclamation
circle-exclamation
circle-info

Testing shops: Use /move command to teleport to NPC location, or spawn NPC in test map to verify shop contents before deploying to production.

Adding a New Shop

  1. Choose Shop Index: Pick unused index (0-99, limited by MAX_SHOP)

  2. Register in ShopManager.xml:

    Use Map="*" X="*" Y="*" for global shops (any location).

  3. Create Shop File: GameServer/Data/Shop/050 - My Custom Shop.xml

    • Filename MUST be exactly 3 digits, space-dash-space, description

    • Shop index (50) must match filename prefix (050)

  4. Add Items: Use examples above as templates

  5. Configure Pricing (optional): Add entries to ItemValue.xml for custom prices/currencies

  6. Configure Stackables (optional): Ensure stackable items are defined in ItemStack.xml

  7. Restart GameServer: Shops load at startup only

  8. Test: Click NPC to verify shop opens with correct items and prices

circle-info

You can reload shops without restarting by calling gShopManager.LoadShop() from code, but this requires a custom admin command. By default, shops only load during server startup.

circle-exclamation

Last updated