/*========================================== * Attempt to open guild storage for sd * return * 0 : success (open or req to create a new one) * 1 : fail * 2 : no guild for sd *------------------------------------------*/ int storage_guild_storageopen(struct map_session_data* sd) { struct guild_storage *gstor; nullpo_ret(sd); if(sd->status.guild_id <= 0) return 2; if(sd->state.storage_flag) return 1; //Can't open both storages at a time. if( !pc_can_give_items(sd) ) { //check is this GM level can open guild storage and store items [Lupus] clif_displaymessage(sd->fd, msg_txt(sd,246)); return 1; } if((gstor = guild2storage2(sd->status.guild_id)) == NULL) { intif_request_guild_storage(sd->status.account_id,sd->status.guild_id); return 0; } if(gstor->storage_status) return 1; if( gstor->lock ) return 1; gstor->storage_status = 1; sd->state.storage_flag = 2; storage_sortitem(gstor->items, ARRAYLENGTH(gstor->items)); clif_storagelist(sd, gstor->items, ARRAYLENGTH(gstor->items)); clif_updatestorageamount(sd, gstor->storage_amount, MAX_GUILD_STORAGE); return 0; }
/*========================================== * Opens a storage. Returns: * 0 - success * 1 - fail * 2 - Storage requested from char-server (will open automatically later) *------------------------------------------ */ int storage_storageopen(struct map_session_data *sd) { struct storage *stor; nullpo_retr(0, sd); if(sd->state.finalsave) //Refuse to open storage when you had your last save done. return 1; if(sd->state.storage_flag) return 1; //Already open? if(pc_can_give_items(pc_isGM(sd))) { //check is this GM level is allowed to put items to storage clif_displaymessage(sd->fd, msg_txt(246)); return 1; } if((stor = idb_get(storage_db,sd->status.account_id)) == NULL) { //Request storage. intif_request_storage(sd->status.account_id); return 2; } if (stor->storage_status) return 1; //Already open/player already has it open... stor->storage_status = 1; sd->state.storage_flag = 1; clif_storagelist(sd,stor); clif_updatestorageamount(sd,stor); return 0; }
/*========================================== * カプラ倉庫を開く *------------------------------------------ */ int storage_storageopen(struct map_session_data *sd) { struct storage *stor; int gmlvl = 0; nullpo_retr(0, sd); if(sd->state.storage_flag == 1) return 0; // 既にカプラ倉庫を開いている gmlvl = pc_isGM(sd); if(gmlvl > 0 && battle_config.gm_can_drop_lv > gmlvl) return 0; // 設定しているGMレベルより低い if((stor = (struct storage *)numdb_search(storage_db,sd->status.account_id)) != NULL) { if(stor->storage_status) return 1; stor->storage_status = 1; } if(sd->state.storage_flag == 2) storage_guild_storageclose(sd); // ギルド倉庫をすでに開いている場合閉じる if(stor != NULL) { sd->state.storage_flag = 1; clif_storageitemlist(sd,stor); clif_storageequiplist(sd,stor); clif_updatestorageamount(sd,stor); } else { intif_request_storage(sd->status.account_id); } return 0; }
/** * 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; }
/** * Open premium storage * @param sd Player **/ void storage_premiumStorage_open(struct map_session_data *sd) { nullpo_retv(sd); if (!&sd->premiumStorage) return; sd->state.storage_flag = 3; storage_sortitem(sd->premiumStorage.u.items_storage, sd->premiumStorage.max_amount); clif_storagelist(sd, sd->premiumStorage.u.items_storage, sd->premiumStorage.max_amount, storage_getName(sd->premiumStorage.stor_id)); clif_updatestorageamount(sd, sd->premiumStorage.amount, sd->premiumStorage.max_amount); }
/*========================================== * 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; }
/*========================================== * カプラ倉庫へアイテム追加 *------------------------------------------ */ static int storage_additem(struct map_session_data *sd,struct 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; nullpo_retr(1, data = itemdb_search(item_data->nameid)); if(!itemdb_isequip2(data)) { // 装備品ではないので、既所有品なら個数のみ変化させる for(i=0; i<MAX_STORAGE; i++) { if(stor->store_item[i].nameid == item_data->nameid && stor->store_item[i].card[0] == item_data->card[0] && stor->store_item[i].card[1] == item_data->card[1] && stor->store_item[i].card[2] == item_data->card[2] && stor->store_item[i].card[3] == item_data->card[3] && stor->store_item[i].limit == item_data->limit) { if(stor->store_item[i].amount + amount > MAX_AMOUNT) return 1; stor->store_item[i].amount += amount; stor->dirty = 1; clif_storageitemadded(sd,stor,i,amount); return 0; } } } else if(amount != 1) { return 1; } // 装備品か未所有品だったので空き欄へ追加 for(i=0; i<MAX_STORAGE; i++) { if(stor->store_item[i].nameid == 0) { memcpy(&stor->store_item[i],item_data,sizeof(stor->store_item[0])); stor->store_item[i].id = ++stor->sortkey; stor->store_item[i].amount = amount; stor->storage_amount++; stor->dirty = 1; clif_storageitemadded(sd,stor,i,amount); clif_updatestorageamount(sd,stor); return 0; } } return 1; }
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; 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; }
// 倉庫データ受信 static int intif_parse_LoadStorage (int fd) { struct storage *stor; struct map_session_data *sd; sd = map_id2sd (RFIFOL (fd, 4)); if (sd == NULL) { if (battle_config.error_log) printf ("intif_parse_LoadStorage: user not found %d\n", RFIFOL (fd, 4)); return 1; } stor = account2storage (RFIFOL (fd, 4)); if (stor->storage_status == 1) { // Already open.. lets ignore this update if (battle_config.error_log) printf ("intif_parse_LoadStorage: storage received for a client already open (User %d:%d)\n", sd->status.account_id, sd->status.char_id); return 1; } if (stor->dirty) { // Already have storage, and it has been modified and not saved yet! Exploit! [Skotlex] if (battle_config.error_log) printf ("intif_parse_LoadStorage: received storage for an already modified non-saved storage! (User %d:%d)\n", sd->status.account_id, sd->status.char_id); return 1; } if (RFIFOW (fd, 2) - 8 != sizeof (struct storage)) { if (battle_config.error_log) printf ("intif_parse_LoadStorage: data size error %d %d\n", RFIFOW (fd, 2) - 8, sizeof (struct storage)); return 1; } if (battle_config.save_log) printf ("intif_openstorage: %d\n", RFIFOL (fd, 4)); memcpy (stor, RFIFOP (fd, 8), sizeof (struct storage)); stor->dirty = 0; stor->storage_status = 1; sd->state.storage_flag = 1; clif_storageitemlist (sd, stor); clif_storageequiplist (sd, stor); clif_updatestorageamount (sd, stor); 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; }
/*========================================== * Internal del-item function *------------------------------------------*/ int storage_delitem(struct map_session_data* sd, int n, int amount) { if( sd->status.storage.items[n].nameid == 0 || sd->status.storage.items[n].amount < amount ) return 1; sd->status.storage.items[n].amount -= amount; if( sd->status.storage.items[n].amount == 0 ) { memset(&sd->status.storage.items[n],0,sizeof(sd->status.storage.items[0])); sd->status.storage.storage_amount--; if( sd->state.storage_flag == 1 ) clif_updatestorageamount(sd, sd->status.storage.storage_amount, MAX_STORAGE); } if( sd->state.storage_flag == 1 ) clif_storageitemremoved(sd,n,amount); return 0; }
/*========================================== * Opens a storage. Returns: * 0 - success * 1 - fail *------------------------------------------*/ int storage_storageopen(struct map_session_data *sd) { nullpo_retr(0, sd); if(sd->state.storage_flag) return 1; //Already open? if( !pc_can_give_items(pc_isGM(sd)) ) { //check is this GM level is allowed to put items to storage clif_displaymessage(sd->fd, msg_txt(246)); return 1; } sd->state.storage_flag = 1; clif_storagelist(sd,&sd->status.storage); clif_updatestorageamount(sd,sd->status.storage.storage_amount); return 0; }
/** * Player attempt tp open his storage. * @param sd : player * @return 0 : success, 1 : fail */ int storage_storageopen(struct map_session_data *sd) { nullpo_ret(sd); if (sd->state.storage_flag) return 1; //Already open? if (!pc_can_give_items(sd)) { //Check is this GM level is allowed to put items to storage clif_displaymessage(sd->fd, msg_txt(246)); return 1; } sd->state.storage_flag = 1; storage_sortitem(sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items)); clif_storagelist(sd, sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items)); clif_updatestorageamount(sd, sd->status.storage.storage_amount, sd->storage_size); return 0; }
/*========================================== * Attempt to delete an item in guild storage, then refresh it * return * 0 : success * 1 : fail *------------------------------------------*/ int guild_storage_delitem(struct map_session_data* sd, struct guild_storage* stor, int n, int amount) { nullpo_retr(1, sd); nullpo_retr(1, stor); if(stor->items[n].nameid==0 || stor->items[n].amount<amount) return 1; stor->items[n].amount-=amount; if(stor->items[n].amount==0){ memset(&stor->items[n],0,sizeof(stor->items[0])); stor->storage_amount--; clif_updatestorageamount(sd, stor->storage_amount, MAX_GUILD_STORAGE); } clif_storageitemremoved(sd,n,amount); stor->dirty = 1; return 0; }
/*========================================== * Internal del-item function *------------------------------------------ */ static int storage_delitem(struct map_session_data *sd,struct storage *stor,int n,int amount) { if(stor->storage_[n].nameid==0 || stor->storage_[n].amount<amount) return 1; stor->storage_[n].amount-=amount; if(log_config.enable_logs&0x800) log_pick_pc(sd, "R", stor->storage_[n].nameid, amount, &stor->storage_[n]); if(stor->storage_[n].amount==0){ memset(&stor->storage_[n],0,sizeof(stor->storage_[0])); stor->storage_amount--; clif_updatestorageamount(sd,stor); } clif_storageitemremoved(sd,n,amount); stor->dirty = 1; return 0; }
/** * Player attempt tp open his storage. * @param sd : player * @return 0:success, 1:fail */ int storage_storageopen(struct map_session_data *sd) { nullpo_ret(sd); if(sd->state.storage_flag) return 1; //Already open? if( !pc_can_give_items(sd) ) { // check is this GM level is allowed to put items to storage clif_displaymessage(sd->fd, msg_txt(sd,246)); return 1; } sd->state.storage_flag = 1; storage_sortitem(sd->storage.u.items_storage, sd->storage.max_amount); clif_storagelist(sd, sd->storage.u.items_storage, sd->storage.max_amount, storage_getName(0)); clif_updatestorageamount(sd, sd->storage.amount, sd->storage.max_amount); return 0; }
/*========================================== * Internal del-item function *------------------------------------------*/ int storage_delitem(struct map_session_data* sd, int n, int amount) { if( sd->status.storage.items[n].nameid == 0 || sd->status.storage.items[n].amount < amount ) return 1; sd->status.storage.items[n].amount -= amount; if(log_config.enable_logs&0x800) log_pick_pc(sd, "R", sd->status.storage.items[n].nameid, amount, &sd->status.storage.items[n]); if( sd->status.storage.items[n].amount == 0 ) { memset(&sd->status.storage.items[n],0,sizeof(sd->status.storage.items[0])); sd->status.storage.storage_amount--; if( sd->state.storage_flag == 1 ) clif_updatestorageamount(sd,sd->status.storage.storage_amount); } if( sd->state.storage_flag == 1 ) clif_storageitemremoved(sd,n,amount); return 0; }
/** * Attempt to delete an item in guild storage, then refresh it * @param sd : player * @param stor : guild_storage * @param n : index of item in guild storage * @param amount : number of item to delete * @return True : success, False : fail */ bool storage_guild_delitem(struct map_session_data* sd, struct s_storage* stor, int n, int amount) { nullpo_retr(1, sd); nullpo_retr(1, stor); if(!stor->u.items_guild[n].nameid || stor->u.items_guild[n].amount < amount) return false; stor->u.items_guild[n].amount -= amount; if(!stor->u.items_guild[n].amount) { memset(&stor->u.items_guild[n],0,sizeof(stor->u.items_guild[0])); stor->amount--; clif_updatestorageamount(sd, stor->amount, MAX_GUILD_STORAGE); } clif_storageitemremoved(sd,n,amount); stor->dirty = true; return true; }
/*========================================== * カプラ倉庫からアイテムを減らす *------------------------------------------ */ static void storage_delitem(struct map_session_data *sd,struct storage *stor,int n,int amount) { nullpo_retv(sd); nullpo_retv(stor); if(stor->store_item[n].nameid == 0 || stor->store_item[n].amount < amount) return; stor->store_item[n].amount -= amount; if(stor->store_item[n].amount <= 0) { memset(&stor->store_item[n],0,sizeof(stor->store_item[0])); stor->store_item[n].id = 0; stor->storage_amount--; clif_updatestorageamount(sd,stor); } stor->dirty = 1; clif_storageitemremoved(sd,n,amount); return; }
/** * Make a player delete an item from his storage * @param sd : player * @param n : idx on storage to remove the item from * @param amount :number of item to remove * @return 0:sucess, 1:fail */ int storage_delitem(struct map_session_data* sd, struct s_storage *stor, int index, int amount) { if( stor->u.items_storage[index].nameid == 0 || stor->u.items_storage[index].amount < amount ) return 1; stor->u.items_storage[index].amount -= amount; stor->dirty = true; if( stor->u.items_storage[index].amount == 0 ) { memset(&stor->u.items_storage[index],0,sizeof(stor->u.items_storage[0])); stor->amount--; if( sd->state.storage_flag == 1 || sd->state.storage_flag == 3 ) clif_updatestorageamount(sd, stor->amount, sd->storage.max_amount); } if( sd->state.storage_flag == 1 || sd->state.storage_flag == 3 ) clif_storageitemremoved(sd,index,amount); return 0; }
// 倉庫データ受信 static int intif_parse_LoadStorage(Session *, const Packet_Payload<0x3810>& payload) { dumb_ptr<map_session_data> sd; sd = map_id2sd(account_to_block(payload.account_id)); if (sd == nullptr) { if (battle_config.error_log) PRINTF("intif_parse_LoadStorage: user not found %d\n"_fmt, payload.account_id); return 1; } P<Storage> stor = account2storage(payload.account_id); if (stor->storage_status == 1) { // Already open.. lets ignore this update if (battle_config.error_log) PRINTF("intif_parse_LoadStorage: storage received for a client already open (User %d:%d)\n"_fmt, sd->status_key.account_id, sd->status_key.char_id); return 1; } if (stor->dirty) { // Already have storage, and it has been modified and not saved yet! Exploit! [Skotlex] if (battle_config.error_log) PRINTF("intif_parse_LoadStorage: received storage for an already modified non-saved storage! (User %d:%d)\n"_fmt, sd->status_key.account_id, sd->status_key.char_id); return 1; } if (battle_config.save_log) PRINTF("intif_openstorage: %d\n"_fmt, payload.account_id); *stor = payload.storage; stor->dirty = 0; stor->storage_status = 1; sd->state.storage_open = 1; clif_storageitemlist(sd, stor); clif_storageequiplist(sd, stor); clif_updatestorageamount(sd, stor); return 0; }
/*========================================== * カプラ倉庫データの受信 *------------------------------------------ */ int storage_storageload(int account_id, struct storage *s) { struct map_session_data *sd; struct storage *stor; nullpo_retr(1, s); sd = map_id2sd(account_id); if(sd == NULL || sd->state.waitingdisconnect) { if(battle_config.error_log && sd == NULL) printf("storage_storageload: user not found %d\n", account_id); storage_delete(account_id); return 1; } // 既に倉庫を開いてないかチェック if(sd->state.storage_flag == 1) return 0; if(sd->state.storage_flag == 2) storage_guild_storageclose(sd); stor = account2storage(account_id); if(battle_config.save_log) printf("storageload: %d\n", account_id); memcpy(stor, s, sizeof(struct storage)); storage_sortitem(stor->store_item, MAX_STORAGE, &stor->sortkey, battle_config.personal_storage_sort); stor->storage_status = 1; sd->state.storage_flag = 1; clif_storageitemlist(sd,stor); clif_storageequiplist(sd,stor); clif_updatestorageamount(sd,stor); return 0; }
int ext_storage_open(struct map_session_data *sd) { nullpo_ret(sd); if(sd->state.storage_flag) return 1; if( !pc_can_give_items(pc_isGM(sd)) ) { //check is this GM level is allowed to put items to storage clif_displaymessage(sd->fd, msg_txt(246)); return 1; } if( map[sd->bl.m].flag.nostorage ) { clif_displaymessage(sd->fd, msg_txt(911)); return 1; } sd->state.storage_flag = 3; storage_sortitem(sd->status.ext_storage.items, ARRAYLENGTH(sd->status.ext_storage.items)); clif_storagelist(sd, sd->status.ext_storage.items, ARRAYLENGTH(sd->status.ext_storage.items)); clif_updatestorageamount(sd, sd->status.storage.storage_amount, MAX_EXTRA_STORAGE); return 0; }