Added support for unlimited supplies in market shops (#6571)
Fixes #6569 Thanks to @JohnnyPlayy, @Balferian and @Toshiro90 Co-authored-by: Aleos <aleos89@users.noreply.github.com>
This commit is contained in:
parent
3da8426fe7
commit
6ccf15330e
@ -291,7 +291,7 @@ these floating NPC objects are for. More on that below.
|
||||
-%TAB%pointshop%TAB%<NPC Name>%TAB%<sprite id>,<costvariable>{:<discount>},<itemid>:<price>{,<itemid>:<price>...}
|
||||
<map name>,<x>,<y>,<facing>%TAB%pointshop%TAB%<NPC Name>%TAB%<sprite id>,<costvariable>{:<discount>},<itemid>:<price>{,<itemid>:<price>...}
|
||||
|
||||
<map name>,<x>,<y>,<facing>%TAB%marketshop%TAB%<NPC Name>%TAB%<sprite id>,<itemid>:<price>:<quantity>{,<itemid>:<price>:<quantity>...}
|
||||
<map name>,<x>,<y>,<facing>%TAB%marketshop%TAB%<NPC Name>%TAB%<sprite id>,<itemid>:<price>:<stock>{,<itemid>:<price>:<stock>...}
|
||||
|
||||
Note: Additionally barter shops can be defined in npc/barters.yml
|
||||
|
||||
@ -320,6 +320,9 @@ temporary character variables, permanent local account variables or permanent gl
|
||||
variables. These variables must be of integer type, not string. 'discount' flag is an
|
||||
optional value which makes the price at that shop become affected by discount skill.
|
||||
|
||||
"marketshop" can have limited quantity of an item in stock.
|
||||
Use -1 in the stock field to have unlimited stock in a marketshop.
|
||||
|
||||
** Define an warp/shop/cashshop/itemshop/pointshop/NPC duplicate.
|
||||
|
||||
warp/warp2: <map name>,<x>,<y>,<facing>%TAB%duplicate(<label>)%TAB%<NPC Name>%TAB%<spanx>,<spany>
|
||||
@ -7254,6 +7257,7 @@ A full example of a dynamic shop can be found in doc/sample/npc_dynamic_shop.txt
|
||||
---------------------------------------
|
||||
|
||||
*npcshopitem "<name>",<item id>,<price>{,<item id>,<price>{,<item id>,<price>{,...}}};
|
||||
*npcshopitem "<name>",<item id>,<price>,<stock>{,<item id>,<price>,<stock>{,<item id>,<price>,<stock>{,...}}};
|
||||
|
||||
This command lets you override the contents of an existing NPC shop or cashshop. The
|
||||
current sell list will be wiped, and only the items specified with the price
|
||||
@ -7263,12 +7267,12 @@ The function returns 1 if shop was updated successfully, or 0 if not found.
|
||||
|
||||
NOTES:
|
||||
- That you cannot use -1 to specify default selling price!
|
||||
- If attached shop type is market shop, need an extra param after price, it's <qty>
|
||||
and make sure don't add duplication item!
|
||||
- If the attached shop type is a market shop, notice that there is an extra parameter after price, <stock>. Make sure to not add duplicate items! For unlimited stock use -1.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*npcshopadditem "<name>",<item id>,<price>{,<item id>,<price>{,<item id>,<price>{,...}}};
|
||||
*npcshopadditem "<name>",<item id>,<price>,<stock>{,<item id>,<price>,<stock>{,<item id>,<price>,<stock>{,...}}};
|
||||
|
||||
This command will add more items at the end of the selling list for the
|
||||
specified NPC shop or cashshop. If you specify an item already for sell, that item will
|
||||
@ -7278,8 +7282,8 @@ The function returns 1 if shop was updated successfully, or 0 if not found.
|
||||
|
||||
NOTES:
|
||||
- That you cannot use -1 to specify default selling price!
|
||||
- If attached shop type is market shop, need an extra param after price, it's <qty>
|
||||
and make sure don't add duplication item!
|
||||
- If attached shop type is market shop, need an extra param after price, it's <stock>
|
||||
and make sure don't add duplication item! For unlimited stock use -1.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
@ -7317,9 +7321,9 @@ NOTES:
|
||||
|
||||
*npcshopupdate "<name>",<item_id>,<price>{,<stock>}
|
||||
|
||||
Update an entry from shop. If price is 0 means don't change the price, maybe used for
|
||||
marketshop to update the stock quantity. Except marketshop type, 'stock' value means
|
||||
nothing.
|
||||
Update an entry from a shop. If the price is 0 it won't be changed. May also be used for
|
||||
marketshop to update the stock quantity. For unlimited stock, use -1.
|
||||
For other shop types, the stock value has no effect.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
|
@ -867,7 +867,7 @@ CREATE TABLE IF NOT EXISTS `market` (
|
||||
`name` varchar(50) NOT NULL DEFAULT '',
|
||||
`nameid` int(10) UNSIGNED NOT NULL,
|
||||
`price` INT(11) UNSIGNED NOT NULL,
|
||||
`amount` SMALLINT(5) UNSIGNED NOT NULL,
|
||||
`amount` INT(11) NOT NULL,
|
||||
`flag` TINYINT(2) UNSIGNED NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`name`,`nameid`)
|
||||
) ENGINE = MyISAM;
|
||||
|
3
sql-files/upgrades/upgrade_20220204.sql
Normal file
3
sql-files/upgrades/upgrade_20220204.sql
Normal file
@ -0,0 +1,3 @@
|
||||
ALTER TABLE `market`
|
||||
MODIFY `amount` INT(11) NOT NULL
|
||||
;
|
@ -2283,6 +2283,11 @@ void clif_npc_market_open(struct map_session_data *sd, struct npc_data *nd) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Out of stock
|
||||
if( item->qty == 0 ){
|
||||
continue;
|
||||
}
|
||||
|
||||
p->list[count].nameid = client_nameid( item->nameid );
|
||||
p->list[count].type = itemtype( item->nameid );
|
||||
p->list[count].price = item->value;
|
||||
@ -2312,20 +2317,18 @@ void clif_parse_NPCMarketClosed(int fd, struct map_session_data *sd) {
|
||||
|
||||
/// Purchase item from Market shop.
|
||||
/// 0x9d7 <packet len>.W <count>.B { <name id>.W <qty>.W <price>.L }* (ZC_NPC_MARKET_PURCHASE_RESULT)
|
||||
void clif_npc_market_purchase_ack(struct map_session_data *sd, e_purchase_result res, uint8 n, struct s_npc_buy_list *list) {
|
||||
void clif_npc_market_purchase_ack( struct map_session_data *sd, e_purchase_result res, std::vector<s_npc_buy_list>& list ){
|
||||
#if PACKETVER >= 20131223
|
||||
nullpo_retv( sd );
|
||||
nullpo_retv( list );
|
||||
|
||||
struct npc_data *nd = map_id2nd( sd->npc_shopid );
|
||||
|
||||
nullpo_retv( nd );
|
||||
|
||||
int fd = sd->fd;
|
||||
struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT *p = (struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT *)packet_buffer;
|
||||
|
||||
WFIFOHEAD( fd, sizeof( struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT ) + n * sizeof( struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT_sub ) );
|
||||
struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT *p = (struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT *)WFIFOP( fd, 0 );
|
||||
p->PacketType = HEADER_ZC_NPC_MARKET_PURCHASE_RESULT;
|
||||
p->PacketLength = sizeof( struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT );
|
||||
|
||||
#if PACKETVER_MAIN_NUM >= 20190807 || PACKETVER_RE_NUM >= 20190807 || PACKETVER_ZERO_NUM >= 20190814
|
||||
p->result = ( res == e_purchase_result::PURCHASE_SUCCEED ? 0 : -1 );
|
||||
@ -2333,10 +2336,8 @@ void clif_npc_market_purchase_ack(struct map_session_data *sd, e_purchase_result
|
||||
p->result = ( res == e_purchase_result::PURCHASE_SUCCEED ? 1 : 0 );
|
||||
#endif
|
||||
|
||||
int count = 0;
|
||||
|
||||
if( p->result ){
|
||||
for( int i = 0, j; i < n; i++ ){
|
||||
for( int i = 0, j, count = 0; i < list.size(); i++ ){
|
||||
ARR_FIND( 0, nd->u.shop.count, j, list[i].nameid == nd->u.shop.shop_item[j].nameid );
|
||||
|
||||
// Not found
|
||||
@ -2347,12 +2348,12 @@ void clif_npc_market_purchase_ack(struct map_session_data *sd, e_purchase_result
|
||||
p->list[count].ITID = client_nameid( list[i].nameid );
|
||||
p->list[count].qty = list[i].qty;
|
||||
p->list[count].price = nd->u.shop.shop_item[j].value;
|
||||
p->PacketLength += sizeof( struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT_sub );
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
p->PacketLength = sizeof( struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT ) + count * sizeof( struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT_sub );
|
||||
WFIFOSET( fd, p->PacketLength );
|
||||
clif_send( p, p->PacketLength, &sd->bl, SELF );
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -2371,20 +2372,21 @@ void clif_parse_NPCMarketPurchase(int fd, struct map_session_data *sd) {
|
||||
|
||||
int count = ( p->PacketLength - sizeof( struct packet_npc_market_purchase ) ) / sizeof( struct packet_npc_market_purchase_sub );
|
||||
|
||||
struct s_npc_buy_list *list;
|
||||
std::vector<s_npc_buy_list> items;
|
||||
|
||||
CREATE( list, struct s_npc_buy_list, count );
|
||||
items.reserve( count );
|
||||
|
||||
// Sadly order is reverse
|
||||
for( int i = 0; i < count; i++ ){
|
||||
list[i].nameid = p->list[i].ITID;
|
||||
list[i].qty = p->list[i].qty;
|
||||
s_npc_buy_list item = {};
|
||||
|
||||
item.nameid = p->list[i].ITID;
|
||||
item.qty = p->list[i].qty;
|
||||
|
||||
items.push_back( item );
|
||||
}
|
||||
|
||||
e_purchase_result res = npc_buylist( sd, count, list );
|
||||
clif_npc_market_purchase_ack( sd, res, count, list );
|
||||
|
||||
aFree( list );
|
||||
e_purchase_result res = npc_buylist( sd, items );
|
||||
clif_npc_market_purchase_ack( sd, res, items );
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -12319,8 +12321,22 @@ void clif_parse_NpcBuyListSend( int fd, struct map_session_data* sd ){
|
||||
|
||||
if( sd->state.trading || !sd->npc_shopid )
|
||||
result = e_purchase_result::PURCHASE_FAIL_MONEY;
|
||||
else
|
||||
result = npc_buylist( sd, n, (struct s_npc_buy_list*)p->items );
|
||||
else{
|
||||
std::vector<s_npc_buy_list> items = {};
|
||||
|
||||
items.reserve( n );
|
||||
|
||||
for( uint16 i = 0; i < n; i++ ){
|
||||
s_npc_buy_list item = {};
|
||||
|
||||
item.nameid = p->items[i].itemId;
|
||||
item.qty = p->items[i].amount;
|
||||
|
||||
items.push_back( item );
|
||||
}
|
||||
|
||||
result = npc_buylist( sd, items );
|
||||
}
|
||||
|
||||
sd->npc_shopid = 0; //Clear shop data.
|
||||
clif_npc_buy_result(sd, result);
|
||||
@ -17321,7 +17337,20 @@ void clif_parse_npccashshop_buy( int fd, struct map_session_data *sd ){
|
||||
return;
|
||||
}
|
||||
|
||||
clif_cashshop_ack( sd, npc_cashshop_buylist( sd, p->kafraPoints, p->count, p->items ) );
|
||||
std::vector<s_npc_buy_list> item_list = {};
|
||||
|
||||
item_list.reserve( p->count );
|
||||
|
||||
for( int i = 0; i < p->count; i++ ){
|
||||
s_npc_buy_list item = {};
|
||||
|
||||
item.nameid = p->items[i].itemId;
|
||||
item.qty = p->items[i].amount;
|
||||
|
||||
item_list.push_back( item );
|
||||
}
|
||||
|
||||
clif_cashshop_ack( sd, npc_cashshop_buylist( sd, p->kafraPoints, item_list ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -2411,8 +2411,7 @@ static enum e_CASHSHOP_ACK npc_cashshop_process_payment(struct npc_data *nd, int
|
||||
* @param item_list: List of items to purchase
|
||||
* @return clif_cashshop_ack value to display
|
||||
*/
|
||||
int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, struct PACKET_CZ_PC_BUY_CASH_POINT_ITEM_sub* item_list)
|
||||
{
|
||||
int npc_cashshop_buylist( struct map_session_data *sd, int points, std::vector<s_npc_buy_list>& item_list ){
|
||||
int i, j, amount, new_, w, vt;
|
||||
t_itemid nameid;
|
||||
struct npc_data *nd = (struct npc_data *)map_id2bl(sd->npc_shopid);
|
||||
@ -2429,10 +2428,10 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, str
|
||||
vt = 0; // Global Value
|
||||
|
||||
// Validating Process ----------------------------------------------------
|
||||
for( i = 0; i < count; i++ )
|
||||
for( i = 0; i < item_list.size(); i++ )
|
||||
{
|
||||
nameid = item_list[i].itemId;
|
||||
amount = item_list[i].amount;
|
||||
nameid = item_list[i].nameid;
|
||||
amount = item_list[i].qty;
|
||||
id = itemdb_exists(nameid);
|
||||
|
||||
if( !id || amount <= 0 )
|
||||
@ -2442,12 +2441,12 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, str
|
||||
if( j == nd->u.shop.count || nd->u.shop.shop_item[j].value <= 0 )
|
||||
return ERROR_TYPE_ITEM_ID;
|
||||
|
||||
nameid = item_list[i].itemId = nd->u.shop.shop_item[j].nameid; //item_avail replacement
|
||||
nameid = item_list[i].nameid = nd->u.shop.shop_item[j].nameid; //item_avail replacement
|
||||
|
||||
if( !itemdb_isstackable2(id) && amount > 1 )
|
||||
{
|
||||
ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %u!\n", sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid);
|
||||
amount = item_list[i].amount = 1;
|
||||
amount = item_list[i].qty = 1;
|
||||
}
|
||||
|
||||
if( nd->master_nd ) { // Script-controlled shops decide by themselves, what can be bought and for what price.
|
||||
@ -2468,7 +2467,7 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, str
|
||||
}
|
||||
|
||||
if (nd->master_nd) //Script-based shops.
|
||||
return npc_buylist_sub(sd,count,(struct s_npc_buy_list*)item_list,nd->master_nd);
|
||||
return npc_buylist_sub(sd,item_list,nd->master_nd);
|
||||
|
||||
if( w + sd->weight > sd->max_weight )
|
||||
return ERROR_TYPE_INVENTORY_WEIGHT;
|
||||
@ -2480,9 +2479,9 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, str
|
||||
return res;
|
||||
|
||||
// Delivery Process ----------------------------------------------------
|
||||
for( i = 0; i < count; i++ ) {
|
||||
nameid = item_list[i].itemId;
|
||||
amount = item_list[i].amount;
|
||||
for( i = 0; i < item_list.size(); i++ ) {
|
||||
nameid = item_list[i].nameid;
|
||||
amount = item_list[i].qty;
|
||||
|
||||
if( !pet_create_egg(sd,nameid) ) {
|
||||
struct item item_tmp;
|
||||
@ -2663,16 +2662,16 @@ int npc_cashshop_buy(struct map_session_data *sd, t_itemid nameid, int amount, i
|
||||
* @param item_list: List of items
|
||||
* @param nd: Attached NPC
|
||||
*/
|
||||
static int npc_buylist_sub(struct map_session_data* sd, uint16 n, struct s_npc_buy_list *item_list, struct npc_data* nd) {
|
||||
static int npc_buylist_sub(struct map_session_data* sd, std::vector<s_npc_buy_list>& item_list, struct npc_data* nd) {
|
||||
char npc_ev[EVENT_NAME_LENGTH];
|
||||
int i, key_nameid = 0, key_amount = 0;
|
||||
int key_nameid = 0, key_amount = 0;
|
||||
|
||||
// discard old contents
|
||||
script_cleararray_pc( sd, "@bought_nameid" );
|
||||
script_cleararray_pc( sd, "@bought_quantity" );
|
||||
|
||||
// save list of bought items
|
||||
for (i = 0; i < n; i++) {
|
||||
for( int i = 0; i < item_list.size(); i++ ){
|
||||
script_setarray_pc( sd, "@bought_nameid", i, item_list[i].nameid, &key_nameid );
|
||||
script_setarray_pc( sd, "@bought_quantity", i, item_list[i].qty, &key_amount );
|
||||
}
|
||||
@ -2691,23 +2690,23 @@ static int npc_buylist_sub(struct map_session_data* sd, uint16 n, struct s_npc_b
|
||||
* @param item_list: List of items
|
||||
* @return result code for clif_parse_NpcBuyListSend/clif_npc_market_purchase_ack
|
||||
*/
|
||||
e_purchase_result npc_buylist(struct map_session_data* sd, uint16 n, struct s_npc_buy_list *item_list) {
|
||||
e_purchase_result npc_buylist( struct map_session_data* sd, std::vector<s_npc_buy_list>& item_list ){
|
||||
struct npc_data* nd;
|
||||
struct npc_item_list *shop = NULL;
|
||||
double z;
|
||||
int i,j,k,w,skill,new_;
|
||||
int j,k,w,skill,new_;
|
||||
uint8 market_index[MAX_INVENTORY];
|
||||
|
||||
nullpo_retr(e_purchase_result::PURCHASE_FAIL_COUNT, sd);
|
||||
nullpo_retr(e_purchase_result::PURCHASE_FAIL_COUNT, item_list);
|
||||
|
||||
nd = npc_checknear(sd,map_id2bl(sd->npc_shopid));
|
||||
if( nd == NULL )
|
||||
return e_purchase_result::PURCHASE_FAIL_COUNT;
|
||||
if( nd->subtype != NPCTYPE_SHOP && nd->subtype != NPCTYPE_MARKETSHOP )
|
||||
return e_purchase_result::PURCHASE_FAIL_COUNT;
|
||||
if (!item_list || !n)
|
||||
if( item_list.empty() ){
|
||||
return e_purchase_result::PURCHASE_FAIL_COUNT;
|
||||
}
|
||||
|
||||
z = 0;
|
||||
w = 0;
|
||||
@ -2717,7 +2716,7 @@ e_purchase_result npc_buylist(struct map_session_data* sd, uint16 n, struct s_np
|
||||
|
||||
memset(market_index, 0, sizeof(market_index));
|
||||
// process entries in buy list, one by one
|
||||
for( i = 0; i < n; ++i ) {
|
||||
for( int i = 0; i < item_list.size(); ++i ){
|
||||
t_itemid nameid;
|
||||
unsigned short amount;
|
||||
int value;
|
||||
@ -2734,7 +2733,7 @@ e_purchase_result npc_buylist(struct map_session_data* sd, uint16 n, struct s_np
|
||||
|
||||
#if PACKETVER >= 20131223
|
||||
if (nd->subtype == NPCTYPE_MARKETSHOP) {
|
||||
if (item_list[i].qty > shop[j].qty)
|
||||
if (shop[j].qty >= 0 && item_list[i].qty > shop[j].qty)
|
||||
return e_purchase_result::PURCHASE_FAIL_COUNT;
|
||||
market_index[i] = j;
|
||||
}
|
||||
@ -2778,7 +2777,7 @@ e_purchase_result npc_buylist(struct map_session_data* sd, uint16 n, struct s_np
|
||||
}
|
||||
|
||||
if (nd->master_nd){ //Script-based shops.
|
||||
npc_buylist_sub(sd,n,item_list,nd->master_nd);
|
||||
npc_buylist_sub(sd,item_list,nd->master_nd);
|
||||
return e_purchase_result::PURCHASE_SUCCEED;
|
||||
}
|
||||
|
||||
@ -2792,18 +2791,21 @@ e_purchase_result npc_buylist(struct map_session_data* sd, uint16 n, struct s_np
|
||||
|
||||
pc_payzeny(sd, (int)z, LOG_TYPE_NPC, NULL);
|
||||
|
||||
for( i = 0; i < n; ++i ) {
|
||||
for( int i = 0; i < item_list.size(); ++i ) {
|
||||
t_itemid nameid = item_list[i].nameid;
|
||||
unsigned short amount = item_list[i].qty;
|
||||
|
||||
#if PACKETVER >= 20131223
|
||||
if (nd->subtype == NPCTYPE_MARKETSHOP) {
|
||||
j = market_index[i];
|
||||
|
||||
if( shop[j].qty >= 0 ){
|
||||
if (amount > shop[j].qty)
|
||||
return e_purchase_result::PURCHASE_FAIL_MONEY;
|
||||
return e_purchase_result::PURCHASE_FAIL_COUNT;
|
||||
shop[j].qty -= amount;
|
||||
npc_market_tosql(nd->exname, &shop[j]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (itemdb_type(nameid) == IT_PETEGG)
|
||||
@ -3979,7 +3981,7 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
|
||||
nd->u.shop.count = 0;
|
||||
while ( p ) {
|
||||
t_itemid nameid2;
|
||||
unsigned short qty = 0;
|
||||
int32 qty = -1;
|
||||
int value;
|
||||
struct item_data* id;
|
||||
bool skip = false;
|
||||
@ -3989,7 +3991,7 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
|
||||
switch(type) {
|
||||
case NPCTYPE_MARKETSHOP:
|
||||
#if PACKETVER >= 20131223
|
||||
if (sscanf(p, ",%u:%11d:%6hu", &nameid2, &value, &qty) != 3) {
|
||||
if (sscanf(p, ",%u:%11d:%11d", &nameid2, &value, &qty) != 3) {
|
||||
ShowError("npc_parse_shop: (MARKETSHOP) Invalid item definition in file '%s', line '%d'. Ignoring the rest of the line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer, start - buffer), w1, w2, w3, w4);
|
||||
skip = true;
|
||||
}
|
||||
@ -4023,10 +4025,10 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
|
||||
ShowWarning("npc_parse_shop: Item %s [%u] discounted buying price (%d->%d) is less than overcharged selling price (%d->%d) at file '%s', line '%d'.\n",
|
||||
id->name.c_str(), nameid2, value, (int)(value*0.75), id->value_sell, (int)(id->value_sell*1.24), filepath, strline(buffer,start-buffer));
|
||||
}
|
||||
if (type == NPCTYPE_MARKETSHOP && (!qty || qty > UINT16_MAX)) {
|
||||
ShowWarning("npc_parse_shop: Item %s [%u] is stocked with invalid value %d, changed to 1. File '%s', line '%d'.\n",
|
||||
if (type == NPCTYPE_MARKETSHOP && qty < -1) {
|
||||
ShowWarning("npc_parse_shop: Item %s [%u] is stocked with invalid value %hd, changed to unlimited (-1). File '%s', line '%d'.\n",
|
||||
id->name.c_str(), nameid2, qty, filepath, strline(buffer,start-buffer));
|
||||
qty = 1;
|
||||
qty = -1;
|
||||
}
|
||||
//for logs filters, atcommands and iteminfo script command
|
||||
if( id->maxchance == 0 )
|
||||
@ -4626,7 +4628,7 @@ int npc_instancedestroy(struct npc_data* nd)
|
||||
**/
|
||||
void npc_market_tosql(const char *exname, struct npc_item_list *list) {
|
||||
SqlStmt* stmt = SqlStmt_Malloc(mmysql_handle);
|
||||
if (SQL_ERROR == SqlStmt_Prepare(stmt, "REPLACE INTO `%s` (`name`,`nameid`,`price`,`amount`,`flag`) VALUES ('%s','%u','%d','%hu','%" PRIu8 "')",
|
||||
if (SQL_ERROR == SqlStmt_Prepare(stmt, "REPLACE INTO `%s` (`name`,`nameid`,`price`,`amount`,`flag`) VALUES ('%s','%u','%d','%d','%" PRIu8 "')",
|
||||
market_table, exname, list->nameid, list->value, list->qty, list->flag) ||
|
||||
SQL_ERROR == SqlStmt_Execute(stmt))
|
||||
SqlStmt_ShowDebug(stmt);
|
||||
@ -4709,7 +4711,7 @@ static int npc_market_checkall_sub(DBKey key, DBData *data, va_list ap) {
|
||||
npc_market_tosql(nd->exname, &nd->u.shop.shop_item[j]);
|
||||
}
|
||||
else { // Removing "out-of-date" entry
|
||||
ShowError("npc_market_checkall_sub: NPC '%s' does not sell item %u (qty %hu), deleting...\n", nd->exname, list->nameid, list->qty);
|
||||
ShowError("npc_market_checkall_sub: NPC '%s' does not sell item %u (qty %d), deleting...\n", nd->exname, list->nameid, list->qty);
|
||||
npc_market_delfromsql(nd->exname, list->nameid);
|
||||
}
|
||||
}
|
||||
|
@ -33,28 +33,16 @@ struct npc_item_list {
|
||||
t_itemid nameid;
|
||||
unsigned int value;
|
||||
#if PACKETVER >= 20131223
|
||||
unsigned short qty; ///< Stock counter (Market shop)
|
||||
int32 qty; ///< Stock counter (Market shop)
|
||||
uint8 flag; ///< 1: Item added by npcshopitem/npcshopadditem, force load! (Market shop)
|
||||
#endif
|
||||
};
|
||||
|
||||
#if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
|
||||
#pragma pack(push, 1)
|
||||
#endif // not NetBSD < 6 / Solaris
|
||||
|
||||
/// List of bought/sold item for NPC shops
|
||||
struct s_npc_buy_list {
|
||||
unsigned short qty; ///< Amount of item will be bought
|
||||
#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
|
||||
int32 qty; ///< Amount of item will be bought
|
||||
uint32 nameid; ///< ID of item will be bought
|
||||
#else
|
||||
uint16 nameid; ///< ID of item will be bought
|
||||
#endif
|
||||
} __attribute__((packed));
|
||||
|
||||
#if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
|
||||
#pragma pack(pop)
|
||||
#endif // not NetBSD < 6 / Solaris
|
||||
};
|
||||
|
||||
struct s_stylist_costs{
|
||||
uint32 price;
|
||||
@ -1491,8 +1479,8 @@ int npc_click(struct map_session_data* sd, struct npc_data* nd);
|
||||
bool npc_scriptcont(struct map_session_data* sd, int id, bool closing);
|
||||
struct npc_data* npc_checknear(struct map_session_data* sd, struct block_list* bl);
|
||||
int npc_buysellsel(struct map_session_data* sd, int id, int type);
|
||||
e_purchase_result npc_buylist(struct map_session_data* sd, uint16 n, struct s_npc_buy_list *item_list);
|
||||
static int npc_buylist_sub(struct map_session_data* sd, uint16 n, struct s_npc_buy_list *item_list, struct npc_data* nd);
|
||||
e_purchase_result npc_buylist(struct map_session_data* sd, std::vector<s_npc_buy_list>& item_list);
|
||||
static int npc_buylist_sub(struct map_session_data* sd, std::vector<s_npc_buy_list>& item_list, struct npc_data* nd);
|
||||
uint8 npc_selllist(struct map_session_data* sd, int n, unsigned short *item_list);
|
||||
e_purchase_result npc_barter_purchase( struct map_session_data& sd, std::shared_ptr<s_npc_barter> barter, std::vector<s_barter_purchase>& purchases );
|
||||
void npc_parse_mob2(struct spawn_data* mob);
|
||||
@ -1550,7 +1538,7 @@ void npc_shop_currency_type(struct map_session_data *sd, struct npc_data *nd, in
|
||||
|
||||
extern struct npc_data* fake_nd;
|
||||
|
||||
int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, struct PACKET_CZ_PC_BUY_CASH_POINT_ITEM_sub* item_list);
|
||||
int npc_cashshop_buylist( struct map_session_data *sd, int points, std::vector<s_npc_buy_list>& item_list );
|
||||
bool npc_shop_discount(struct npc_data* nd);
|
||||
|
||||
#if PACKETVER >= 20131223
|
||||
|
@ -17653,9 +17653,17 @@ BUILDIN_FUNC(npcshopadditem)
|
||||
nd->u.shop.count++;
|
||||
}
|
||||
|
||||
int32 stock = script_getnum( st, i + 2 );
|
||||
|
||||
if( stock < -1 ){
|
||||
ShowError( "builtin_npcshopadditem: Invalid stock amount in marketshop '%s'.\n", nd->exname );
|
||||
script_pushint( st, 0 );
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
nd->u.shop.shop_item[j].nameid = nameid;
|
||||
nd->u.shop.shop_item[j].value = script_getnum(st,i+1);
|
||||
nd->u.shop.shop_item[j].qty = script_getnum(st,i+2);
|
||||
nd->u.shop.shop_item[j].qty = stock;
|
||||
|
||||
npc_market_tosql(nd->exname, &nd->u.shop.shop_item[j]);
|
||||
}
|
||||
@ -23299,7 +23307,13 @@ BUILDIN_FUNC(npcshopupdate) {
|
||||
t_itemid nameid = script_getnum(st, 3);
|
||||
int price = script_getnum(st, 4);
|
||||
#if PACKETVER >= 20131223
|
||||
uint16 stock = script_hasdata(st,5) ? script_getnum(st,5) : 0;
|
||||
int32 stock = script_hasdata(st,5) ? script_getnum(st,5) : -1;
|
||||
|
||||
if( stock < -1 ){
|
||||
ShowError( "buildin_npcshopupdate: Invalid stock amount in marketshop '%s'.\n", nd->exname );
|
||||
script_pushint( st, 0 );
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
#endif
|
||||
int i;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user