diff options
Diffstat (limited to 'src/map/npc.c')
-rw-r--r-- | src/map/npc.c | 153 |
1 files changed, 78 insertions, 75 deletions
diff --git a/src/map/npc.c b/src/map/npc.c index 6ba088a80..7a3fa9c3f 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -2715,43 +2715,47 @@ static int npc_selllist_sub(struct map_session_data *sd, struct itemlist *item_l char card_slot[NAME_LENGTH]; char opt_index_str[NAME_LENGTH]; char opt_value_str[NAME_LENGTH]; - int i, j; + char opt_param_str[NAME_LENGTH]; + int i = 0; + int j = 0; int key_nameid = 0; int key_amount = 0; int key_refine = 0; - int key_attribute = 0; + int key_attribute = ATTR_NONE; int key_identify = 0; int key_card[MAX_SLOTS]; int key_opt_idx[MAX_ITEM_OPTIONS]; int key_opt_value[MAX_ITEM_OPTIONS]; + int key_opt_param[MAX_ITEM_OPTIONS]; nullpo_ret(sd); nullpo_ret(item_list); nullpo_ret(nd); // discard old contents - script->cleararray_pc(sd, "@sold_nameid", (void*)0); - script->cleararray_pc(sd, "@sold_quantity", (void*)0); - script->cleararray_pc(sd, "@sold_refine", (void*)0); - script->cleararray_pc(sd, "@sold_attribute", (void*)0); - script->cleararray_pc(sd, "@sold_identify", (void*)0); - - for( j = 0; j < MAX_SLOTS; j++ ) - {// clear each of the card slot entries + script->cleararray_pc(sd, "@sold_nameid", (void *)0); + script->cleararray_pc(sd, "@sold_quantity", (void *)0); + script->cleararray_pc(sd, "@sold_refine", (void *)0); + script->cleararray_pc(sd, "@sold_attribute", (void *)0); + script->cleararray_pc(sd, "@sold_identify", (void *)0); + + for (j = 0; j < MAX_SLOTS; j++) { // clear each of the card slot entries key_card[j] = 0; snprintf(card_slot, sizeof(card_slot), "@sold_card%d", j + 1); - script->cleararray_pc(sd, card_slot, (void*)0); + script->cleararray_pc(sd, card_slot, (void *)0); } for (j = 0; j < MAX_ITEM_OPTIONS; j++) { // Clear Each item option entry key_opt_idx[j] = 0; key_opt_value[j] = 0; + key_opt_param[j] = 0; - snprintf(opt_index_str, sizeof(opt_index_str), "@slot_opt_idx%d", j + 1); - script->cleararray_pc(sd, opt_index_str, (void*)0); - - snprintf(opt_value_str, sizeof(opt_value_str), "@slot_opt_val%d", j + 1); - script->cleararray_pc(sd, opt_value_str, (void*)0); + snprintf(opt_index_str, sizeof(opt_index_str), "@sold_opt_idx%d", j + 1); + script->cleararray_pc(sd, opt_index_str, (void *)0); + snprintf(opt_value_str, sizeof(opt_value_str), "@sold_opt_val%d", j + 1); + script->cleararray_pc(sd, opt_value_str, (void *)0); + snprintf(opt_param_str, sizeof(opt_param_str), "@sold_opt_param%d", j + 1); + script->cleararray_pc(sd, opt_param_str, (void *)0); } // save list of to be sold items @@ -2764,32 +2768,31 @@ static int npc_selllist_sub(struct map_session_data *sd, struct itemlist *item_l intptr_t attribute = item->attribute; intptr_t identify = item->identify; - script->setarray_pc(sd, "@sold_nameid", i, (void*)nameid, &key_nameid); - script->setarray_pc(sd, "@sold_quantity", i, (void*)amount, &key_amount); - // process item based information into the arrays - script->setarray_pc(sd, "@sold_refine", i, (void*)refine, &key_refine); - script->setarray_pc(sd, "@sold_attribute", i, (void*)attribute, &key_attribute); - script->setarray_pc(sd, "@sold_identify", i, (void*)identify, &key_identify); + script->setarray_pc(sd, "@sold_nameid", i, (void *)nameid, &key_nameid); + script->setarray_pc(sd, "@sold_quantity", i, (void *)amount, &key_amount); + script->setarray_pc(sd, "@sold_refine", i, (void *)refine, &key_refine); + script->setarray_pc(sd, "@sold_attribute", i, (void *)attribute, &key_attribute); + script->setarray_pc(sd, "@sold_identify", i, (void *)identify, &key_identify); for (j = 0; j < MAX_SLOTS; j++) { intptr_t card = item->card[j]; - // store each of the cards/special info from the item in the array snprintf(card_slot, sizeof(card_slot), "@sold_card%d", j + 1); - script->setarray_pc(sd, card_slot, i, (void*)card, &key_card[j]); + script->setarray_pc(sd, card_slot, i, (void *)card, &key_card[j]); } for (j = 0; j < MAX_ITEM_OPTIONS; j++) { intptr_t opt_idx = item->option[j].index; intptr_t opt_value = item->option[j].value; + intptr_t opt_param = item->option[j].param; - snprintf(opt_index_str, sizeof(opt_index_str), "@slot_opt_idx%d", j + 1); - script->setarray_pc(sd, opt_index_str, i, (void*)opt_idx, &key_opt_idx[j]); - - snprintf(opt_value_str, sizeof(opt_value_str), "@slot_opt_val%d", j + 1); - script->setarray_pc(sd, opt_value_str, i, (void*)opt_value, &key_opt_value[j]); + snprintf(opt_index_str, sizeof(opt_index_str), "@sold_opt_idx%d", j + 1); + script->setarray_pc(sd, opt_index_str, i, (void *)opt_idx, &key_opt_idx[j]); + snprintf(opt_value_str, sizeof(opt_value_str), "@sold_opt_val%d", j + 1); + script->setarray_pc(sd, opt_value_str, i, (void *)opt_value, &key_opt_value[j]); + snprintf(opt_param_str, sizeof(opt_param_str), "@sold_opt_param%d", j + 1); + script->setarray_pc(sd, opt_param_str, i, (void *)opt_param, &key_opt_param[j]); } - } // invoke event @@ -2798,104 +2801,102 @@ static int npc_selllist_sub(struct map_session_data *sd, struct itemlist *item_l return 0; } -/// Player item selling to npc shop. -/// -/// @param item_list 'n' pairs <index,amount> -/// @return result code for clif->parse_NpcSellListSend +/** + * Processes a character's request to sell items to a NPC shop. + * + * @param sd The character who wants to sell the items. + * @param item_list The list of items and respective amounts which should be sold. + * @return 1 on failure, 0 on success. + * + **/ static int npc_selllist(struct map_session_data *sd, struct itemlist *item_list) { - int64 z; - int i,skill_t, skill_idx = skill->get_index(MC_OVERCHARGE); - struct npc_data *nd; - bool duplicates[MAX_INVENTORY] = { 0 }; - nullpo_retr(1, sd); nullpo_retr(1, item_list); - if( ( nd = npc->checknear(sd, map->id2bl(sd->npc_shopid)) ) == NULL ) { + struct npc_data *nd = npc->checknear(sd, map->id2bl(sd->npc_shopid)); + + if (nd == NULL) return 1; - } - if( nd->subtype != SHOP ) { - if (!(nd->subtype == SCRIPT && nd->u.scr.shop && (nd->u.scr.shop->type == NST_ZENY || nd->u.scr.shop->type == NST_MARKET))) + if (nd->subtype != SHOP) { + if (nd->subtype != SCRIPT || nd->u.scr.shop == NULL || (nd->u.scr.shop->type != NST_ZENY && nd->u.scr.shop->type != NST_MARKET)) return 1; } - z = 0; - if (sd->status.zeny >= MAX_ZENY && nd->master_nd == NULL) return 1; - // verify the sell list - for (i = 0; i < VECTOR_LENGTH(*item_list); i++) { + bool duplicates[MAX_INVENTORY] = { false }; + int64 z = 0; + + // Verify the sell list. + for (int i = 0; i < VECTOR_LENGTH(*item_list); i++) { struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, i); - int nameid, value, idx = entry->id; + int idx = entry->id; - if (idx >= sd->status.inventorySize || idx < 0 || entry->amount < 0) { + if (idx >= sd->status.inventorySize || idx < 0 || entry->amount < 0) return 1; - } - if (duplicates[idx]) { - // Sanity check. The client sends each inventory index at most once [Haru] + if (duplicates[idx]) // Sanity check. The client sends each inventory index at most once. [Haru] return 1; - } + duplicates[idx] = true; - nameid = sd->status.inventory[idx].nameid; + int nameid = sd->status.inventory[idx].nameid; - if (!nameid || !sd->inventory_data[idx] || sd->status.inventory[idx].amount < entry->amount) { + if (nameid == 0 || sd->inventory_data[idx] == NULL || sd->status.inventory[idx].amount < entry->amount) return 1; - } - if (nd->master_nd) { - // Script-controlled shops decide by themselves, what can be sold and at what price. + if (nd->master_nd != NULL) // Script-controlled shops decide by themselves, what can be sold and at what price. continue; - } - value = pc->modifysellvalue(sd, sd->inventory_data[idx]->value_sell); + int value = pc->modifysellvalue(sd, sd->inventory_data[idx]->value_sell); z += (int64)value * entry->amount; } - if( nd->master_nd ) { // Script-controlled shops + if (nd->master_nd != NULL) // Script-controlled shops. return npc->selllist_sub(sd, item_list, nd->master_nd); - } - // delete items - for (i = 0; i < VECTOR_LENGTH(*item_list); i++) { + if (z + sd->status.zeny > MAX_ZENY) + return 1; + + // Delete items. + for (int i = 0; i < VECTOR_LENGTH(*item_list); i++) { struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, i); int idx = entry->id; if (sd->inventory_data[idx]->type == IT_PETEGG && sd->status.inventory[idx].card[0] == CARD0_PET) { - if (pet->search_petDB_index(sd->status.inventory[idx].nameid, PET_EGG) >= 0) { + if (pet->search_petDB_index(sd->status.inventory[idx].nameid, PET_EGG) >= 0) intif->delete_petdata(MakeDWord(sd->status.inventory[idx].card[1], sd->status.inventory[idx].card[2])); - } } - // Achievements [Smokexyz/Hercules] + // Achievements. [Smokexyz/Hercules] achievement->validate_item_sell(sd, sd->status.inventory[idx].nameid, entry->amount); pc->delitem(sd, idx, entry->amount, 0, DELITEM_SOLD, LOG_TYPE_NPC); - } - if (z + sd->status.zeny > MAX_ZENY && nd->master_nd == NULL) - return 1; - if (z > MAX_ZENY) z = MAX_ZENY; pc->getzeny(sd, (int)z, LOG_TYPE_NPC, NULL); - // custom merchant shop exp bonus - if( battle_config.shop_exp > 0 && z > 0 && ( skill_t = pc->checkskill2(sd,skill_idx) ) > 0) { - if( sd->status.skill[skill_idx].flag >= SKILL_FLAG_REPLACED_LV_0 ) + int skill_t; + int skill_idx = skill->get_index(MC_OVERCHARGE); + + // Custom merchant shop exp bonus. + if (battle_config.shop_exp > 0 && z > 0 && (skill_t = pc->checkskill2(sd, skill_idx)) > 0) { + if (sd->status.skill[skill_idx].flag >= SKILL_FLAG_REPLACED_LV_0) skill_t = sd->status.skill[skill_idx].flag - SKILL_FLAG_REPLACED_LV_0; - if( skill_t > 0 ) { + if (skill_t > 0) { z = apply_percentrate64(z, skill_t * battle_config.shop_exp, 10000); + if (z < 1) z = 1; + pc->gainexp(sd, NULL, 0, (int)z, false); } } @@ -5241,6 +5242,8 @@ static const char *npc_parse_mapflag(const char *w1, const char *w2, const char map->list[m].flag.nostorage = (state) ? cap_value(atoi(w4), 1, 3) : 0; } else if (!strcmpi(w3, "nogstorage")) { map->list[m].flag.nogstorage = (state) ? cap_value(atoi(w4), 1, 3) : 0; + } else if (strcmpi(w3, "nopet") == 0) { + map->list[m].flag.nopet = (state != 0) ? 1 : 0; } else { npc->parse_unknown_mapflag(mapname, w3, w4, start, buffer, filepath, retval); } |