/*========================================== * Check here if we can add items in inventories (against full inventory) *------------------------------------------ */ static int trade_check(struct map_session_data *sd, struct map_session_data *target_sd) { struct item inventory[MAX_INVENTORY]; struct item inventory2[MAX_INVENTORY]; struct item_data *data; int trade_i, i, amount, idx; nullpo_retr(0, sd); nullpo_retr(0, target_sd); // get inventory of players memcpy(&inventory, &sd->status.inventory, sizeof(struct item) * MAX_INVENTORY); memcpy(&inventory2, &target_sd->status.inventory, sizeof(struct item) * MAX_INVENTORY); // check free slots in both inventories for(trade_i = 0; trade_i < MAX_DEAL_ITEMS; trade_i++) { amount = sd->trade.item_amount[trade_i]; if (amount > 0) { idx = sd->trade.item_index[trade_i] - 2; if (itemdb_isdropable(inventory[idx].nameid)) { // check quantity if (amount > inventory[idx].amount) // player changes its inventory before to commit return 0; if (amount > 0) { // search if it's possible to add item (for full inventory) data = itemdb_search(inventory[idx].nameid); i = MAX_INVENTORY; // check for non-equipement items if (!itemdb_isequip2(data)) { for(i = 0; i < MAX_INVENTORY; i++) if (inventory2[i].nameid == inventory[idx].nameid && inventory2[i].card[0] == inventory[idx].card[0] && inventory2[i].card[1] == inventory[idx].card[1] && inventory2[i].card[2] == inventory[idx].card[2] && inventory2[i].card[3] == inventory[idx].card[3]) { if (inventory2[i].amount + amount > MAX_AMOUNT) return 0; inventory2[i].amount += amount; inventory[idx].amount -= amount; if (inventory[idx].amount <= 0) memset(&inventory[idx], 0, sizeof(struct item)); break; } } // check for equipement if (i == MAX_INVENTORY) { for(i = 0; i < MAX_INVENTORY; i++) { if (inventory2[i].nameid == 0) { memcpy(&inventory2[i], &inventory[idx], sizeof(struct item)); inventory2[i].amount = amount; inventory[idx].amount -= amount; if (inventory[idx].amount <= 0) memset(&inventory[idx], 0, sizeof(struct item)); break; } } if (i == MAX_INVENTORY) return 0; } } } } amount = target_sd->trade.item_amount[trade_i]; if (amount > 0) { idx = target_sd->trade.item_index[trade_i] - 2; if (itemdb_isdropable(inventory2[idx].nameid)) { // check quantity if (amount > inventory2[idx].amount) // player changes its inventory before to commit return 0; if (amount > 0) { // search if it's possible to add item (for full inventory) data = itemdb_search(inventory2[idx].nameid); i = MAX_INVENTORY; // check for non-equipement items if (!itemdb_isequip2(data)) { for(i = 0; i < MAX_INVENTORY; i++) if (inventory[i].nameid == inventory2[idx].nameid && inventory[i].card[0] == inventory2[idx].card[0] && inventory[i].card[1] == inventory2[idx].card[1] && inventory[i].card[2] == inventory2[idx].card[2] && inventory[i].card[3] == inventory2[idx].card[3]) { if (inventory[i].amount + amount > MAX_AMOUNT) return 0; inventory[i].amount += amount; inventory2[idx].amount -= amount; if (inventory2[idx].amount <= 0) memset(&inventory2[idx], 0, sizeof(struct item)); break; } } // check for equipement if (i == MAX_INVENTORY) { for(i = 0; i < MAX_INVENTORY; i++) { if (inventory[i].nameid == 0) { memcpy(&inventory[i], &inventory2[idx], sizeof(struct item)); inventory[i].amount = amount; inventory2[idx].amount -= amount; if (inventory2[idx].amount <= 0) memset(&inventory2[idx], 0, sizeof(struct item)); break; } } if (i == MAX_INVENTORY) return 0; } } } } } return 1; }
/*========================================== * processes one itemdb entry *------------------------------------------*/ static bool itemdb_parse_dbrow(char** str, const char* source, int line, int scriptopt) { /* +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+ | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+ | id | name_english | name_japanese | type | price_buy | price_sell | weight | attack | defence | range | slots | equip_jobs | equip_upper | equip_genders | equip_locations | weapon_level | equip_level | refineable | view | script | equip_script | unequip_script | +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+ */ int nameid; struct item_data* id; nameid = atoi(str[0]); if( nameid <= 0 ) { ShowWarning("itemdb_parse_dbrow: Invalid id %d in line %d of \"%s\", skipping.\n", nameid, line, source); return false; } //ID,Name,Jname,Type,Price,Sell,Weight,ATK,DEF,Range,Slot,Job,Job Upper,Gender,Loc,wLV,eLV,refineable,View id = itemdb_load(nameid); safestrncpy(id->name, str[1], sizeof(id->name)); safestrncpy(id->jname, str[2], sizeof(id->jname)); id->type = atoi(str[3]); if( id->type < 0 || id->type == IT_UNKNOWN || id->type == IT_UNKNOWN2 || ( id->type > IT_DELAYCONSUME && id->type < IT_THROWWEAPON ) || id->type >= IT_MAX ) {// catch invalid item types ShowWarning("itemdb_parse_dbrow: Invalid item type %d for item %d. IT_ETC will be used.\n", id->type, nameid); id->type = IT_ETC; } if (id->type == IT_DELAYCONSUME) { //Items that are consumed only after target confirmation id->type = IT_USABLE; id->flag.delay_consume = 1; } else //In case of an itemdb reload and the item type changed. id->flag.delay_consume = 0; //When a particular price is not given, we should base it off the other one //(it is important to make a distinction between 'no price' and 0z) if ( str[4][0] ) id->value_buy = atoi(str[4]); else id->value_buy = atoi(str[5]) * 2; if ( str[5][0] ) id->value_sell = atoi(str[5]); else id->value_sell = id->value_buy / 2; /* if ( !str[4][0] && !str[5][0]) { ShowWarning("itemdb_parse_dbrow: No buying/selling price defined for item %d (%s), using 20/10z\n", nameid, id->jname); id->value_buy = 20; id->value_sell = 10; } else */ if (id->value_buy/124. < id->value_sell/75.) ShowWarning("itemdb_parse_dbrow: Buying/Selling [%d/%d] price of item %d (%s) allows Zeny making exploit through buying/selling at discounted/overcharged prices!\n", id->value_buy, id->value_sell, nameid, id->jname); id->weight = atoi(str[6]); id->atk = atoi(str[7]); id->matk = 0; id->def = atoi(str[8]); id->range = atoi(str[9]); id->slot = atoi(str[10]); if (id->slot > MAX_SLOTS) { ShowWarning("itemdb_parse_dbrow: Item %d (%s) specifies %d slots, but the server only supports up to %d. Using %d slots.\n", nameid, id->jname, id->slot, MAX_SLOTS, MAX_SLOTS); id->slot = MAX_SLOTS; } itemdb_jobid2mapid(id->class_base, (unsigned int)strtoul(str[11],NULL,0)); id->class_upper = atoi(str[12]); id->sex = atoi(str[13]); id->equip = atoi(str[14]); if (!id->equip && itemdb_isequip2(id)) { ShowWarning("Item %d (%s) is an equipment with no equip-field! Making it an etc item.\n", nameid, id->jname); id->type = IT_ETC; } id->wlv = atoi(str[15]); id->elv = atoi(str[16]); id->flag.no_refine = atoi(str[17]) ? 0 : 1; //FIXME: verify this id->look = atoi(str[18]); id->dropRate = 0; id->ancient = false; id->add_dropRate = 0; id->flag.available = 1; id->view_id = 0; id->sex = itemdb_gendercheck(id); //Apply gender filtering. if (id->script) { script_free_code(id->script); id->script = NULL; } if (id->equip_script) { script_free_code(id->equip_script); id->equip_script = NULL; } if (id->unequip_script) { script_free_code(id->unequip_script); id->unequip_script = NULL; } if (*str[19]) id->script = parse_script(str[19], source, line, scriptopt); if (*str[20]) id->equip_script = parse_script(str[20], source, line, scriptopt); if (*str[21]) id->unequip_script = parse_script(str[21], source, line, scriptopt); return true; }
/*========================================== * Check here if we can add item in inventory (against full inventory) *------------------------------------------ */ int trade_check(struct map_session_data *sd) { struct item inventory[MAX_INVENTORY]; struct item inventory2[MAX_INVENTORY]; struct item_data *data; struct map_session_data *target_sd; int trade_i, i, amount; target_sd = map_id2sd(sd->trade_partner); // get inventory of player memcpy(&inventory, &sd->status.inventory, sizeof(struct item) * MAX_INVENTORY); memcpy(&inventory2, &target_sd->status.inventory, sizeof(struct item) * MAX_INVENTORY); // check free slot in both inventory for(trade_i = 0; trade_i < 10; trade_i++) { amount = sd->deal.item[trade_i].amount; if (amount > 0) { int n = sd->deal.item[trade_i].index; // check quantity if (amount > inventory[n].amount) amount = inventory[n].amount; if (amount > 0) { data = itemdb_search(inventory[n].nameid); i = MAX_INVENTORY; // check for non-equipement item if (!itemdb_isequip2(data)) { for(i = 0; i < MAX_INVENTORY; i++) if (inventory2[i].nameid == inventory[n].nameid && inventory2[i].card[0] == inventory[n].card[0] && inventory2[i].card[1] == inventory[n].card[1] && inventory2[i].card[2] == inventory[n].card[2] && inventory2[i].card[3] == inventory[n].card[3]) { if (inventory2[i].amount + amount > MAX_AMOUNT) return 0; inventory2[i].amount += amount; inventory[n].amount -= amount; if (inventory[n].amount <= 0) memset(&inventory[n], 0, sizeof(struct item)); break; } } // check for equipement if (i == MAX_INVENTORY) { for(i = 0; i < MAX_INVENTORY; i++) { if (inventory2[i].nameid == 0) { memcpy(&inventory2[i], &inventory[n], sizeof(struct item)); inventory2[i].amount = amount; inventory[n].amount -= amount; if (inventory[n].amount <= 0) memset(&inventory[n], 0, sizeof(struct item)); break; } } if (i == MAX_INVENTORY) return 0; } } } amount = target_sd->deal.item[trade_i].amount; if (amount > 0) { int n = target_sd->deal.item[trade_i].index; // check quantity if (amount > inventory2[n].amount) amount = inventory2[n].amount; if (amount > 0) { // search if it's possible to add item (for full inventory) data = itemdb_search(inventory2[n].nameid); i = MAX_INVENTORY; if (!itemdb_isequip2(data)) { for(i = 0; i < MAX_INVENTORY; i++) if (inventory[i].nameid == inventory2[n].nameid && inventory[i].card[0] == inventory2[n].card[0] && inventory[i].card[1] == inventory2[n].card[1] && inventory[i].card[2] == inventory2[n].card[2] && inventory[i].card[3] == inventory2[n].card[3]) { if (inventory[i].amount + amount > MAX_AMOUNT) return 0; inventory[i].amount += amount; inventory2[n].amount -= amount; if (inventory2[n].amount <= 0) memset(&inventory2[n], 0, sizeof(struct item)); break; } } if (i == MAX_INVENTORY) { for(i = 0; i < MAX_INVENTORY; i++) { if (inventory[i].nameid == 0) { memcpy(&inventory[i], &inventory2[n], sizeof(struct item)); inventory[i].amount = amount; inventory2[n].amount -= amount; if (inventory2[n].amount <= 0) memset(&inventory2[n], 0, sizeof(struct item)); break; } } if (i == MAX_INVENTORY) return 0; } } } } return 1; }