Skip to content

Add, Price and Remove Shop Items

This guide shows how to add an item to the shop, change its price, or take it off sale. It covers heroes, gear boxes, etc items and costumes. Pages for gacha boxes, medals and costumes go deeper into those parts.

All file names below come from the source code that loads them. Anything marked not confirmed yet was not verified in code or config.

The shop is not one file. Each kind of item has its own table, and the server and the client both read it.

What you sell Server file (ls_gamesvr\config\) Client file (config\) Loaded by
Hero (mercenary) sp2_item_price.ini, sp2_setitem_info.ini sp2_setitem_info.ini ioItemPriceManager::LoadPriceInfo, ioSetItemInfoManager
Gear box (machine) sp2_extraitem_info.ini sp2_extraitem_info.ini ioExtraItemInfoManager.cpp
Etc item (packages, boxes, tickets) sp2_etcitem_info.ini sp2_etcitem_info.ini ioEtcItemManager
Costume sp2_costume_shop_goods.ini sp2_costume_shop_info.ini CostumeShopGoodsManager.cpp, ioCostumeShopInfoManager.cpp
Banners, text ads, links not read by the server sp2_shop.ini ioShopManager.cpp

Two facts decide how you work:

  • The server owns the price and the active flag. At login it sends the hero prices to the client. The client has no loader for sp2_item_price.ini (ioClassPrice::ApplyPrice takes a packet).
  • The client owns the look: name, icon, tab, order and tooltip text. If the client has no entry, the item is not shown.

If the two files disagree, the item shows wrong data or cannot be bought. After every change, compare the matching server and client entry.

  1. Open sp2_item_price.ini on the server. Find the block [CLASS_n], where n is the hero number (set_code minus 700000 in sp2_setitem_info.ini).

  2. Set the keys:

    [CLASS_5]
    ACTIVE = 1
    CASH = 2500
    BONUS_PESO = 0

    ACTIVE = 0 hides the hero from the shop. CASH is the gold price of the permanent hero. The loader also reads PC_ROOM_ACTIVE, FREE_DAY_ACTIVE, TYPE and SUBSCRIPTION_TYPE.

  3. The file header sets the hire lengths and price factors: [PESO_LIMIT_1], [CASH_LIMIT_1] with LIMIT_DATE (seconds) and LIMIT_PER (price factor). The peso base price is loaded from the database (the file says so). Which table holds it: not confirmed yet.

  4. If you add a hero beyond the current count, raise MAX_CLASS in [INFO]. Blocks past MAX_CLASS are never read.

  5. In the client’s sp2_setitem_info.ini, check the matching [set_item<n>]: shop_order (position, 0 means no fixed spot), shop_mark_type (badge), need_level_type1 and need_level1 (level to unlock), img_name (shop picture).

The full hero setup is in Add a hero.

Gear is sold as a “machine”. The block name is [random_machine<n>], and random_machine_cnt in [common_info] must be at least the highest n.

[random_machine2]
type = 5
machine_code = 1
package = 0
need_peso1 = 9800
need_cash = 0
bonus_peso = 0
sell_peso = 1960
need_level = 5
; client only
name = Basic Gear Supply
order = 100
icon = UIIconPack10#goods_extra1
group = 1
active = 1
  • need_peso1, need_peso2 … are prices for each period. The matching period<n> or period_time<n>_value sets the length in hours.
  • need_cash is the gold price. sell_peso is what the player gets when selling it back.
  • Keys after ;client only are read by the client. The server ignores them but the config set keeps both in one file.
  • active = 0 removes the box from the shop (ioRandomMachineGroup::LoadMachineBasicInfo, ioExtraItemInfoManager.cpp).

Etc items are blocks [etcitem<n>]. max in [common] must be at least the highest n, otherwise the client never reads the block.

[etcitem19]
name = Hero Summon Ticket
type = 1000022
can_sell = 0
sell_peso = 600
active1 = 1
value1 = 1
peso1 = 600
cash1 = 0
  1. Keep type unique. The client skips a duplicate (ioEtcItemManager::AddEtcItem) and also skips a type that the code does not know: the log shows UNKOWN ETCITEM TYPE. You cannot invent a new type in config only.
  2. peso1 and cash1 are the price for entry value1. For several offers use value2, peso2, cash2 and so on.
  3. The client file adds the shop look: shop_name1, shop_order1, shop_mark_type1, shop_tab_type1 (1 hero, 2 gear, 3 costume, 4 special), main_manual1, icon_name.
Goal Change
Hide it, keep owned copies working ACTIVE = 0 (hero), active = 0 (gear box, costume machine), active1 = 0 (etc item)
Cash only, no peso offer peso1 = 999999999 on the server and the client
Remove it completely Delete the block on both sides and lower the count key (max, machine_count, costume_cnt). Only for items nobody owns

The shipped configs use 999999999 for “not for sale”. The shop code has no special check for that number. It is only too high to pay.

Do not delete a block that players already own. Inventory entries still point to it. Hide it with the active flag instead.

The comments in the config files show the sale keys, written as sale_start_date_1, sale_end_date_1, sale_cash_1, sale_peso_1. The date format in the examples is yyyymmddhh. They are read through ioSaleManager (g_SaleMgr.LoadINI). What a sale price of -1 does: not confirmed yet. Server and client need the same dates.

2014 2019 2021
Server config in the repo ls_gamesvr\config\ and ls_mainsvr\config\ only shop, gacha and gear files in ls_gamesvr\config\ (the testbed holds the full set) ls_gamesvr\config\ and ls_mainsvr\config\
Client config inside rs.iop inside rs.iop plain config\ folder
Costume machine active key on the server not read read read
HERO_POSSIBLE flag in sp2_item_price.ini not in code in code, behind HERO_POSSIBLE_CHECK in code, behind HERO_POSSIBLE_CHECK
sp2_shop.ini on the server present, server does not load it not confirmed yet not confirmed yet

ls_mainsvr reads the event, clover and mileage shop files (EventGoodsManager.cpp). It does not load the gacha or costume goods files. Change the ls_gamesvr copies.

  1. Reload or restart the game server. A new client file needs a client restart.
  2. Open the shop. Look for the item in the right tab, with the right name and price.
  3. Buy it with a test account. A wrong price means the server file is not the one you edited. A missing item means the client entry is missing or its max / *_cnt count is too low.

Not confirmed yet: the exact reload command for a running server, and the shop tabs of the 2014 and 2019 clients (their config\ is packed).