Market and Player Trading
This guide shows how to change the player market (the “trade” window where players sell gear to each other for peso). It covers the fees, the level limits, the listing time, the minimum price, and the rule that decides which gear may be listed. Read it with Gear Upgrade and Compound Rates and Gacha Boxes, because the gear boxes decide whether a gear can be sold.
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 market sells gear only (PRESENT_EXTRAITEM). User::OnTradeCreate returns an error for any other type.
How the market is built
Section titled “How the market is built”| Part | File | Read by |
|---|---|---|
| Fees, levels, listing time | ls_gamesvr\config\sp2_trade_info.ini, section [common] |
TradeInfoManager.cpp (ls_gamesvr\NodeInfo\) |
| Same values for the window, plus the minimum price | config\sp2_trade_info.ini in the client |
TradeInfoManager.cpp (LSClient\) |
| Who may sell which gear | sp2_extraitem_info.ini (item<n>_trade, tradetype*) |
ioExtraItemInfoManager.cpp |
| Unlock item | etc item type 1000046 |
ioEtcItemTradeStateChange::_OnUse (ioEtcItem.cpp) |
| Mail texts for sold, cancelled and expired offers | sp2_present_helper.ini, section [TradePresent] |
ioPresentHelper::LoadTradePresent |
| List storage | table userTradeDB and procedures game_trade_* |
DB scripts in the testbed db\ folders |
The server owns the money. The client file gives the window the same numbers for display and holds one rule the server does not check (the minimum price). After every change, compare the server and client files.
The settings
Section titled “The settings”[common]Change = 1register_period = 30register_limit_level = 20item_buy_limit_level = 15register_tex = 0.05fbuy_tex = 0.1fpc_room_register_tex = 0.025fpc_room_buy_tex = 0.05f| Key | Used for | Server | Client |
|---|---|---|---|
register_period |
How long an offer stays listed (days is the likely unit; the unit is not stated in code) | yes | yes (window text) |
register_limit_level |
Level needed to list gear | yes | no use found in the client windows |
item_buy_limit_level |
Level needed to buy | yes | yes |
register_tex |
Listing fee, a fraction of the price. 0.05 means 5 percent | yes | yes |
buy_tex |
Extra charge for the buyer, a fraction of the price | yes | yes |
pc_room_register_tex, pc_room_buy_tex |
Same fees for internet cafe players | yes | yes |
Change |
Reload flag read by CheckNeedReload |
yes | no |
register_limit_peso |
Minimum price of an offer | not read | yes |
trade_state_change_item_level |
Level needed to use the unlock item | not read | yes |
trade_list_request_time |
Milliseconds between list refreshes (default 60000) | not read | yes |
Notes from the code:
- The server uses the key
register_tex, the file spells it “tex” for tax. Keep the spelling. - Listing:
User::OnTradeCreatechecks the grade level againstregister_limit_level, then chargesprice * register_texas peso. If the player has less, the error isTRADE_CREATE_PESO. The gear is deleted from the inventory and the row goes touserTradeDBwith the listing time. - Buying: the buyer needs
price + price * buy_tex(ServerNode::OnTradeGetInfoOK). The server takes that amount. The seller is paid through the postbox (mail text id fromTradeSellMent,TRADE_S_SELL_COMPLETEinServerNode.cpp). The exact seller amount was not traced to the end. Not confirmed yet. - Minimum price: only the client enforces
register_limit_peso(TradeItemRegisterWnd.cpp). The player types the price in units of 10000 peso. The server code ofOnTradeCreatehas no price check, so a changed client could list below the minimum. A maximum price: not confirmed yet. - The shipped client file has
register_limit_peso = 50000andtrade_state_change_item_level = 20.
Change the fees and limits
Section titled “Change the fees and limits”- Edit
sp2_trade_info.inion the server. KeepChange = 1. The line that would reset the flag is commented out, so the file is reloaded at each check while the flag is 1. How often the check runs: not confirmed yet. - Edit the client file with the same values for
register_period,register_limit_level,item_buy_limit_level,register_tex,buy_texand the two internet cafe values. The window shows the fee from the client copy, but the server charges its own. - Set
register_limit_pesoandtrade_state_change_item_levelin the client file only. - If the two files differ, the window shows one fee and the server takes another. This is the most common market mistake.
To close the market for a version, the simplest way found in the code is the gear rule below (no gear can be listed). A switch that hides the trade window: not confirmed yet.
Decide which gear may be sold
Section titled “Decide which gear may be sold”A gear carries a trade state (m_iTradeState in ioUserExtraItem.h):
| Value | Name | Meaning |
|---|---|---|
| 0 | EET_DISABLE |
cannot be traded |
| 1 | EET_NORMAL |
tradable after it is unlocked |
| 2 | EET_ENABLE |
can be listed now |
| 3 | EET_REGISTER |
is listed |
OnTradeCreate only accepts state 2. A gear gets its state in one of three ways:
-
From the gear box. In
sp2_extraitem_info.inieach[random_machineN]hastradetype_cntand groupstradetypeN_rateKandtradetypeN_valueK(Kfrom 1 to 3,TRADE_TYPE_MAX). Each item lineitem<n>_tradepicks the group (default 1). The roll uses the rates as weights and the value as the state.tradetype_cnt = 1tradetype1_rate1 = 100tradetype1_value1 = 0tradetype1_rate2 = 0tradetype1_value2 = 1In the 2021 testbed file, 144 rate rows are above 0, and the values used are 0 (no trade), 1 and 2. The first group above gives state 0 with 100 percent, so those gears can never be sold.
-
By the unlock item. Etc item
1000046(EIT_ETC_TRADE_STATE_CHANGE) turns a gear with state 1 into state 2. It refuses a gear in another state and a gear that a hero wears (TRADE_STATE_CHANGE_EQUIP_ITEM). The item is used up. The client requirestrade_state_change_item_level. -
After a failed or expired offer. When an offer is cancelled or expires, the gear returns as a postbox present and gets state 2 again (
User.cpp,PRESENT_TRADE_CANCEL_MENTandPRESENT_TRADE_TIMEOUT_MENT). Only permanent gear (period 0) gets this.
Power-up sets the state back to 0 (ioPowerUpManager.cpp). Gear received as a present is created with state 0, except returned market gear (User.cpp).
To make a gear box give sellable gear, set a group with valueK = 2 for state 2, or valueK = 1 and let players buy the unlock item.
Mail texts
Section titled “Mail texts”sp2_present_helper.ini section [TradePresent] holds the postbox text ids for buy, sell, cancel and time out (TradeBuyMent, TradeSellMent, TradeCancelMent, TradeTimeOutMent). The shipped values are 37 to 40 in all three versions. The texts themselves are in the client text table. See Client Text and Translation. The keys PresentAlarm, SellPresentAlarm and PresentPeriod are read too. Their values in the shipped file were not checked. Not confirmed yet.
The database side
Section titled “The database side”The list lives in userTradeDB (columns idx, accountIDX, itemType, value1, value2, price, mcustom, fcustom, userIP, periodDate, regDate). The procedures are game_trade_add, game_trade_delete, game_trade_get_list and game_trade_get_self_index. The 2019 and 2021 scripts also have game_trade_get_list_original, and a log table log_data_trade. value1 and value2 hold the gear code and the level. The list page is read newest first (idx descending). How the expiry is triggered: not confirmed yet.
Differences between versions
Section titled “Differences between versions”| 2014 | 2019 | 2021 | |
|---|---|---|---|
Server code of TradeInfoManager and OnTradeCreate |
same keys | same keys | same keys |
| Fees in the shipped server file | register_tex 0.01, buy_tex 0.01 |
0.05, 0.1 (testbed) |
0.05, 0.1 |
Client sp2_trade_info.ini |
packed, not read | packed, not read | register_limit_peso = 50000 |
tradetype value 2 rows in the testbed gear file |
48 | 52 | 52 |
game_trade_get_list_original procedure |
no | yes | yes |
Log table log_data_trade |
stub only | yes | yes |
The 2014 testbed file also has a commented alternate register_limit_level of 99. The 2014 server fees are low (1 percent). Whether the 2014 client shows the same fees: not confirmed yet, its file is packed.
Check your change
Section titled “Check your change”- Reload or restart the game server. A client file change needs a client restart.
- List a gear with a test account that has the level and state 2. Check the peso drop equals the price times
register_tex. - Buy it with a second test account. Check the peso drop equals the price times
1 + buy_tex. - Wait for or shorten the listing time to test the return mail. Check that the gear comes back with state 2.
Not confirmed yet: the exact reload interval, the seller payout amount, the maximum price, and the 2014 and 2019 client file contents.
