From 022d72891e1c38ac6953a5118eea87efd7deddc3 Mon Sep 17 00:00:00 2001 From: Cydh Ramdh Date: Sat, 3 Jan 2015 20:37:38 +0700 Subject: [PATCH] Changed Guild/Party Bound Item Retrieval Methods: * Bug Fixes bug:9338 * Now resend the list to map-server from char/inter-server to avoid "weird" item allocation on guild storage. Example, previously you will meet stacked item like GUID does, but it shouldn't! * Also will check the maximum amount that can be store in guild store. If guild storage is full (the slots or item stack limit is reach) the rest value/item will be dropped. * Account of kicked guild member won't be kicked from server anymore if the player idle on character select window (just prevents player to login when retriving items are in progress) * Delete guild bound items from guild master when guild is disbanded! Previously, the bound type just changed to NONE. Also for party bound item. * If kicked guild/party member is trading bound item when be kicked, the trade will be canceled! * If the guild member is being kicked when open guild storage, storage will be closed first waiting for next item retrieval. * Now when guild storage is opened, storage_status (changed the var to 'opened') will be used to hold char_id who opens it. Misc: * Cleanup guild storage prefix functions, changed them to "gstorage_*" * Added `picklog` type 'B' for logging deleted bound item because of kicked from guild/party. * Updated documentation for new used packet 0x3857 NOTE: Please import upgrade-20150103_log.sql Signed-off-by: Cydh Ramdh --- doc/packet_interserv.txt | 14 ++ sql-files/upgrades/upgrade_20150103_log.sql | 1 + src/char/char.c | 17 ++ src/char/char.h | 5 + src/char/char_clif.c | 9 + src/char/int_storage.c | 234 ++++++++---------- src/common/mmo.h | 6 +- src/map/atcommand.c | 22 +- src/map/chrif.c | 2 +- src/map/clif.c | 74 +++--- src/map/guild.c | 133 ++++++---- src/map/guild.h | 2 +- src/map/intif.c | 72 ++++-- src/map/intif.h | 2 +- src/map/itemdb.c | 5 +- src/map/log.c | 1 + src/map/log.h | 1 + src/map/map.c | 20 +- src/map/party.c | 34 ++- src/map/party.h | 2 +- src/map/pc.c | 26 +- src/map/pc.h | 1 + src/map/script.c | 2 +- src/map/storage.c | 254 +++++++++++--------- src/map/storage.h | 29 +-- src/map/trade.c | 10 + src/map/unit.c | 2 +- 27 files changed, 573 insertions(+), 407 deletions(-) create mode 100644 sql-files/upgrades/upgrade_20150103_log.sql diff --git a/doc/packet_interserv.txt b/doc/packet_interserv.txt index e550883fea..06f6f9ed2b 100644 --- a/doc/packet_interserv.txt +++ b/doc/packet_interserv.txt @@ -2021,6 +2021,20 @@ Currently the max packet size is 0xFFFF (see 'WFIFOSET()' in 'src/common/socket. desc: - Acknowledge the good deletion of the bound item +0x3857 + Type: IZ + Structure: .W .W .W .W { .?B }*MAX_INVENTORY + index: 0,2,4,6,8 + len: variable: 8+items + parameter: + - cmd : packet identification (0x3856) + - size + - count : number of item retrieved + - guild_id + - items: retreived guild bound items + desc: + - Ask map-server to process the retreived guild bound items from expelled member + 0x3860 Type: IZ Structure: .W .W .L .?B diff --git a/sql-files/upgrades/upgrade_20150103_log.sql b/sql-files/upgrades/upgrade_20150103_log.sql new file mode 100644 index 0000000000..98fda3d397 --- /dev/null +++ b/sql-files/upgrades/upgrade_20150103_log.sql @@ -0,0 +1 @@ +ALTER TABLE `picklog` MODIFY `type` ENUM('M','P','L','T','V','S','N','C','A','R','G','E','B','O','I','X','D','U','$') NOT NULL DEFAULT 'S'; diff --git a/src/char/char.c b/src/char/char.c index f29edbc0c9..3b04ffc990 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -1809,7 +1809,24 @@ void char_disconnect_player(uint32 account_id) set_eof(i); } +/** +* Set 'flag' value of char_session_data +* @param account_id +* @param value +* @param set True: set the value by using '|= val', False: unset the value by using '&= ~val' +**/ +void char_set_session_flag_(int account_id, int val, bool set) { + int i; + struct char_session_data* sd; + ARR_FIND(0, fd_max, i, session[i] && (sd = (struct char_session_data*)session[i]->session_data) && sd->account_id == account_id); + if (i < fd_max) { + if (set) + sd->flag |= val; + else + sd->flag &= ~val; + } +} void char_auth_ok(int fd, struct char_session_data *sd) { struct online_char_data* character; diff --git a/src/char/char.h b/src/char/char.h index 2a325f1d1e..6c2d2979d5 100644 --- a/src/char/char.h +++ b/src/char/char.h @@ -199,6 +199,7 @@ struct char_session_data { uint8 isvip; time_t unban_time[MAX_CHARS]; int charblock_timer; + uint8 flag; // &1 - Retrieving guild bound items }; @@ -263,6 +264,10 @@ int char_make_new_char_sql(struct char_session_data* sd, char* name_, int slot, int char_make_new_char_sql(struct char_session_data* sd, char* name_, int str, int agi, int vit, int int_, int dex, int luk, int slot, int hair_color, int hair_style); #endif +void char_set_session_flag_(int account_id, int val, bool set); +#define char_set_session_flag(account_id, val) ( char_set_session_flag_((account_id), (val), true) ) +#define char_unset_session_flag(account_id, val) ( char_set_session_flag_((account_id), (val), false) ) + //For use in packets that depend on an sd being present [Skotlex] #define FIFOSD_CHECK(rest) { if(RFIFOREST(fd) < rest) return 0; if (sd==NULL || !sd->auth) { RFIFOSKIP(fd,rest); return 0; } } diff --git a/src/char/char_clif.c b/src/char/char_clif.c index 46e6e14676..8258c4f94a 100644 --- a/src/char/char_clif.c +++ b/src/char/char_clif.c @@ -704,6 +704,15 @@ int chclif_parse_charselect(int fd, struct char_session_data* sd,uint32 ipl){ char_id = atoi(data); Sql_FreeResult(sql_handle); + // Prevent select a char while retrieving guild bound items + if (sd->flag&1) { + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x6c; + WFIFOB(fd,2) = 0; // rejected from server + WFIFOSET(fd,3); + return 1; + } + /* client doesn't let it get to this point if you're banned, so its a forged packet */ if( sd->found_char[slot] == char_id && sd->unban_time[slot] > time(NULL) ) { WFIFOHEAD(fd,3); diff --git a/src/char/int_storage.c b/src/char/int_storage.c index 58096a4710..d5f80234d2 100644 --- a/src/char/int_storage.c +++ b/src/char/int_storage.c @@ -229,47 +229,81 @@ int mapif_parse_SaveGuildStorage(int fd) mapif_save_guild_storage_ack(fd, RFIFOL(fd,4), guild_id, 1); return 0; } + #ifdef BOUND_ITEMS -int mapif_itembound_ack(int fd, int aid, int guild_id) +/** +* IZ 0x3856 .L .W +* Tells map-server if the process if complete, unlock the guild storage +*/ +static void mapif_itembound_ack(int fd, int account_id, int guild_id) { WFIFOHEAD(fd,8); WFIFOW(fd,0) = 0x3856; - WFIFOL(fd,2) = aid; + WFIFOL(fd,2) = account_id; WFIFOW(fd,6) = guild_id; WFIFOSET(fd,8); - return 0; + char_unset_session_flag(account_id, 1); } -//------------------------------------------------ -//Guild bound items pull for offline characters [Akinari] -//------------------------------------------------ +/** +* IZ 0x3857 .W .W .W { .?B }.*MAX_INVENTORY +* Send the retrieved guild bound items to map-server, store them to guild storage. +* By using this method, stackable items will looks how it should be, and overflowed +* item's stack won't disturbs the guild storage table and the leftover items (when +* storage is full) will be discarded. +* @param fd +* @param guild_id +* @param items[] +* @param count +* @author [Cydh] +*/ +static void mapif_itembound_store2gstorage(int fd, int guild_id, struct item items[], unsigned short count) { + int size = 8 + sizeof(struct item) * MAX_INVENTORY, i; + + WFIFOHEAD(fd, size); + WFIFOW(fd, 0) = 0x3857; + WFIFOW(fd, 2) = size; + WFIFOW(fd, 6) = guild_id; + for (i = 0; i < count && i < MAX_INVENTORY; i++) { + if (!&items[i]) + continue; + memcpy(WFIFOP(fd, 8 + (i * sizeof(struct item))), &items[i], sizeof(struct item)); + } + WFIFOW(fd, 4) = i; + WFIFOSET(fd, size); +} + +/** +* ZI 0x3056 .L .L .W +* Pulls guild bound items for offline characters +* @author [Akinari] +*/ int mapif_parse_itembound_retrieve(int fd) { StringBuf buf; SqlStmt* stmt; - struct item item; - int j, i = 0, s = 0, bound_qt = 0; bool found = false; - struct item items[MAX_INVENTORY]; - unsigned int bound_item[MAX_INVENTORY] = { 0 }; - uint32 char_id = RFIFOL(fd,2); - int aid = RFIFOL(fd,6); - int guild_id = RFIFOW(fd,10); + unsigned short i = 0, count = 0, size = 0; + struct item item, items[MAX_INVENTORY] = { 0 }; + int j, guild_id = RFIFOW(fd,10); + uint32 char_id = RFIFOL(fd,2), account_id = RFIFOL(fd,6); StringBuf_Init(&buf); + + // Get bound items from player's inventory StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`"); for( j = 0; j < MAX_SLOTS; ++j ) StringBuf_Printf(&buf, ", `card%d`", j); - StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`='%d'",schema_config.inventory_db,char_id); + StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`='%d' AND `bound` = %d", schema_config.inventory_db,char_id, BOUND_GUILD); stmt = SqlStmt_Malloc(sql_handle); - if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) - || SQL_ERROR == SqlStmt_Execute(stmt) ) + if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) || + SQL_ERROR == SqlStmt_Execute(stmt) ) { SqlStmt_ShowDebug(stmt); SqlStmt_Free(stmt); StringBuf_Destroy(&buf); - mapif_itembound_ack(fd,aid,guild_id); + mapif_itembound_ack(fd,account_id,guild_id); return 1; } @@ -285,83 +319,67 @@ int mapif_parse_itembound_retrieve(int fd) for( j = 0; j < MAX_SLOTS; ++j ) SqlStmt_BindColumn(stmt, 9+j, SQLDT_SHORT, &item.card[j], 0, NULL, NULL); - while( SQL_SUCCESS == SqlStmt_NextRow(stmt) ) { - if(item.bound == BOUND_GUILD) { - memcpy(&items[i],&item,sizeof(struct item)); - i++; - } - } + while( SQL_SUCCESS == SqlStmt_NextRow(stmt) ) + memcpy(&items[count++], &item, sizeof(struct item)); Sql_FreeResult(sql_handle); - if(!i) { //No items found - No need to continue + ShowInfo("Found '"CL_WHITE"%d"CL_RESET"' guild bound item(s) from CID = "CL_WHITE"%d"CL_RESET", AID = %d, Guild ID = "CL_WHITE"%d"CL_RESET".\n", count, char_id, account_id, guild_id); + if (!count) { //No items found - No need to continue StringBuf_Destroy(&buf); SqlStmt_Free(stmt); - mapif_itembound_ack(fd,aid,guild_id); - return 0; + mapif_itembound_ack(fd,account_id,guild_id); + return 1; } - //First we delete the character's items + char_set_session_flag(account_id, 1); + + // Delete bound items from player's inventory StringBuf_Clear(&buf); - StringBuf_Printf(&buf, "DELETE FROM `%s` WHERE",schema_config.inventory_db); - for(j=0; jstatus.guild_id); + gstorage = gstorage_get_storage(sd->status.guild_id); if (gstorage == NULL) {// Doesn't have opened @gstorage yet, so we skip the deletion since *shouldn't* have any item there. return -1; } - j = gstorage->storage_amount; - gstorage->lock = 1; // Lock @gstorage: do not allow any item to be retrieved or stored from any guild member - for (i = 0; i < j; ++i) { - guild_storage_delitem(sd, gstorage, i, gstorage->items[i].amount); + if (gstorage->opened) { + struct map_session_data *tsd = map_charid2sd(gstorage->opened); + if (tsd) + gstorage_storageclose(tsd); } - storage_guild_storageclose(sd); - gstorage->lock = 0; // Cleaning done, release lock + + j = gstorage->storage_amount; + gstorage->locked = true; // Lock @gstorage: do not allow any item to be retrieved or stored from any guild member + for (i = 0; i < j; ++i) { + gstorage_delitem(sd, gstorage, i, gstorage->items[i].amount); + } + gstorage_storageclose(sd); + gstorage->locked = false; // Cleaning done, release lock clif_displaymessage(fd, msg_txt(sd,1395)); // Your guild storage was cleaned. return 0; diff --git a/src/map/chrif.c b/src/map/chrif.c index 6b387ef728..4810b7f524 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -293,7 +293,7 @@ int chrif_save(struct map_session_data *sd, int flag) { //For data sync if (sd->state.storage_flag == 2) - storage_guild_storagesave(sd->status.account_id, sd->status.guild_id, flag); + gstorage_storagesave(sd->status.account_id, sd->status.guild_id, flag); if (flag) sd->state.storage_flag = 0; //Force close it. diff --git a/src/map/clif.c b/src/map/clif.c index 9c39efde6d..fe9fd7eea8 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -2198,30 +2198,30 @@ void clif_additem(struct map_session_data *sd, int n, int amount, unsigned char WFIFOHEAD(fd,packet_len(header)); if( fail ) { - WFIFOW(fd,offs+0)=header; - WFIFOW(fd,offs+2)=n+2; - WFIFOW(fd,offs+4)=amount; - WFIFOW(fd,offs+6)=0; - WFIFOB(fd,offs+8)=0; - WFIFOB(fd,offs+9)=0; - WFIFOB(fd,offs+10)=0; - WFIFOW(fd,offs+11)=0; - WFIFOW(fd,offs+13)=0; - WFIFOW(fd,offs+15)=0; - WFIFOW(fd,offs+17)=0; + WFIFOW(fd,offs+0) = header; + WFIFOW(fd,offs+2) = n+2; + WFIFOW(fd,offs+4) = amount; + WFIFOW(fd,offs+6) = 0; + WFIFOB(fd,offs+8) = 0; + WFIFOB(fd,offs+9) = 0; + WFIFOB(fd,offs+10) = 0; + WFIFOW(fd,offs+11) = 0; + WFIFOW(fd,offs+13) = 0; + WFIFOW(fd,offs+15) = 0; + WFIFOW(fd,offs+17) = 0; #if PACKETVER < 20120925 - WFIFOW(fd,offs+19)=0; + WFIFOW(fd,offs+19) = 0; #else - WFIFOL(fd,offs+19)=0; + WFIFOL(fd,offs+19) = 0; offs += 2; #endif - WFIFOB(fd,offs+21)=0; - WFIFOB(fd,offs+22)=fail; + WFIFOB(fd,offs+21) = 0; + WFIFOB(fd,offs+22) = fail; #if PACKETVER >= 20061218 - WFIFOL(fd,offs+23)=0; + WFIFOL(fd,offs+23) = 0; #endif #if PACKETVER >= 20071002 - WFIFOW(fd,offs+27)=0; // HireExpireDate + WFIFOW(fd,offs+27) = 0; // HireExpireDate #endif } else @@ -2229,31 +2229,31 @@ void clif_additem(struct map_session_data *sd, int n, int amount, unsigned char if( n < 0 || n >= MAX_INVENTORY || sd->status.inventory[n].nameid <=0 || sd->inventory_data[n] == NULL ) return; - WFIFOW(fd,offs+0)=header; - WFIFOW(fd,offs+2)=n+2; - WFIFOW(fd,offs+4)=amount; + WFIFOW(fd,offs+0) = header; + WFIFOW(fd,offs+2) = n+2; + WFIFOW(fd,offs+4) = amount; if (sd->inventory_data[n]->view_id > 0) - WFIFOW(fd,offs+6)=sd->inventory_data[n]->view_id; + WFIFOW(fd,offs+6) = sd->inventory_data[n]->view_id; else - WFIFOW(fd,offs+6)=sd->status.inventory[n].nameid; - WFIFOB(fd,offs+8)=sd->status.inventory[n].identify; - WFIFOB(fd,offs+9)=sd->status.inventory[n].attribute; - WFIFOB(fd,offs+10)=sd->status.inventory[n].refine; + WFIFOW(fd,offs+6) = sd->status.inventory[n].nameid; + WFIFOB(fd,offs+8) = sd->status.inventory[n].identify; + WFIFOB(fd,offs+9) = sd->status.inventory[n].attribute; + WFIFOB(fd,offs+10) = sd->status.inventory[n].refine; clif_addcards(WFIFOP(fd,offs+11), &sd->status.inventory[n]); #if PACKETVER < 20120925 - WFIFOW(fd,offs+19)=pc_equippoint(sd,n); + WFIFOW(fd,offs+19) = pc_equippoint(sd,n); #else - WFIFOL(fd,offs+19)=pc_equippoint(sd,n); + WFIFOL(fd,offs+19) = pc_equippoint(sd,n); offs += 2; #endif - WFIFOB(fd,offs+21)=itemtype(sd->inventory_data[n]->nameid); - WFIFOB(fd,offs+22)=fail; + WFIFOB(fd,offs+21) = itemtype(sd->inventory_data[n]->nameid); + WFIFOB(fd,offs+22) = fail; #if PACKETVER >= 20061218 - WFIFOL(fd,offs+23)=sd->status.inventory[n].expire_time; + WFIFOL(fd,offs+23) = sd->status.inventory[n].expire_time; #endif #if PACKETVER >= 20071002 /* Yellow color only for non-stackable item */ - WFIFOW(fd,offs+27)=(sd->status.inventory[n].bound && !itemdb_isstackable(sd->status.inventory[n].nameid)) ? BOUND_DISPYELLOW : 0; + WFIFOW(fd,offs+27) = (sd->status.inventory[n].bound && !itemdb_isstackable(sd->status.inventory[n].nameid)) ? BOUND_DISPYELLOW : 0; #endif } @@ -8676,7 +8676,7 @@ void clif_refresh_storagewindow(struct map_session_data *sd) { // Notify the client that the gstorage is open otherwise it will // remain locked forever and nobody will be able to access it if( sd->state.storage_flag == 2 ) { - struct guild_storage *gstor = guild2storage2(sd->status.guild_id); + struct guild_storage *gstor = gstorage_get_storage(sd->status.guild_id); if( !gstor ) // Shouldn't happen. The information should already be at the map-server intif_request_guild_storage(sd->status.account_id, sd->status.guild_id); @@ -11915,7 +11915,7 @@ void clif_parse_MoveToKafra(int fd, struct map_session_data *sd) storage_storageadd(sd, item_index, item_amount); else if (sd->state.storage_flag == 2) - storage_guild_storageadd(sd, item_index, item_amount); + gstorage_storageadd(sd, item_index, item_amount); } @@ -11934,7 +11934,7 @@ void clif_parse_MoveFromKafra(int fd,struct map_session_data *sd) if (sd->state.storage_flag == 1) storage_storageget(sd, item_index, item_amount); else if(sd->state.storage_flag == 2) - storage_guild_storageget(sd, item_index, item_amount); + gstorage_storageget(sd, item_index, item_amount); } @@ -11954,7 +11954,7 @@ void clif_parse_MoveToKafraFromCart(int fd, struct map_session_data *sd){ if (sd->state.storage_flag == 1) storage_storageaddfromcart(sd, idx, amount); else if (sd->state.storage_flag == 2) - storage_guild_storageaddfromcart(sd, idx, amount); + gstorage_storageaddfromcart(sd, idx, amount); } @@ -11974,7 +11974,7 @@ void clif_parse_MoveFromKafraToCart(int fd, struct map_session_data *sd){ storage_storagegettocart(sd, idx, amount); else if (sd->state.storage_flag == 2) - storage_guild_storagegettocart(sd, idx, amount); + gstorage_storagegettocart(sd, idx, amount); } @@ -11986,7 +11986,7 @@ void clif_parse_CloseKafra(int fd, struct map_session_data *sd) storage_storageclose(sd); else if( sd->state.storage_flag == 2 ) - storage_guild_storageclose(sd); + gstorage_storageclose(sd); } diff --git a/src/map/guild.c b/src/map/guild.c index 5b04dd5326..5e0b8c8cab 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -19,6 +19,8 @@ #include "pc.h" #include "intif.h" #include "channel.h" +#include "log.h" +#include "trade.h" #include @@ -39,7 +41,6 @@ struct eventlist { #define GUILD_PAYEXP_LIST 8192 //The maximum number of cache //Guild EXP cache - struct guild_expcache { int guild_id, account_id, char_id; uint64 exp; @@ -408,6 +409,20 @@ int guild_npc_request_info(int guild_id,const char *event) { return guild_request_info(guild_id); } +/** + * Close trade window if party member is kicked when trade a party bound item + * @param sd + **/ +static void guild_trade_bound_cancel(struct map_session_data *sd) { +#ifdef BOUND_ITEMS + nullpo_retv(sd); + if (sd->state.isBoundTrading&(1<bl.m].flag.gvg_castle)) return 0; + guild_trade_bound_cancel(sd); intif_guild_leave(sd->status.guild_id, sd->status.account_id, sd->status.char_id,0,mes); return 0; } @@ -773,12 +789,24 @@ int guild_expulsion(struct map_session_data* sd, int guild_id, uint32 account_id // find the member and perform expulsion i = guild_getindex(g, account_id, char_id); - if( i != -1 && strcmp(g->member[i].name,g->master) != 0 ) //Can't expel the GL! + if( i != -1 && strcmp(g->member[i].name,g->master) != 0 ) { //Can't expel the GL! + if (tsd) + guild_trade_bound_cancel(tsd); intif_guild_leave(g->guild_id,account_id,char_id,1,mes); + } return 0; } +/** +* A confirmation from inter-serv that player is kicked successfully +* @param guild_Id +* @param account_id +* @param char_id +* @param flag +* @param name +* @param mes +*/ int guild_member_withdraw(int guild_id, uint32 account_id, uint32 char_id, int flag, const char* name, const char* mes) { int i; struct guild* g = guild_search(guild_id); @@ -815,7 +843,7 @@ int guild_member_withdraw(int guild_id, uint32 account_id, uint32 char_id, int f if(sd != NULL && sd->status.guild_id == guild_id) { // do stuff that needs the guild_id first, BEFORE we wipe it if (sd->state.storage_flag == 2) //Close the guild storage. - storage_guild_storageclose(sd); + gstorage_storageclose(sd); guild_send_dot_remove(sd); channel_pcquit(sd,3); //leave guild and ally chan sd->status.guild_id = 0; @@ -833,35 +861,44 @@ int guild_member_withdraw(int guild_id, uint32 account_id, uint32 char_id, int f } #ifdef BOUND_ITEMS -void guild_retrieveitembound(uint32 char_id,int aid,int guild_id) { - TBL_PC *sd = map_id2sd(aid); - if(sd){ //Character is online +/** +* Retrieve guild bound items from kicked member +* @param char_id +* @param account_id +* @param guild_id +*/ +void guild_retrieveitembound(uint32 char_id, uint32 account_id, int guild_id) { + TBL_PC *sd = map_charid2sd(char_id); + if (sd) { //Character is online int idxlist[MAX_INVENTORY]; int j; j = pc_bound_chk(sd,BOUND_GUILD,idxlist); - if(j) { - struct guild_storage* stor = guild2storage(sd->status.guild_id); + if (j) { + struct guild_storage* stor = gstorage_guild2storage(sd->status.guild_id); int i; - for(i=0;istatus.inventory[idxlist[i]],sd->status.inventory[idxlist[i]].amount); + // Close the storage first if someone open it + if (stor && stor->opened) { + struct map_session_data *tsd = map_charid2sd(stor->opened); + if (tsd) + gstorage_storageclose(tsd); + } + for (i = 0; i < j; i++) { //Loop the matching items, gstorage_additem takes care of opening storage + if (stor) + gstorage_additem(sd,stor,&sd->status.inventory[idxlist[i]],sd->status.inventory[idxlist[i]].amount); pc_delitem(sd,idxlist[i],sd->status.inventory[idxlist[i]].amount,0,4,LOG_TYPE_GSTORAGE); } - storage_guild_storageclose(sd); //Close and save the storage + gstorage_storageclose(sd); //Close and save the storage } } else { //Character is offline, ask char server to do the job - struct guild_storage* stor = guild2storage2(guild_id); + struct guild_storage* stor = gstorage_get_storage(guild_id); struct guild *g = guild_search(guild_id); nullpo_retv(g); - if(stor && stor->storage_status == 1) { //Someone is in guild storage, close them - int i; - for(i=0; imax_member; i++){ - TBL_PC *pl_sd = g->member[i].sd; - if(pl_sd && pl_sd->state.storage_flag == 2) - storage_guild_storageclose(pl_sd); - } + if(stor && stor->opened) { //Someone is in guild storage, close them + struct map_session_data *tsd = map_charid2sd(stor->opened); + if (tsd) + gstorage_storageclose(tsd); } - intif_itembound_req(char_id,aid,guild_id); + intif_itembound_guild_retrieve(char_id,account_id,guild_id); } } #endif @@ -1643,14 +1680,14 @@ int guild_broken(int guild_id,int flag) { struct guild *g = guild_search(guild_id); int i; - if(flag!=0 || g==NULL) + if (flag != 0 || g == NULL) return 0; - for(i=0;imax_member;i++){ // Destroy all relationships + for (i = 0; i < g->max_member; i++){ // Destroy all relationships struct map_session_data *sd = g->member[i].sd; if(sd != NULL){ if(sd->state.storage_flag == 2) - storage_guild_storage_quit(sd,1); + gstorage_storage_quit(sd,1); sd->status.guild_id=0; sd->guild = NULL; sd->state.gmaster_flag = 0; @@ -1665,7 +1702,7 @@ int guild_broken(int guild_id,int flag) { guild_db->foreach(guild_db,guild_broken_sub,guild_id); castle_db->foreach(castle_db,castle_guild_broken_sub,guild_id); - guild_storage_delete(guild_id); + gstorage_delete(guild_id); if( channel_config.ally_enable ) { channel_delete(g->channel); } @@ -1673,7 +1710,10 @@ int guild_broken(int guild_id,int flag) { return 0; } -//Changes the Guild Master to the specified player. [Skotlex] +/** Changes the Guild Master to the specified player. [Skotlex] +* @param guild_id +* @param sd New guild master +*/ int guild_gm_change(int guild_id, struct map_session_data *sd) { struct guild *g; nullpo_ret(sd); @@ -1681,7 +1721,7 @@ int guild_gm_change(int guild_id, struct map_session_data *sd) { if (sd->status.guild_id != guild_id) return 0; - g=guild_search(guild_id); + g = guild_search(guild_id); nullpo_ret(g); @@ -1693,7 +1733,11 @@ int guild_gm_change(int guild_id, struct map_session_data *sd) { return 1; } -//Notification from Char server that a guild's master has changed. [Skotlex] +/** Notification from Char server that a guild's master has changed. [Skotlex] +* @param guild_id +* @param account_id +* @param char_id +*/ int guild_gm_changed(int guild_id, uint32 account_id, uint32 char_id) { struct guild *g; struct guild_member gm; @@ -1743,9 +1787,10 @@ int guild_gm_changed(int guild_id, uint32 account_id, uint32 char_id) { return 1; } -/*==================================================== - * Guild disbanded - *---------------------------------------------------*/ +/** Disband a guild +* @param sd Player who breaks the guild +* @param name Guild name +*/ int guild_break(struct map_session_data *sd,char *name) { struct guild *g; struct unit_data *ud; @@ -1757,25 +1802,25 @@ int guild_break(struct map_session_data *sd,char *name) { nullpo_ret(sd); - if( (g=sd->guild)==NULL ) + if ((g=sd->guild)==NULL) return 0; - if(strcmp(g->name,name)!=0) + if (strcmp(g->name,name) != 0) return 0; - if(!sd->state.gmaster_flag) + if (!sd->state.gmaster_flag) return 0; - for(i=0;imax_member;i++){ + for (i = 0; i < g->max_member; i++) { if( g->member[i].account_id>0 && ( g->member[i].account_id!=sd->status.account_id || g->member[i].char_id!=sd->status.char_id )) break; } - if(imax_member){ + if (i < g->max_member) { clif_guild_broken(sd,2); return 0; } /* Regardless of char server allowing it, we clear the guild master's auras */ - if((ud = unit_bl2ud(&sd->bl))) { + if ((ud = unit_bl2ud(&sd->bl))) { int count = 0; struct skill_unit_group *group[4]; @@ -1792,15 +1837,15 @@ int guild_break(struct map_session_data *sd,char *name) { break; } } - for(i = 0; i < count; i++) + for (i = 0; i < count; i++) skill_delunitgroup(group[i]); } #ifdef BOUND_ITEMS //Guild bound item check - Removes the bound flag j = pc_bound_chk(sd,BOUND_GUILD,idxlist); - for(i=0;istatus.inventory[idxlist[i]].bound = BOUND_NONE; + for(i = 0; i < j; i++) + pc_delitem(sd,idxlist[i],sd->status.inventory[idxlist[i]].amount,0,1,LOG_TYPE_BOUND_REMOVAL); #endif intif_guild_break(g->guild_id); @@ -1911,6 +1956,9 @@ void guild_castle_reconnect_sub(void *key, void *data, va_list ap) { * Saves pending guild castle data changes when char-server is * disconnected. * On reconnect pushes all changes to char-server for saving. + * @param castle_id + * @param index + * @param value */ void guild_castle_reconnect(int castle_id, int index, int value) { static struct linkdb_node *gc_save_pending = NULL; @@ -1926,7 +1974,10 @@ void guild_castle_reconnect(int castle_id, int index, int value) { } } -// Load castle data then invoke OnAgitInit* on last +/** Load castle data then invoke OnAgitInit* on last +* @param len +* @param gc Guild Castle data +*/ int guild_castledataloadack(int len, struct guild_castle *gc) { int i; int n = (len-4) / sizeof(struct guild_castle); diff --git a/src/map/guild.h b/src/map/guild.h index 3641634df0..36d8b93084 100644 --- a/src/map/guild.h +++ b/src/map/guild.h @@ -107,7 +107,7 @@ void guild_flags_clear(void); void guild_guildaura_refresh(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv); #ifdef BOUND_ITEMS -void guild_retrieveitembound(uint32 char_id,int aid,int guild_id); +void guild_retrieveitembound(uint32 char_id,uint32 account_id,int guild_id); #endif void do_final_guild(void); diff --git a/src/map/intif.c b/src/map/intif.c index de0ba6ea3b..add5162ed7 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -30,7 +30,7 @@ static const int packet_len_table[]={ 39,-1,15,15, 14,19, 7,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3820 10,-1,15, 0, 79,19, 7,-1, 0,-1,-1,-1, 14,67,186,-1, //0x3830 -1, 0, 0,14, 0, 0, 0, 0, -1,74,-1,11, 11,-1, 0, 0, //0x3840 - -1,-1, 7, 7, 7,11, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3850 Auctions [Zephyrus] itembound[Akinari] + -1,-1, 7, 7, 7,11, 8,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3850 Auctions [Zephyrus] itembound[Akinari] -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3860 Quests [Kevin] [Inkfish] -1, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 3, 3, 0, //0x3870 Mercenaries [Zephyrus] / Elemental [pakpil] 12,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3880 @@ -1333,22 +1333,22 @@ int intif_parse_LoadGuildStorage(int fd) guild_id = RFIFOL(fd,8); flag = RFIFOL(fd,12); - if(guild_id <= 0) + if (guild_id <= 0) return 0; - sd=map_id2sd( RFIFOL(fd,4) ); - if( flag ){ //If flag != 0, we attach a player and open the storage - if(sd==NULL){ - ShowError("intif_parse_LoadGuildStorage: user not found %d\n",RFIFOL(fd,4)); + sd = map_id2sd( RFIFOL(fd,4) ); + if (flag){ //If flag != 0, we attach a player and open the storage + if(sd == NULL){ + ShowError("intif_parse_LoadGuildStorage: user not found (AID: %d)\n",RFIFOL(fd,4)); return 0; } } - gstor=guild2storage(guild_id); - if(!gstor) { + gstor = gstorage_guild2storage(guild_id); + if (!gstor) { ShowWarning("intif_parse_LoadGuildStorage: error guild_id %d not exist\n",guild_id); return 0; } - if (gstor->storage_status == 1) { // Already open.. lets ignore this update + if (gstor->opened) { // Already open.. lets ignore this update ShowWarning("intif_parse_LoadGuildStorage: storage received for a client already open (User %d:%d)\n", flag?sd->status.account_id:1, flag?sd->status.char_id:1); return 0; } @@ -1358,13 +1358,13 @@ int intif_parse_LoadGuildStorage(int fd) } if( RFIFOW(fd,2)-13 != sizeof(struct guild_storage) ){ ShowError("intif_parse_LoadGuildStorage: data size error %d %d\n",RFIFOW(fd,2)-13 , sizeof(struct guild_storage)); - gstor->storage_status = 0; + gstor->opened = 0; return 0; } memcpy(gstor,RFIFOP(fd,13),sizeof(struct guild_storage)); if( flag ) - storage_guild_storageopen(sd); + gstorage_storageopen(sd); return 1; } @@ -1376,7 +1376,7 @@ int intif_parse_LoadGuildStorage(int fd) */ int intif_parse_SaveGuildStorage(int fd) { - storage_guild_storagesaved(/*RFIFOL(fd,2), */RFIFOL(fd,6)); + gstorage_storagesaved(/*RFIFOL(fd,2), */RFIFOL(fd,6)); return 1; } @@ -2875,13 +2875,14 @@ void intif_parse_MessageToFD(int fd) { #ifdef BOUND_ITEMS /** - * Request char-serv to delete some bound item, for non connected cid + * ZI 0x3056 .L .L .W + * Request inter-serv to delete some bound item, for non connected cid * @param char_id : Char to delete item ID * @param aid : Account to delete item ID * @param guild_id : Guild of char */ -void intif_itembound_req(uint32 char_id, uint32 aid,int guild_id) { - struct guild_storage *gstor = guild2storage2(guild_id); +void intif_itembound_guild_retrieve(uint32 char_id,uint32 account_id,int guild_id) { + struct guild_storage *gstor = gstorage_get_storage(guild_id); if( CheckForCharServer() ) return; @@ -2889,10 +2890,12 @@ void intif_itembound_req(uint32 char_id, uint32 aid,int guild_id) { WFIFOHEAD(inter_fd,12); WFIFOW(inter_fd,0) = 0x3056; WFIFOL(inter_fd,2) = char_id; - WFIFOL(inter_fd,6) = aid; + WFIFOL(inter_fd,6) = account_id; WFIFOW(inter_fd,10) = guild_id; WFIFOSET(inter_fd,12); - if(gstor) gstor->lock = 1; //Lock for retrieval process + if (gstor) + gstor->locked = true; //Lock for retrieval process + ShowInfo("Request guild bound item(s) retrieval for CID = "CL_WHITE"%d"CL_RESET", AID = %d, Guild ID = "CL_WHITE"%d"CL_RESET".\n", char_id, account_id, guild_id); } /** @@ -2903,8 +2906,38 @@ void intif_itembound_req(uint32 char_id, uint32 aid,int guild_id) { */ void intif_parse_itembound_ack(int fd) { int guild_id = RFIFOW(fd,6); - struct guild_storage *gstor = guild2storage2(guild_id); - if(gstor) gstor->lock = 0; //Unlock now that operation is completed + struct guild_storage *gstor = gstorage_get_storage(guild_id); + if (gstor) + gstor->locked = false; //Unlock now that operation is completed +} + +/** +* IZ 0x3857 .W .W .W { .?B }.*MAX_INVENTORY +* Received the retrieved guild bound items from inter-server, store them to guild storage. +* @param fd +* @author [Cydh] +*/ +void intif_parse_itembound_store2gstorage(int fd) { + unsigned short i, failed = 0; + short count = RFIFOW(fd, 4), guild_id = RFIFOW(fd, 6); + struct guild_storage *gstor = gstorage_guild2storage(guild_id); + + if (!gstor) { + ShowError("intif_parse_itembound_store2gstorage: Guild '%d' not found.\n", guild_id); + return; + } + + //@TODO: Gives some actions for item(s) that cannot be stored because storage is full or reach the limit of stack amount + for (i = 0; i < count; i++) { + struct item *item = (struct item*)RFIFOP(fd, 8 + i*sizeof(struct item)); + if (!item) + continue; + if (!gstorage_additem2(gstor, item, item->amount)) + failed++; + } + ShowInfo("Retrieved '"CL_WHITE"%d"CL_RESET"' (failed: %d) guild bound item(s) for Guild ID = "CL_WHITE"%d"CL_RESET".\n", count, failed, guild_id); + gstor->locked = false; + gstor->opened = 0; } #endif @@ -2998,6 +3031,7 @@ int intif_parse(int fd) //Bound items #ifdef BOUND_ITEMS case 0x3856: intif_parse_itembound_ack(fd); break; + case 0x3857: intif_parse_itembound_store2gstorage(fd); break; #endif //Quest system diff --git a/src/map/intif.h b/src/map/intif.h index b2534291ec..fd40d1f9f1 100644 --- a/src/map/intif.h +++ b/src/map/intif.h @@ -60,7 +60,7 @@ int intif_guild_emblem(int guild_id, int len, const char *data); int intif_guild_castle_dataload(int num, int *castle_ids); int intif_guild_castle_datasave(int castle_id, int index, int value); #ifdef BOUND_ITEMS -void intif_itembound_req(uint32 char_id, uint32 aid, int guild_id); +void intif_itembound_guild_retrieve(uint32 char_id, uint32 account_id, int guild_id); #endif int intif_create_pet(uint32 account_id, uint32 char_id, short pet_type, short pet_lv, short pet_egg_id, diff --git a/src/map/itemdb.c b/src/map/itemdb.c index 1c10975fb6..fc0f0e23b7 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -419,10 +419,9 @@ struct item_data* itemdb_search(unsigned short nameid) { * @param id Item data * @return True if item is equip, false otherwise */ -bool itemdb_isequip2(struct item_data *id) -{ +bool itemdb_isequip2(struct item_data *id) { nullpo_ret(id); - switch(id->type) { + switch (id->type) { case IT_WEAPON: case IT_ARMOR: case IT_AMMO: diff --git a/src/map/log.c b/src/map/log.c index e5ff9d0147..f167f803a3 100644 --- a/src/map/log.c +++ b/src/map/log.c @@ -74,6 +74,7 @@ static char log_picktype2char(e_log_pick_type type) case LOG_TYPE_BANK: return 'K'; // Ban(K) Transactions case LOG_TYPE_OTHER: return 'X'; // Other case LOG_TYPE_CASH: return '$'; // Cash + case LOG_TYPE_BOUND_REMOVAL: return 'B'; // Removed bound items when guild/party is broken } // should not get here, fallback diff --git a/src/map/log.h b/src/map/log.h index 71b27f6b03..ebfc706274 100644 --- a/src/map/log.h +++ b/src/map/log.h @@ -43,6 +43,7 @@ typedef enum e_log_pick_type LOG_TYPE_OTHER = 0x10000, LOG_TYPE_CASH = 0x20000, LOG_TYPE_BANK = 0x40000, + LOG_TYPE_BOUND_REMOVAL = 0x80000, // combinations LOG_TYPE_LOOT = LOG_TYPE_PICKDROP_MONSTER|LOG_TYPE_CONSUME, // all diff --git a/src/map/map.c b/src/map/map.c index ae6f1223bc..0b6132d7a3 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -1524,16 +1524,16 @@ bool map_closest_freecell(int16 m, int16 *x, int16 *y, int type, int flag) int map_addflooritem(struct item *item,int amount,int16 m,int16 x,int16 y,int first_charid,int second_charid,int third_charid,int flags) { int r; - struct flooritem_data *fitem=NULL; + struct flooritem_data *fitem = NULL; nullpo_ret(item); - if(!(flags&4) && battle_config.item_onfloor && (itemdb_traderight(item->nameid)&1) ) + if (!(flags&4) && battle_config.item_onfloor && (itemdb_traderight(item->nameid)&1)) return 0; //can't be dropped - if(!map_searchrandfreecell(m,&x,&y,flags&2?1:0)) + if (!map_searchrandfreecell(m,&x,&y,flags&2?1:0)) return 0; - r=rnd(); + r = rnd(); CREATE(fitem, struct flooritem_data, 1); fitem->bl.type=BL_ITEM; @@ -1542,7 +1542,7 @@ int map_addflooritem(struct item *item,int amount,int16 m,int16 x,int16 y,int fi fitem->bl.x=x; fitem->bl.y=y; fitem->bl.id = map_get_new_object_id(); - if(fitem->bl.id==0){ + if (fitem->bl.id==0) { aFree(fitem); return 0; } @@ -1555,13 +1555,13 @@ int map_addflooritem(struct item *item,int amount,int16 m,int16 x,int16 y,int fi fitem->third_get_tick = fitem->second_get_tick + (flags&1 ? battle_config.mvp_item_third_get_time : battle_config.item_third_get_time); memcpy(&fitem->item,item,sizeof(*item)); - fitem->item.amount=amount; - fitem->subx=(r&3)*3+3; - fitem->suby=((r>>2)&3)*3+3; - fitem->cleartimer=add_timer(gettick()+battle_config.flooritem_lifetime,map_clearflooritem_timer,fitem->bl.id,0); + fitem->item.amount = amount; + fitem->subx = (r&3)*3+3; + fitem->suby = ((r>>2)&3)*3+3; + fitem->cleartimer = add_timer(gettick()+battle_config.flooritem_lifetime,map_clearflooritem_timer,fitem->bl.id,0); map_addiddb(&fitem->bl); - if(map_addblock(&fitem->bl)) + if (map_addblock(&fitem->bl)) return 0; clif_dropflooritem(fitem); diff --git a/src/map/party.c b/src/map/party.c index 9ff31fec0c..d761f74dd2 100644 --- a/src/map/party.c +++ b/src/map/party.c @@ -17,6 +17,7 @@ #include "instance.h" #include "intif.h" #include "mapreg.h" +#include "trade.h" #include @@ -188,6 +189,20 @@ int party_request_info(int party_id, uint32 char_id) return intif_request_partyinfo(party_id, char_id); } +/** + * Close trade window if party member is kicked when trade a party bound item + * @param sd + **/ +static void party_trade_bound_cancel(struct map_session_data *sd) { +#ifdef BOUND_ITEMS + nullpo_retv(sd); + if (sd->state.isBoundTrading&(1<party.party_id,account_id,p->party.member[i].char_id); return 1; @@ -541,6 +557,8 @@ int party_removemember2(struct map_session_data *sd,uint32 char_id,int party_id) if( sd ) { if( !sd->status.party_id ) return -3; + + party_trade_bound_cancel(sd); intif_party_leave(sd->status.party_id,sd->status.account_id,sd->status.char_id); return 1; } else { @@ -573,6 +591,7 @@ int party_leave(struct map_session_data *sd) if( i == MAX_PARTY ) return 0; + party_trade_bound_cancel(sd); intif_party_leave(p->party.party_id,sd->status.account_id,sd->status.char_id); return 1; } @@ -600,10 +619,11 @@ int party_member_withdraw(int party_id, uint32 account_id, uint32 char_id) int idxlist[MAX_INVENTORY]; //or malloc to reduce consumtion int j,i; + party_trade_bound_cancel(sd); j = pc_bound_chk(sd,BOUND_PARTY,idxlist); for(i = 0; i < j; i++) - pc_delitem(sd,idxlist[i],sd->status.inventory[idxlist[i]].amount,0,1,LOG_TYPE_OTHER); + pc_delitem(sd,idxlist[i],sd->status.inventory[idxlist[i]].amount,0,1,LOG_TYPE_BOUND_REMOVAL); #endif sd->status.party_id = 0; @@ -1057,7 +1077,7 @@ int party_exp_share(struct party_data* p, struct block_list* src, unsigned int b } //Does party loot. first_charid holds the charid of the player who has time priority to take the item. -int party_share_loot(struct party_data* p, struct map_session_data* sd, struct item* item_data, int first_charid) +int party_share_loot(struct party_data* p, struct map_session_data* sd, struct item* item, int first_charid) { TBL_PC* target = NULL; int i; @@ -1077,7 +1097,7 @@ int party_share_loot(struct party_data* p, struct map_session_data* sd, struct i if( (psd = p->data[i].sd) == NULL || sd->bl.m != psd->bl.m || pc_isdead(psd) || (battle_config.idle_no_share && pc_isidle(psd)) ) continue; - if (pc_additem(psd,item_data,item_data->amount,LOG_TYPE_PICKDROP_PLAYER)) + if (pc_additem(psd,item,item->amount,LOG_TYPE_PICKDROP_PLAYER)) continue; //Chosen char can't pick up loot. //Successful pick. @@ -1100,7 +1120,7 @@ int party_share_loot(struct party_data* p, struct map_session_data* sd, struct i while (count > 0) { //Pick a random member. i = rnd()%count; - if (pc_additem(psd[i],item_data,item_data->amount,LOG_TYPE_PICKDROP_PLAYER)) { // Discard this receiver. + if (pc_additem(psd[i],item,item->amount,LOG_TYPE_PICKDROP_PLAYER)) { // Discard this receiver. psd[i] = psd[count-1]; count--; } else { // Successful pick. @@ -1114,12 +1134,12 @@ int party_share_loot(struct party_data* p, struct map_session_data* sd, struct i if (!target) { target = sd; //Give it to the char that picked it up - if ((i = pc_additem(sd,item_data,item_data->amount,LOG_TYPE_PICKDROP_PLAYER))) + if ((i = pc_additem(sd,item,item->amount,LOG_TYPE_PICKDROP_PLAYER))) return i; } - if( p && battle_config.party_show_share_picker && battle_config.show_picker_item_type&(1<nameid)) ) - clif_party_show_picker(target, item_data); + if( p && battle_config.party_show_share_picker && battle_config.show_picker_item_type&(1<nameid)) ) + clif_party_show_picker(target, item); return 0; } diff --git a/src/map/party.h b/src/map/party.h index 66a048eb47..339a48befc 100644 --- a/src/map/party.h +++ b/src/map/party.h @@ -84,7 +84,7 @@ int party_recv_message(int party_id,uint32 account_id,const char *mes,int len); int party_skill_check(struct map_session_data *sd, int party_id, uint16 skill_id, uint16 skill_lv); int party_send_xy_clear(struct party_data *p); int party_exp_share(struct party_data *p,struct block_list *src,unsigned int base_exp,unsigned int job_exp,int zeny); -int party_share_loot(struct party_data* p, struct map_session_data* sd, struct item* item_data, int first_charid); +int party_share_loot(struct party_data* p, struct map_session_data* sd, struct item* item, int first_charid); int party_send_dot_remove(struct map_session_data *sd); int party_sub_count(struct block_list *bl, va_list ap); int party_sub_count_class(struct block_list *bl, va_list ap); diff --git a/src/map/pc.c b/src/map/pc.c index 9e81d88abf..bc30b9a20b 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -4430,47 +4430,47 @@ bool pc_dropitem(struct map_session_data *sd,int n,int amount) *------------------------------------------*/ bool pc_takeitem(struct map_session_data *sd,struct flooritem_data *fitem) { - int flag=0; + int flag = 0; unsigned int tick = gettick(); struct party_data *p = NULL; nullpo_ret(sd); nullpo_ret(fitem); - if(!check_distance_bl(&fitem->bl, &sd->bl, 2) && sd->ud.skill_id!=BS_GREED) + if (!check_distance_bl(&fitem->bl, &sd->bl, 2) && sd->ud.skill_id!=BS_GREED) return false; // Distance is too far - if( sd->sc.cant.pickup ) + if (sd->sc.cant.pickup) return false; if (sd->status.party_id) p = party_search(sd->status.party_id); - if(fitem->first_get_charid > 0 && fitem->first_get_charid != sd->status.char_id) { + if (fitem->first_get_charid > 0 && fitem->first_get_charid != sd->status.char_id) { struct map_session_data *first_sd = map_charid2sd(fitem->first_get_charid); - if(DIFF_TICK(tick,fitem->first_get_tick) < 0) { + if (DIFF_TICK(tick,fitem->first_get_tick) < 0) { if (!(p && p->party.item&1 && first_sd && first_sd->status.party_id == sd->status.party_id - )) + )) return false; } - else if(fitem->second_get_charid > 0 && fitem->second_get_charid != sd->status.char_id) { + else if (fitem->second_get_charid > 0 && fitem->second_get_charid != sd->status.char_id) { struct map_session_data *second_sd = map_charid2sd(fitem->second_get_charid); - if(DIFF_TICK(tick, fitem->second_get_tick) < 0) { - if(!(p && p->party.item&1 && + if (DIFF_TICK(tick, fitem->second_get_tick) < 0) { + if (!(p && p->party.item&1 && ((first_sd && first_sd->status.party_id == sd->status.party_id) || (second_sd && second_sd->status.party_id == sd->status.party_id)) - )) + )) return false; } - else if(fitem->third_get_charid > 0 && fitem->third_get_charid != sd->status.char_id){ + else if (fitem->third_get_charid > 0 && fitem->third_get_charid != sd->status.char_id){ struct map_session_data *third_sd = map_charid2sd(fitem->third_get_charid); - if(DIFF_TICK(tick,fitem->third_get_tick) < 0) { + if (DIFF_TICK(tick,fitem->third_get_tick) < 0) { if(!(p && p->party.item&1 && ((first_sd && first_sd->status.party_id == sd->status.party_id) || (second_sd && second_sd->status.party_id == sd->status.party_id) || (third_sd && third_sd->status.party_id == sd->status.party_id)) - )) + )) return false; } } diff --git a/src/map/pc.h b/src/map/pc.h index 43dbf09cfd..eb2619c365 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -229,6 +229,7 @@ struct map_session_data { unsigned int banking : 1; //1 when we using the banking system 0 when closed unsigned int hpmeter_visible : 1; unsigned disable_atcommand_on_npc : 1; //Prevent to use atcommand while talking with NPC [Kichi] + uint8 isBoundTrading; // Player is currently add bound item to trade list [Cydh] } state; struct { unsigned char no_weapon_damage, no_magic_damage, no_misc_damage; diff --git a/src/map/script.c b/src/map/script.c index 2b633015b5..5ad7fc4673 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -9232,7 +9232,7 @@ BUILDIN_FUNC(guildopenstorage) if( sd == NULL ) return 0; - ret = storage_guild_storageopen(sd); + ret = gstorage_storageopen(sd); script_pushint(st,ret); return SCRIPT_CMD_SUCCESS; } diff --git a/src/map/storage.c b/src/map/storage.c index 105992ad15..9d99e4c6e4 100644 --- a/src/map/storage.c +++ b/src/map/storage.c @@ -5,6 +5,7 @@ #include "../common/db.h" #include "../common/nullpo.h" #include "../common/malloc.h" +#include "../common/showmsg.h" #include "map.h" // struct map_session_data #include "storage.h" @@ -85,8 +86,8 @@ static int storage_reconnect_sub(DBKey key, DBData *data, va_list ap) { struct guild_storage *stor = db_data2ptr(data); - if (stor->dirty && stor->storage_status == 0) //Save closed storages. - storage_guild_storagesave(0, stor->guild_id,0); + if (stor->dirty && stor->opened == 0) //Save closed storages. + gstorage_storagesave(0, stor->guild_id,0); return 0; } @@ -421,12 +422,12 @@ static DBData create_guildstorage(DBKey key, va_list args) * @param guild_id : id of the guild * @return guild_storage */ -struct guild_storage *guild2storage(int guild_id) +struct guild_storage *gstorage_guild2storage(int guild_id) { struct guild_storage *gs = NULL; - if(guild_search(guild_id) != NULL) - gs = idb_ensure(guild_storage_db,guild_id,create_guildstorage); + if (guild_search(guild_id) != NULL) + gs = (struct guild_storage *)idb_ensure(guild_storage_db,guild_id,create_guildstorage); return gs; } @@ -437,7 +438,7 @@ struct guild_storage *guild2storage(int guild_id) * @param guild_id : guild_id to search the storage * @return guild_storage or NULL */ -struct guild_storage *guild2storage2(int guild_id) +struct guild_storage *gstorage_get_storage(int guild_id) { return (struct guild_storage*)idb_get(guild_storage_db,guild_id); } @@ -447,11 +448,9 @@ struct guild_storage *guild2storage2(int guild_id) * @param guild_id : guild to remove the storage from * @return 0 */ -int guild_storage_delete(int guild_id) +void gstorage_delete(int guild_id) { idb_remove(guild_storage_db,guild_id); - - return 0; } /** @@ -459,7 +458,7 @@ int guild_storage_delete(int guild_id) * @param sd : player * @return 0 : success, 1 : fail, 2 : no guild found */ -int storage_guild_storageopen(struct map_session_data* sd) +char gstorage_storageopen(struct map_session_data* sd) { struct guild_storage *gstor; @@ -476,18 +475,18 @@ int storage_guild_storageopen(struct map_session_data* sd) return 1; } - if((gstor = guild2storage2(sd->status.guild_id)) == NULL) { + if((gstor = gstorage_get_storage(sd->status.guild_id)) == NULL) { intif_request_guild_storage(sd->status.account_id,sd->status.guild_id); return 0; } - if(gstor->storage_status) + if(gstor->opened) return 1; - if( gstor->lock ) + if( gstor->locked ) return 1; - gstor->storage_status = 1; + gstor->opened = sd->status.char_id; sd->state.storage_flag = 2; storage_sortitem(gstor->items, ARRAYLENGTH(gstor->items)); clif_storagelist(sd, gstor->items, ARRAYLENGTH(gstor->items)); @@ -500,66 +499,109 @@ int storage_guild_storageopen(struct map_session_data* sd) * 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 item : item to add * @param amount : number of item to add - * @return 0 : success, 1 : fail + * @return True : success, False : fail */ -char guild_storage_additem(struct map_session_data* sd, struct guild_storage* stor, struct item* item_data, int amount) +bool gstorage_additem(struct map_session_data* sd, struct guild_storage* stor, struct item* item, int amount) { - struct item_data *data; + struct item_data *id; int i; - nullpo_retr(1, sd); - nullpo_retr(1, stor); - nullpo_retr(1, item_data); + nullpo_ret(sd); + nullpo_ret(stor); + nullpo_ret(item); - if(item_data->nameid == 0 || amount <= 0) - return 1; + if(item->nameid == 0 || amount <= 0) + return false; - data = itemdb_search(item_data->nameid); + id = itemdb_search(item->nameid); - if( data->stack.guildstorage && amount > data->stack.amount ) // item stack limitation - return 1; + if( id->stack.guildstorage && amount > id->stack.amount ) // item stack limitation + return false; - if( !itemdb_canguildstore(item_data, pc_get_group_level(sd)) || item_data->expire_time ) { // Check if item is storable. [Skotlex] + if( !itemdb_canguildstore(item, pc_get_group_level(sd)) || item->expire_time ) { // Check if item is storable. [Skotlex] clif_displaymessage (sd->fd, msg_txt(sd,264)); - return 1; + return false; } - if( (item_data->bound == BOUND_ACCOUNT || item_data->bound > BOUND_GUILD) && !pc_can_give_bounded_items(sd) ) { + if( (item->bound == BOUND_ACCOUNT || item->bound > BOUND_GUILD) && !pc_can_give_bounded_items(sd) ) { clif_displaymessage(sd->fd, msg_txt(sd,294)); - return 1; + return false; } - if(itemdb_isstackable2(data)) { //Stackable + if(itemdb_isstackable2(id)) { //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; + if(compare_item(&stor->items[i], item)) { + if( amount > MAX_AMOUNT - stor->items[i].amount || ( id->stack.guildstorage && amount > id->stack.amount - stor->items[i].amount ) ) + return false; stor->items[i].amount+=amount; clif_storageitemadded(sd,&stor->items[i],i,amount); - stor->dirty = 1; - - return 0; + stor->dirty = true; + return true; } } } //Add item for(i = 0; i < MAX_GUILD_STORAGE && stor->items[i].nameid; i++); - if(i >= MAX_GUILD_STORAGE) - return 1; + return false; - memcpy(&stor->items[i],item_data,sizeof(stor->items[0])); - stor->items[i].amount=amount; + memcpy(&stor->items[i],item,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; + stor->dirty = true; + return true; +} - 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_ret(stor); + nullpo_ret(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; } /** @@ -568,15 +610,15 @@ char guild_storage_additem(struct map_session_data* sd, struct guild_storage* st * @param stor : guild_storage * @param n : index of item in guild storage * @param amount : number of item to delete - * @return 0 : success, 1 : fail + * @return True : success, False : fail */ -int guild_storage_delitem(struct map_session_data* sd, struct guild_storage* stor, int n, int amount) +bool gstorage_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; + return false; stor->items[n].amount -= amount; @@ -587,25 +629,23 @@ int guild_storage_delitem(struct map_session_data* sd, struct guild_storage* sto } clif_storageitemremoved(sd,n,amount); - stor->dirty = 1; - - return 0; + stor->dirty = true; + return true; } /** * Attempt to add an item in guild storage from inventory, then refresh it * @param sd : player * @param amount : number of item to delete - * @return 1:success, 0:fail */ -void storage_guild_storageadd(struct map_session_data* sd, int index, int amount) +void gstorage_storageadd(struct map_session_data* sd, int index, int amount) { struct guild_storage *stor; nullpo_retv(sd); - nullpo_retv(stor = guild2storage2(sd->status.guild_id)); + nullpo_retv(stor = gstorage_get_storage(sd->status.guild_id)); - if( !stor->storage_status || stor->storage_amount > MAX_GUILD_STORAGE ) + if( !stor->opened || stor->opened != sd->status.char_id || stor->storage_amount > MAX_GUILD_STORAGE ) return; if( index < 0 || index >= MAX_INVENTORY ) @@ -617,12 +657,12 @@ void storage_guild_storageadd(struct map_session_data* sd, int index, int amount if( amount < 1 || amount > sd->status.inventory[index].amount ) return; - if( stor->lock ) { - storage_guild_storageclose(sd); + if( stor->locked ) { + gstorage_storageclose(sd); return; } - if(guild_storage_additem(sd,stor,&sd->status.inventory[index],amount) == 0) + if(gstorage_additem(sd,stor,&sd->status.inventory[index],amount)) pc_delitem(sd,index,amount,0,4,LOG_TYPE_GSTORAGE); else { clif_storageitemremoved(sd,index,0); @@ -637,16 +677,16 @@ void storage_guild_storageadd(struct map_session_data* sd, int index, int amount * @param amount : number of item to get * @return 1:success, 0:fail */ -void storage_guild_storageget(struct map_session_data* sd, int index, int amount) +void gstorage_storageget(struct map_session_data* sd, int index, int amount) { struct guild_storage *stor; unsigned char flag = 0; nullpo_retv(sd); - nullpo_retv(stor = guild2storage2(sd->status.guild_id)); + nullpo_retv(stor = gstorage_get_storage(sd->status.guild_id)); - if(!stor->storage_status) - return; + if(!stor->opened || stor->opened != sd->status.char_id) + return; if(index < 0 || index >= MAX_GUILD_STORAGE) return; @@ -655,15 +695,15 @@ void storage_guild_storageget(struct map_session_data* sd, int index, int amount return; if(amount < 1 || amount > stor->items[index].amount) - return; + return; - if( stor->lock ) { - storage_guild_storageclose(sd); + if( stor->locked ) { + gstorage_storageclose(sd); return; } if((flag = pc_additem(sd,&stor->items[index],amount,LOG_TYPE_GSTORAGE)) == 0) - guild_storage_delitem(sd,stor,index,amount); + gstorage_delitem(sd,stor,index,amount); else { // inform fail clif_storageitemremoved(sd,index,0); clif_additem(sd,0,0,flag); @@ -675,16 +715,15 @@ void storage_guild_storageget(struct map_session_data* sd, int index, int amount * @param sd : player * @param index : index of item in cart * @param amount : number of item to transfer - * @return 1:fail, 0:success */ -void storage_guild_storageaddfromcart(struct map_session_data* sd, int index, int amount) +void gstorage_storageaddfromcart(struct map_session_data* sd, int index, int amount) { struct guild_storage *stor; nullpo_retv(sd); - nullpo_retv(stor = guild2storage2(sd->status.guild_id)); + nullpo_retv(stor = gstorage_get_storage(sd->status.guild_id)); - if( !stor->storage_status || stor->storage_amount > MAX_GUILD_STORAGE ) + if( !stor->opened || stor->opened != sd->status.char_id || stor->storage_amount > MAX_GUILD_STORAGE ) return; if( index < 0 || index >= MAX_CART ) @@ -696,7 +735,7 @@ void storage_guild_storageaddfromcart(struct map_session_data* sd, int index, in if( amount < 1 || amount > sd->status.cart[index].amount ) return; - if(guild_storage_additem(sd,stor,&sd->status.cart[index],amount) == 0) + if(gstorage_additem(sd,stor,&sd->status.cart[index],amount)) pc_cart_delitem(sd,index,amount,0,LOG_TYPE_GSTORAGE); else { clif_storageitemremoved(sd,index,0); @@ -711,19 +750,19 @@ void storage_guild_storageaddfromcart(struct map_session_data* sd, int index, in * @param amount : number of item to transfer * @return 1:fail, 0:success */ -void storage_guild_storagegettocart(struct map_session_data* sd, int index, int amount) +void gstorage_storagegettocart(struct map_session_data* sd, int index, int amount) { short flag; struct guild_storage *stor; nullpo_retv(sd); - nullpo_retv(stor = guild2storage2(sd->status.guild_id)); + nullpo_retv(stor = gstorage_get_storage(sd->status.guild_id)); - if(!stor->storage_status) - return; + if(!stor->opened || stor->opened != sd->status.char_id) + return; if(index < 0 || index >= MAX_GUILD_STORAGE) - return; + return; if(stor->items[index].nameid == 0) return; @@ -732,7 +771,7 @@ void storage_guild_storagegettocart(struct map_session_data* sd, int index, int return; if((flag = pc_cart_additem(sd,&stor->items[index],amount,LOG_TYPE_GSTORAGE)) == 0) - guild_storage_delitem(sd,stor,index,amount); + gstorage_delitem(sd,stor,index,amount); else { clif_storageitemremoved(sd,index,0); clif_cart_additem_ack(sd,(flag == 1) ? ADDITEM_TO_CART_FAIL_WEIGHT:ADDITEM_TO_CART_FAIL_COUNT); @@ -744,104 +783,93 @@ void storage_guild_storagegettocart(struct map_session_data* sd, int index, int * @param account_id : account requesting the save * @param guild_id : guild to take the guild_storage * @param flag : 1=char quitting, close the storage - * @return 0 : fail (no storage), 1 : success (requested) + * @return False : fail (no storage), True : success (requested) */ -int storage_guild_storagesave(uint32 account_id, int guild_id, int flag) +bool gstorage_storagesave(uint32 account_id, int guild_id, int flag) { - struct guild_storage *stor = guild2storage2(guild_id); + struct guild_storage *stor = gstorage_get_storage(guild_id); - if(stor) { + if (stor) { if (flag) //Char quitting, close it. - stor->storage_status = 0; + stor->opened = 0; - if (stor->dirty) + if (stor->dirty) intif_send_guild_storage(account_id,stor); - return 1; + return true; } - return 0; + return false; } /** * ACK save of guild storage * @param guild_id : guild to use the storage - * @return 0 : fail (no storage), 1 : success */ -int storage_guild_storagesaved(int guild_id) +void gstorage_storagesaved(int guild_id) { struct guild_storage *stor; - if((stor = guild2storage2(guild_id)) != NULL) { - if (stor->dirty && stor->storage_status == 0) // Storage has been correctly saved. - stor->dirty = 0; - - return 1; + if ((stor = gstorage_get_storage(guild_id)) != NULL) { + if (stor->dirty && stor->opened == 0) // Storage has been correctly saved. + stor->dirty = false; } - - return 0; } /** * Close storage for player then save it * @param sd : player - * @return 0 */ -int storage_guild_storageclose(struct map_session_data* sd) +void gstorage_storageclose(struct map_session_data* sd) { struct guild_storage *stor; - nullpo_ret(sd); - nullpo_ret(stor = guild2storage2(sd->status.guild_id)); + nullpo_retv(sd); + nullpo_retv(stor = gstorage_get_storage(sd->status.guild_id)); clif_storageclose(sd); - if (stor->storage_status) { + if (stor->opened) { if (save_settings&CHARSAVE_STORAGE) chrif_save(sd, 0); //This one also saves the storage. [Skotlex] else - storage_guild_storagesave(sd->status.account_id, sd->status.guild_id,0); + gstorage_storagesave(sd->status.account_id, sd->status.guild_id,0); - stor->storage_status=0; + stor->opened = 0; } sd->state.storage_flag = 0; - - return 0; } /** * Close storage for player then save it * @param sd * @param flag - * @return */ -int storage_guild_storage_quit(struct map_session_data* sd, int flag) +void gstorage_storage_quit(struct map_session_data* sd, int flag) { struct guild_storage *stor; - nullpo_ret(sd); - nullpo_ret(stor=guild2storage2(sd->status.guild_id)); + nullpo_retv(sd); + nullpo_retv(stor = gstorage_get_storage(sd->status.guild_id)); - if(flag) { // Only during a guild break flag is 1 (don't save storage) + if (flag) { // Only during a guild break flag is 1 (don't save storage) sd->state.storage_flag = 0; - stor->storage_status = 0; + stor->opened = 0; clif_storageclose(sd); if (save_settings&CHARSAVE_STORAGE) chrif_save(sd,0); - return 0; + return; } - if(stor->storage_status) { + if (stor->opened) { if (save_settings&CHARSAVE_STORAGE) chrif_save(sd,0); else - storage_guild_storagesave(sd->status.account_id,sd->status.guild_id,1); + gstorage_storagesave(sd->status.account_id,sd->status.guild_id,1); } sd->state.storage_flag = 0; - stor->storage_status = 0; - - return 0; + stor->opened = 0; } diff --git a/src/map/storage.h b/src/map/storage.h index b3dc1c01e2..112618d528 100644 --- a/src/map/storage.h +++ b/src/map/storage.h @@ -24,20 +24,21 @@ void do_final_storage(void); void do_reconnect_storage(void); void storage_storage_quit(struct map_session_data *sd, int flag); -struct guild_storage* guild2storage(int guild_id); -struct guild_storage *guild2storage2(int guild_id); -int guild_storage_delete(int guild_id); -int storage_guild_storageopen(struct map_session_data *sd); -char guild_storage_additem(struct map_session_data *sd,struct guild_storage *stor,struct item *item_data,int amount); -int guild_storage_delitem(struct map_session_data *sd,struct guild_storage *stor,int n,int amount); -void storage_guild_storageadd(struct map_session_data *sd,int index,int amount); -void storage_guild_storageget(struct map_session_data *sd,int index,int amount); -void storage_guild_storageaddfromcart(struct map_session_data *sd,int index,int amount); -void storage_guild_storagegettocart(struct map_session_data *sd,int index,int amount); -int storage_guild_storageclose(struct map_session_data *sd); -int storage_guild_storage_quit(struct map_session_data *sd,int flag); -int storage_guild_storagesave(uint32 account_id, int guild_id, int flag); -int storage_guild_storagesaved(int guild_id); //Ack from char server that guild store was saved. +struct guild_storage* gstorage_guild2storage(int guild_id); +struct guild_storage *gstorage_get_storage(int guild_id); +void gstorage_delete(int guild_id); +char gstorage_storageopen(struct map_session_data *sd); +bool gstorage_additem(struct map_session_data *sd,struct guild_storage *stor,struct item *item,int amount); +bool gstorage_additem2(struct guild_storage *stor, struct item *item, int amount); +bool gstorage_delitem(struct map_session_data *sd,struct guild_storage *stor,int n,int amount); +void gstorage_storageadd(struct map_session_data *sd,int index,int amount); +void gstorage_storageget(struct map_session_data *sd,int index,int amount); +void gstorage_storageaddfromcart(struct map_session_data *sd,int index,int amount); +void gstorage_storagegettocart(struct map_session_data *sd,int index,int amount); +void gstorage_storageclose(struct map_session_data *sd); +void gstorage_storage_quit(struct map_session_data *sd,int flag); +bool gstorage_storagesave(uint32 account_id, int guild_id, int flag); +void gstorage_storagesaved(int guild_id); int compare_item(struct item *a, struct item *b); diff --git a/src/map/trade.c b/src/map/trade.c index 619da43caf..a286e3e06d 100644 --- a/src/map/trade.c +++ b/src/map/trade.c @@ -391,6 +391,9 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount) return; } + if (item->bound) + sd->state.isBoundTrading |= (1<bound); + // Locate a trade position ARR_FIND( 0, 10, trade_i, sd->deal.item[trade_i].index == index || sd->deal.item[trade_i].amount == 0 ); if( trade_i == 10 ) { // No space left @@ -483,7 +486,10 @@ void trade_tradecancel(struct map_session_data *sd) struct map_session_data *target_sd; int trade_i; + nullpo_retv(sd); + target_sd = map_id2sd(sd->trade_partner); + sd->state.isBoundTrading = 0; if(!sd->state.trading) { // Not trade accepted if( target_sd ) { @@ -546,6 +552,8 @@ void trade_tradecommit(struct map_session_data *sd) struct map_session_data *tsd; int trade_i; + nullpo_retv(sd); + if (!sd->state.trading || !sd->state.deal_locked) //Locked should be 1 (pressed ok) before you can press trade. return; @@ -624,10 +632,12 @@ void trade_tradecommit(struct map_session_data *sd) sd->state.deal_locked = 0; sd->trade_partner = 0; sd->state.trading = 0; + sd->state.isBoundTrading = 0; tsd->state.deal_locked = 0; tsd->trade_partner = 0; tsd->state.trading = 0; + tsd->state.isBoundTrading = 0; clif_tradecompleted(sd, 0); clif_tradecompleted(tsd, 0); diff --git a/src/map/unit.c b/src/map/unit.c index 66e695b609..aa84e4db3a 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -2855,7 +2855,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, if (sd->state.storage_flag == 1) storage_storage_quit(sd,0); else if (sd->state.storage_flag == 2) - storage_guild_storage_quit(sd,0); + gstorage_storage_quit(sd,0); sd->state.storage_flag = 0; //Force close it when being warped. }