// Extended Vending System static bool itemdb_read_vending(char* fields[], int columns, int current) { struct item_data* id; int nameid; nameid = atoi(fields[0]); if( ( id = itemdb_exists(nameid) ) == NULL ) { ShowWarning("itemdb_read_vending: Invalid item id %d.\n", nameid); return false; } if( !itemdb_isstackable2(id) ) { ShowWarning("itemdb_read_vending: Cannot use a non stackable item. ID %d.\n", nameid); return false; } if( id->weight > 0 ) { ShowWarning("itemdb_read_vending: Coins only can have 0 weight. Cannot use ID %d.\n", nameid); return false; } coins_db[current] = nameid; return true; }
void itemdb_save_serials(void) { struct item_data *id; StringBuf buf; int count = 0, i; StringBuf_Init(&buf); StringBuf_Printf(&buf, "REPLACE INTO `item_serials` (`nameid`, `serial`) VALUES "); for( i = 0; i < ARRAYLENGTH(itemdb_array); i++ ) { id = itemdb_array[i]; if( id == NULL || itemdb_isstackable2(id) || id->last_serial == 0 || !id->changed ) continue; if( count ) StringBuf_AppendStr(&buf, ","); StringBuf_Printf(&buf, "('%d','%u')", id->nameid, id->last_serial); id->changed = false; count++; } if( count && SQL_ERROR == Sql_QueryStr(mmysql_handle, StringBuf_Value(&buf)) ) Sql_ShowDebug(mmysql_handle); StringBuf_Destroy(&buf); return; }
/** * Attempt to add an item in guild storage, then refresh it * @param sd : player attempting to open the guild_storage * @param stor : guild_storage * @param item_data : item to add * @param amount : number of item to add * @return 0 : success, 1 : fail */ char guild_storage_additem(struct map_session_data* sd, struct guild_storage* stor, struct item* item_data, int amount) { struct item_data *data; int i; nullpo_retr(1, sd); nullpo_retr(1, stor); nullpo_retr(1, item_data); if(item_data->nameid == 0 || amount <= 0) return 1; data = itemdb_search(item_data->nameid); if( data->stack.guildstorage && amount > data->stack.amount ) {// item stack limitation return 1; } if( !itemdb_canguildstore(item_data, pc_get_group_level(sd)) || item_data->expire_time ) { //Check if item is storable. [Skotlex] clif_displaymessage (sd->fd, msg_txt(sd,264)); return 1; } if( (item_data->bound == BOUND_ACCOUNT || item_data->bound > BOUND_GUILD) && !pc_can_give_bounded_items(sd) ) { clif_displaymessage(sd->fd, msg_txt(sd,294)); return 1; } if(itemdb_isstackable2(data)){ //Stackable for(i=0;i<MAX_GUILD_STORAGE;i++){ if(compare_item(&stor->items[i], item_data)) { if( amount > MAX_AMOUNT - stor->items[i].amount || ( data->stack.guildstorage && amount > data->stack.amount - stor->items[i].amount ) ) return 1; stor->items[i].amount+=amount; clif_storageitemadded(sd,&stor->items[i],i,amount); stor->dirty = 1; return 0; } } } //Add item for(i=0;i<MAX_GUILD_STORAGE && stor->items[i].nameid;i++); if(i>=MAX_GUILD_STORAGE) return 1; memcpy(&stor->items[i],item_data,sizeof(stor->items[0])); stor->items[i].amount=amount; stor->storage_amount++; clif_storageitemadded(sd,&stor->items[i],i,amount); clif_updatestorageamount(sd, stor->storage_amount, MAX_GUILD_STORAGE); stor->dirty = 1; return 0; }
/** * Make a player add an item to his storage * @param sd : player * @param item_data : item to add * @param amount : quantity of items * @return 0:success, 1:failed */ static int storage_additem(struct map_session_data* sd, struct item* item_data, int amount) { struct storage_data* stor = &sd->status.storage; struct item_data *data; int i; if( item_data->nameid == 0 || amount <= 0 ) return 1; data = itemdb_search(item_data->nameid); if( data->stack.storage && amount > data->stack.amount ) {// item stack limitation return 1; } if( !itemdb_canstore(item_data, pc_get_group_level(sd)) ) { //Check if item is storable. [Skotlex] clif_displaymessage (sd->fd, msg_txt(sd,264)); return 1; } if( (item_data->bound > BOUND_ACCOUNT) && !pc_can_give_bounded_items(sd) ) { clif_displaymessage(sd->fd, msg_txt(sd,294)); return 1; } if( itemdb_isstackable2(data) ) {//Stackable for( i = 0; i < sd->storage_size; i++ ) { if( compare_item(&stor->items[i], item_data) ) {// existing items found, stack them if( amount > MAX_AMOUNT - stor->items[i].amount || ( data->stack.storage && amount > data->stack.amount - stor->items[i].amount ) ) return 1; stor->items[i].amount += amount; clif_storageitemadded(sd,&stor->items[i],i,amount); return 0; } } } // find free slot ARR_FIND( 0, sd->storage_size, i, stor->items[i].nameid == 0 ); if( i >= sd->storage_size ) return 1; // add item to slot memcpy(&stor->items[i],item_data,sizeof(stor->items[0])); stor->storage_amount++; stor->items[i].amount = amount; clif_storageitemadded(sd,&stor->items[i],i,amount); clif_updatestorageamount(sd, stor->storage_amount, sd->storage_size); return 0; }
int guild_storage_additem(struct map_session_data* sd, struct guild_storage* stor, struct item* item_data, int amount) { struct item_data *data; int i; nullpo_retr(1, sd); nullpo_retr(1, stor); nullpo_retr(1, item_data); if(item_data->nameid <= 0 || amount <= 0) return 1; data = itemdb_search(item_data->nameid); if( !itemdb_canguildstore(item_data, pc_isGM(sd)) || item_data->expire_time || item_data->bound ) { //Check if item is storable. [Skotlex] clif_displaymessage (sd->fd, msg_txt(264)); return 1; } if( sd->state.secure_items ) { clif_displaymessage(sd->fd, "You can't store items on Guild Storage. Blocked with @security"); return 1; } if(itemdb_isstackable2(data)){ //Stackable for(i=0;i<MAX_GUILD_STORAGE;i++){ if(compare_item(&stor->items[i], item_data)) { if(stor->items[i].amount+amount > MAX_AMOUNT) return 1; stor->items[i].amount+=amount; clif_storageitemadded(sd,&stor->items[i],i,amount); stor->dirty = 1; if(log_config.enable_logs&0x1000) log_pick_pc(sd, "G", item_data->nameid, -amount, item_data, 0); return 0; } } } //Add item for(i=0;i<MAX_GUILD_STORAGE && stor->items[i].nameid;i++); if(i>=MAX_GUILD_STORAGE) return 1; memcpy(&stor->items[i],item_data,sizeof(stor->items[0])); stor->items[i].amount=amount; stor->storage_amount++; clif_storageitemadded(sd,&stor->items[i],i,amount); clif_updateguildstorageamount(sd,stor->storage_amount); stor->dirty = 1; if(log_config.enable_logs&0x1000) log_pick_pc(sd, "G", item_data->nameid, -amount, item_data, item_data->serial ); return 0; }
/*========================================== * Internal add-item function. *------------------------------------------*/ static int storage_additem(struct map_session_data* sd, struct item* item_data, int amount, int flag) { struct storage_data* stor = &sd->status.storage; struct item_data *data; int i; if( item_data->nameid <= 0 || amount <= 0 ) return 1; data = itemdb_search(item_data->nameid); if( !itemdb_canstore(item_data, pc_isGM(sd)) ) { //Check if item is storable. [Skotlex] clif_displaymessage (sd->fd, msg_txt(264)); return 1; } if( itemdb_isstackable2(data) ) {//Stackable for( i = 0; i < MAX_STORAGE; i++ ) { if( compare_item(&stor->items[i], item_data) ) {// existing items found, stack them if( amount > MAX_AMOUNT - stor->items[i].amount ) return 1; stor->items[i].amount += amount; if( flag ) clif_storageitemadded(sd,&stor->items[i],i,amount); if(log_config.enable_logs&0x800) log_pick_pc(sd, "R", item_data->nameid, -amount, item_data, 0); return 0; } } } // find free slot ARR_FIND( 0, MAX_STORAGE, i, stor->items[i].nameid == 0 ); if( i >= MAX_STORAGE ) return 1; // add item to slot memcpy(&stor->items[i],item_data,sizeof(stor->items[0])); stor->storage_amount++; stor->items[i].amount = amount; if( flag ) { clif_storageitemadded(sd,&stor->items[i],i,amount); clif_updatestorageamount(sd,stor->storage_amount); } if(log_config.enable_logs&0x800) log_pick_pc(sd, "R", item_data->nameid, -amount, item_data, item_data->serial ); return 0; }
/*========================================== * Internal add-item function. *------------------------------------------ */ static int storage_additem(struct map_session_data *sd,struct storage *stor,struct item *item_data,int amount) { struct item_data *data; int i; if (sd->state.finalsave) return 1; if(item_data->nameid <= 0 || amount <= 0) return 1; data = itemdb_search(item_data->nameid); if (!itemdb_canstore(item_data, pc_isGM(sd))) { //Check if item is storable. [Skotlex] clif_displaymessage (sd->fd, msg_txt(264)); return 1; } if(itemdb_isstackable2(data)){ //Stackable for(i=0;i<MAX_STORAGE;i++){ if( compare_item (&stor->storage_[i], item_data)) { if(amount > MAX_AMOUNT - stor->storage_[i].amount) return 1; stor->storage_[i].amount+=amount; clif_storageitemadded(sd,stor,i,amount); stor->dirty = 1; if(log_config.enable_logs&0x800) log_pick_pc(sd, "R", item_data->nameid, -amount, item_data); return 0; } } } //Add item for(i=0;i<MAX_STORAGE && stor->storage_[i].nameid;i++); if(i>=MAX_STORAGE) return 1; memcpy(&stor->storage_[i],item_data,sizeof(stor->storage_[0])); stor->storage_[i].amount=amount; stor->storage_amount++; clif_storageitemadded(sd,stor,i,amount); clif_updatestorageamount(sd,stor); stor->dirty = 1; if(log_config.enable_logs&0x800) log_pick_pc(sd, "R", item_data->nameid, -amount, item_data); return 0; }
/** * Attempt to add an item in guild storage, then refresh i * @param stor : guild_storage * @param item : item to add * @param amount : number of item to add * @return True : success, False : fail */ bool gstorage_additem2(struct guild_storage *stor, struct item* item, int amount) { struct item_data *id; int i; nullpo_retr(false, stor); nullpo_retr(false, item); if (item->nameid == 0 || amount <= 0 || !(id = itemdb_exists(item->nameid))) return false; if (item->expire_time) return false; if (itemdb_isstackable2(id)) { //Stackable for (i = 0; i < MAX_GUILD_STORAGE; i++) { if (compare_item(&stor->items[i], item)) { //Set the amount, make it fit with max amount amount = min(amount, ((id->stack.guildstorage) ? id->stack.amount : MAX_AMOUNT) - stor->items[i].amount); if (amount != item->amount) ShowWarning("gstorage_additem2: Stack limit reached! Altered amount of item \""CL_WHITE"%s"CL_RESET"\" (%d). '"CL_WHITE"%d"CL_RESET"' -> '"CL_WHITE"%d"CL_RESET"'.\n", id->name, id->nameid, item->amount, amount); stor->items[i].amount += amount; stor->dirty = true; return true; } } } //Add the item for (i = 0; i < MAX_GUILD_STORAGE && stor->items[i].nameid; i++); if (i >= MAX_GUILD_STORAGE) return false; memcpy(&stor->items[i], item, sizeof(stor->items[0])); stor->items[i].amount = amount; stor->storage_amount++; stor->dirty = true; return true; }
/// Reads items allowed to be sold in buying stores static bool itemdb_read_buyingstore (char *fields[], int columns, int current) { // <nameid> int nameid; struct item_data *id; nameid = atoi (fields[0]); if ( (id = itemdb_exists (nameid)) == NULL) { ShowWarning ("itemdb_read_buyingstore: Invalid item id %d.\n", nameid); return false; } if (!itemdb_isstackable2 (id)) { ShowWarning ("itemdb_read_buyingstore: Non-stackable item id %d cannot be enabled for buying store.\n", nameid); return false; } id->flag.buyingstore = true; return true; }
/*================================================================== * Reads item stacking restrictions *----------------------------------------------------------------*/ static bool itemdb_read_stack(char* fields[], int columns, int current) { // <item id>,<stack limit amount>,<type> unsigned short nameid, amount; unsigned int type; struct item_data* id; nameid = (unsigned short)strtoul(fields[0], NULL, 10); if( ( id = itemdb_exists(nameid) ) == NULL ) { ShowWarning("itemdb_read_stack: Unknown item id '%hu'.\n", nameid); return false; } if( !itemdb_isstackable2(id) ) { ShowWarning("itemdb_read_stack: Item id '%hu' is not stackable.\n", nameid); return false; } amount = (unsigned short)strtoul(fields[1], NULL, 10); type = strtoul(fields[2], NULL, 10); if( !amount ) { // ignore return true; } id->stack.amount = amount; id->stack.inventory = (type&1)!=0; id->stack.cart = (type&2)!=0; id->stack.storage = (type&4)!=0; id->stack.guildstorage = (type&8)!=0; return true; }
/*========================================== * Checks if trade is possible (against zeny limits, inventory limits, etc) *------------------------------------------*/ int trade_check (struct map_session_data *sd, struct map_session_data *tsd) { struct item inventory[MAX_INVENTORY]; struct item inventory2[MAX_INVENTORY]; struct item_data *data; int trade_i, i, n; short amount; // check zenys value against hackers (Zeny was already checked on time of adding, but you never know when you lost some zeny since then. if (sd->deal.zeny > sd->status.zeny || (tsd->status.zeny > MAX_ZENY - sd->deal.zeny)) return 0; if (tsd->deal.zeny > tsd->status.zeny || (sd->status.zeny > MAX_ZENY - tsd->deal.zeny)) return 0; // get inventory of player memcpy (&inventory, &sd->status.inventory, sizeof (struct item) * MAX_INVENTORY); memcpy (&inventory2, &tsd->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) { n = sd->deal.item[trade_i].index; if (amount > inventory[n].amount) return 0; //qty Exploit? data = itemdb_search (inventory[n].nameid); i = MAX_INVENTORY; if (itemdb_isstackable2 (data)) { //Stackable item. 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; break; } } if (i == MAX_INVENTORY) {// look for an empty slot. for (i = 0; i < MAX_INVENTORY && inventory2[i].nameid; i++); if (i == MAX_INVENTORY) return 0; memcpy (&inventory2[i], &inventory[n], sizeof (struct item)); inventory2[i].amount = amount; inventory[n].amount -= amount; } } amount = tsd->deal.item[trade_i].amount; if (!amount) continue; n = tsd->deal.item[trade_i].index; if (amount > inventory2[n].amount) return 0; // search if it's possible to add item (for full inventory) data = itemdb_search (inventory2[n].nameid); i = MAX_INVENTORY; if (itemdb_isstackable2 (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; break; } } if (i == MAX_INVENTORY) { for (i = 0; i < MAX_INVENTORY && inventory[i].nameid; i++); if (i == MAX_INVENTORY) return 0; memcpy (&inventory[i], &inventory2[n], sizeof (struct item)); inventory[i].amount = amount; inventory2[n].amount -= amount; } } return 1; }