summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/script_commands.txt38
-rw-r--r--src/map/clif.c12
-rw-r--r--src/map/clif.h16
-rw-r--r--src/map/npc.c60
4 files changed, 85 insertions, 41 deletions
diff --git a/doc/script_commands.txt b/doc/script_commands.txt
index bb714d856..898e4e331 100644
--- a/doc/script_commands.txt
+++ b/doc/script_commands.txt
@@ -299,6 +299,29 @@ type of shop will not allow you to sell items at it, you may only purchase
items here. The layout used to define sale items still count, and
"<price>" refers to how many points will be spent purchasing the them.
+** Define a trader NPC
+<map name>,<x>,<y>,<facing>%TAB%trader%TAB%<NPC Name>%TAB%<sprite id>,{<code>}
+-%TAB%trader%TAB%<NPC Name>%TAB%-1,{<code>}
+
+All the standards that are valid to script objects are also valid for trader objects
+(see ** Define an NPC object for more information).
+This will define a trader NPC, which can cause a shop, cashshop or market window
+to come up when clicked or called by other means. Unlike shop/cashshop NPCs this
+type will run a code and can change the items that are being sold over time without
+other NPC objects.
+The types that a trader object can have are the following:
+- NST_ZENY (0) Normal Zeny Shop (shop)
+- NST_CASH (1) Normal Cash Shop (cashshop)
+- NST_MARKET (2) Normal NPC Market Shop (where items have limited availability
+ and need to be refurbished)
+- NST_CUSTOM (3) Custom Shop (any currency, item/var/etca, check sample)
+Unless otherwise specified via *tradertype an trader object will be defined as
+NST_ZENY.
+
+Note: NST_MARKET is only available with PACKETVER 20131223 or newer.
+See '12 - NPC Trader-Related Commands' and /doc/sample/npc_trader_sample.txt for
+more information regarding how to use this NPC type.
+
** Define an warp/shop/cashshop/NPC duplicate.
warp: <map name>,<x>,<y>{,<facing>}%TAB%duplicate(<label>)%TAB%<NPC Name>%TAB%<spanx>,<spany>
@@ -1061,6 +1084,21 @@ Only the special labels which are not associated with any script command
are listed here. There are other kinds of labels which may be triggered in
a similar manner, but they are described with their associated commands.
+OnCountFunds:
+
+This special label is triggered when a player opens a trader NPC object that
+is NST_CUSTOM. It is used to define different currency types to the trader via
+*setcurrency. Should be used along with OnPayFunds, see /doc/sample/npc_trader_sample.txt
+for more information.
+
+OnPayFunds:
+
+This special label is triggered when a purchase is made on a trader NPC object
+that is NST_CUSTOM. Receives @price, total cost and @points, secondary input
+field for cash windows. It is used to remove items that are set as currency.
+Should be used along with OnCountFunds, see /doc/sample/npc_trader_sample.txt
+for more information.
+
On<label name>:
These special labels are used with Mob scripts mostly, and script commands
diff --git a/src/map/clif.c b/src/map/clif.c
index 1da6070e8..0fc1fe044 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -15561,20 +15561,10 @@ void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd) {
WFIFOSET(fd,WFIFOW(fd,2));
}
-
/// Cashshop Buy Ack (ZC_PC_CASH_POINT_UPDATE).
/// 0289 <cash point>.L <error>.W
/// 0289 <cash point>.L <kafra point>.L <error>.W (PACKETVER >= 20070711)
-/// error:
-/// 0 = The deal has successfully completed. (ERROR_TYPE_NONE)
-/// 1 = The Purchase has failed because the NPC does not exist. (ERROR_TYPE_NPC)
-/// 2 = The Purchase has failed because the Kafra Shop System is not working correctly. (ERROR_TYPE_SYSTEM)
-/// 3 = You are over your Weight Limit. (ERROR_TYPE_INVENTORY_WEIGHT)
-/// 4 = You cannot purchase items while you are in a trade. (ERROR_TYPE_EXCHANGE)
-/// 5 = The Purchase has failed because the Item Information was incorrect. (ERROR_TYPE_ITEM_ID)
-/// 6 = You do not have enough Kafra Credit Points. (ERROR_TYPE_MONEY)
-/// 7 = You can purchase up to 10 items.
-/// 8 = Some items could not be purchased.
+/// For error return codes see enum cashshop_error@clif.h
void clif_cashshop_ack(struct map_session_data* sd, int error) {
struct npc_data *nd;
int fd = sd->fd;
diff --git a/src/map/clif.h b/src/map/clif.h
index f54c4afce..d0444f9fe 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -349,6 +349,22 @@ enum clif_messages {
};
/**
+ * Used to answer CZ_PC_BUY_CASH_POINT_ITEM (clif_parse_cashshop_buy)
+ **/
+enum cashshop_error {
+ ERROR_TYPE_NONE = 0, // The deal has successfully completed. (ERROR_TYPE_NONE)
+ ERROR_TYPE_NPC, // The Purchase has failed because the NPC does not exist. (ERROR_TYPE_NPC)
+ ERROR_TYPE_SYSTEM, // The Purchase has failed because the Kafra Shop System is not working correctly. (ERROR_TYPE_SYSTEM)
+ ERROR_TYPE_INVENTORY_WEIGHT, // You are over your Weight Limit. (ERROR_TYPE_INVENTORY_WEIGHT)
+ ERROR_TYPE_EXCHANGE, // You cannot purchase items while you are in a trade. (ERROR_TYPE_EXCHANGE)
+ ERROR_TYPE_ITEM_ID, // The Purchase has failed because the Item Information was incorrect. (ERROR_TYPE_ITEM_ID)
+ ERROR_TYPE_MONEY, // You do not have enough Kafra Credit Points. (ERROR_TYPE_MONEY)
+ // Unofficial type names
+ ERROR_TYPE_QUANTITY, // You can purchase up to 10 items. (ERROR_TYPE_QUANTITY)
+ ERROR_TYPE_NOT_ALL, // Some items could not be purchased. (ERROR_TYPE_NOT_ALL)
+};
+
+/**
* Color Table
**/
enum clif_colors {
diff --git a/src/map/npc.c b/src/map/npc.c
index 289c42d44..247d7109b 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -1298,23 +1298,23 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns
unsigned short shop_size = 0;
if( sd->state.trading )
- return 4;
+ return ERROR_TYPE_EXCHANGE;
if( count <= 0 )
- return 5;
+ return ERROR_TYPE_ITEM_ID;
if( points < 0 )
- return 6;
+ return ERROR_TYPE_MONEY;
if( !(nd = (struct npc_data *)map->id2bl(sd->npc_shopid)) )
- return 1;
+ return ERROR_TYPE_NPC;
if( nd->subtype != CASHSHOP ) {
if( nd->subtype == SCRIPT && nd->u.scr.shop && nd->u.scr.shop->type != NST_ZENY && nd->u.scr.shop->type != NST_MARKET ) {
shop = nd->u.scr.shop->item;
shop_size = nd->u.scr.shop->items;
} else
- return 1;
+ return ERROR_TYPE_NPC;
} else {
shop = nd->u.shop.shop_item;
shop_size = nd->u.shop.count;
@@ -1330,11 +1330,11 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns
amount = item_list[i*2+0];
if( !itemdb->exists(nameid) || amount <= 0 )
- return 5;
+ return ERROR_TYPE_ITEM_ID;
ARR_FIND(0,shop_size,j,shop[j].nameid == nameid);
if( j == shop_size || shop[j].value <= 0 )
- return 5;
+ return ERROR_TYPE_ITEM_ID;
if( !itemdb->isstackable(nameid) && amount > 1 ) {
ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %d!\n",
@@ -1347,7 +1347,7 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns
new_++;
break;
case ADDITEM_OVERAMOUNT:
- return 3;
+ return ERROR_TYPE_INVENTORY_WEIGHT;
}
vt += shop[j].value * amount;
@@ -1355,20 +1355,20 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns
}
if( w + sd->weight > sd->max_weight )
- return 3;
+ return ERROR_TYPE_INVENTORY_WEIGHT;
if( pc->inventoryblank(sd) < new_ )
- return 3;
+ return ERROR_TYPE_INVENTORY_WEIGHT;
if( points > vt ) points = vt;
// Payment Process ----------------------------------------------------
if( nd->subtype == SCRIPT && nd->u.scr.shop->type == NST_CUSTOM ) {
if( !npc->trader_pay(nd,sd,vt,points) )
- return 6;
+ return ERROR_TYPE_MONEY;
} else {
if( sd->kafraPoints < points || sd->cashPoints < (vt - points) )
- return 6;
+ return ERROR_TYPE_MONEY;
pc->paycash(sd,vt,points);
}
// Delivery Process ----------------------------------------------------
@@ -1387,7 +1387,7 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns
}
}
- return 0;
+ return ERROR_TYPE_NONE;
}
//npc_buylist for script-controlled shops.
@@ -1631,26 +1631,26 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po
unsigned short shop_size = 0;
if( amount <= 0 )
- return 5;
+ return ERROR_TYPE_ITEM_ID;
if( points < 0 )
- return 6;
+ return ERROR_TYPE_MONEY;
if( sd->state.trading )
- return 4;
+ return ERROR_TYPE_EXCHANGE;
if( !(nd = (struct npc_data *)map->id2bl(sd->npc_shopid)) )
- return 1;
+ return ERROR_TYPE_NPC;
if( (item = itemdb->exists(nameid)) == NULL )
- return 5; // Invalid Item
+ return ERROR_TYPE_ITEM_ID; // Invalid Item
if( nd->subtype != CASHSHOP ) {
if( nd->subtype == SCRIPT && nd->u.scr.shop && nd->u.scr.shop->type != NST_ZENY && nd->u.scr.shop->type != NST_MARKET ) {
shop = nd->u.scr.shop->item;
shop_size = nd->u.scr.shop->items;
} else
- return 1;
+ return ERROR_TYPE_NPC;
} else {
shop = nd->u.shop.shop_item;
shop_size = nd->u.shop.count;
@@ -1659,10 +1659,10 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po
ARR_FIND(0, shop_size, i, shop[i].nameid == nameid);
if( i == shop_size )
- return 5;
+ return ERROR_TYPE_ITEM_ID;
if( shop[i].value <= 0 )
- return 5;
+ return ERROR_TYPE_ITEM_ID;
if(!itemdb->isstackable(nameid) && amount > 1) {
ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %d!\n",
@@ -1673,15 +1673,15 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po
switch( pc->checkadditem(sd, nameid, amount) ) {
case ADDITEM_NEW:
if( pc->inventoryblank(sd) == 0 )
- return 3;
+ return ERROR_TYPE_INVENTORY_WEIGHT;
break;
case ADDITEM_OVERAMOUNT:
- return 3;
+ return ERROR_TYPE_INVENTORY_WEIGHT;
}
w = item->weight * amount;
if( w + sd->weight > sd->max_weight )
- return 3;
+ return ERROR_TYPE_INVENTORY_WEIGHT;
if( (double)shop[i].value * amount > INT_MAX ) {
ShowWarning("npc_cashshop_buy: Item '%s' (%d) price overflow attempt!\n", item->name, nameid);
@@ -1689,7 +1689,7 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po
nd->exname, map->list[nd->bl.m].name, nd->bl.x, nd->bl.y,
sd->status.name, sd->status.account_id, sd->status.char_id,
shop[i].value, amount);
- return 5;
+ return ERROR_TYPE_ITEM_ID;
}
price = shop[i].value * amount;
@@ -1699,10 +1699,10 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po
if( nd->subtype == SCRIPT && nd->u.scr.shop->type == NST_CUSTOM ) {
if( !npc->trader_pay(nd,sd,price,points) )
- return 6;
+ return ERROR_TYPE_MONEY;
} else {
if( (sd->kafraPoints < points) || (sd->cashPoints < price - points) )
- return 6;
+ return ERROR_TYPE_MONEY;
pc->paycash(sd, price, points);
}
@@ -1716,7 +1716,7 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po
pc->additem(sd,&item_tmp, amount, LOG_TYPE_NPC);
}
- return 0;
+ return ERROR_TYPE_NONE;
}
/// Player item purchase from npc shop.
@@ -2612,7 +2612,7 @@ const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* s
enum npc_subtype type;
if( strcmp(w1,"-") == 0 ) {
- // 'floating' shop?
+ // 'floating' shop
x = y = dir = 0;
m = -1;
} else {// w1=<map name>,<x>,<y>,<facing>
@@ -2711,7 +2711,7 @@ const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* s
nd->dir = dir;
if( map->list[nd->bl.m].users )
clif->spawn(&nd->bl);
- } else {// 'floating' shop?
+ } else {// 'floating' shop
map->addiddb(&nd->bl);
}
strdb_put(npc->name_db, nd->exname, nd);