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:
@@ -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,17 +2791,20 @@ 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 (amount > shop[j].qty)
|
||||
return e_purchase_result::PURCHASE_FAIL_MONEY;
|
||||
shop[j].qty -= amount;
|
||||
npc_market_tosql(nd->exname, &shop[j]);
|
||||
|
||||
if( shop[j].qty >= 0 ){
|
||||
if (amount > shop[j].qty)
|
||||
return e_purchase_result::PURCHASE_FAIL_COUNT;
|
||||
shop[j].qty -= amount;
|
||||
npc_market_tosql(nd->exname, &shop[j]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user