From d88a6aca45a068a62a9cf768ee80b4437c67a3c5 Mon Sep 17 00:00:00 2001 From: aleos89 Date: Tue, 29 Mar 2016 13:30:27 -0400 Subject: [PATCH 01/22] Optimized Inventory, Cart Inventory, and Storage usage * These storage types now mimic Guild Storage and can be loaded/saved whenever needed. * Relieves mmo_charstatus from having to send storage types and lets the char-server handle it. * All storage types now have an increased max amount. * Fixes #441 - Players will no longer be required to log out to resync cart item data before opening a Vending Store. * Refactored player weight and cart weight calculations into their own functions. * Added script commands guildstoragecountitem[2] and guildstoragedelitem[2]. * Refactored several function return types as well as documentation. Thanks to @lighta and @cydh for their help with it! --- conf/msg_conf/map_msg.conf | 2 +- conf/msg_conf/map_msg_idn.conf | 2 +- doc/packet_interserv.txt | 55 ++++ doc/script_commands.txt | 46 ++- src/char/char.c | 126 ++------ src/char/char.h | 11 +- src/char/char_clif.c | 6 +- src/char/int_auction.c | 25 +- src/char/int_storage.c | 565 +++++++++++++++++++++++++-------- src/char/int_storage.h | 15 +- src/char/inter.c | 10 +- src/common/mmo.h | 33 +- src/login/account.c | 26 +- src/map/atcommand.c | 100 +++--- src/map/battle.c | 12 +- src/map/buyingstore.c | 8 +- src/map/chrif.c | 18 +- src/map/clif.c | 248 ++++++++------- src/map/clif.h | 3 +- src/map/guild.c | 42 +-- src/map/intif.c | 286 ++++++++++++++--- src/map/intif.h | 8 +- src/map/itemdb.c | 2 +- src/map/mail.c | 18 +- src/map/map.c | 5 +- src/map/npc.c | 26 +- src/map/party.c | 2 +- src/map/pc.c | 370 +++++++++++---------- src/map/pc.h | 16 +- src/map/pet.c | 13 +- src/map/script.c | 303 +++++++++++------- src/map/skill.c | 62 ++-- src/map/status.c | 167 ++++++---- src/map/status.h | 2 + src/map/storage.c | 309 +++++++++--------- src/map/storage.h | 33 +- src/map/trade.c | 18 +- src/map/unit.c | 2 +- src/map/vending.c | 48 ++- 39 files changed, 1820 insertions(+), 1223 deletions(-) diff --git a/conf/msg_conf/map_msg.conf b/conf/msg_conf/map_msg.conf index 78500e307e..742f964977 100644 --- a/conf/msg_conf/map_msg.conf +++ b/conf/msg_conf/map_msg.conf @@ -770,7 +770,7 @@ 732: Item cannot be opened when your inventory is full. -733: Item '%s' has not yet saved to your cart. Please re-log in order to correctly save your Vending information. +//733 free // @cloneequip/@clonestat 734: Cannot clone your own %s. diff --git a/conf/msg_conf/map_msg_idn.conf b/conf/msg_conf/map_msg_idn.conf index c36f114c3b..d4afc3fc23 100644 --- a/conf/msg_conf/map_msg_idn.conf +++ b/conf/msg_conf/map_msg_idn.conf @@ -769,7 +769,7 @@ 732: Item tidak dapat dibuka ketika inventory penuh. -733: Item '%s' belum tersimpan di gerobak. Harap masuk kembali untuk dapat menyimpan informasi vending dengan benar. +//733 free // @cloneequip/@clonestat 734: Tidak dapat mengkloning %s diri sendiri. diff --git a/doc/packet_interserv.txt b/doc/packet_interserv.txt index ed698e5f82..64d3fbd23b 100644 --- a/doc/packet_interserv.txt +++ b/doc/packet_interserv.txt @@ -1327,6 +1327,33 @@ Currently the max packet size is 0xFFFF (see 'WFIFOSET()' in 'src/common/socket. desc: - Delete pet data +0x308a + Type: ZI + Structure: .W .B .L .L + index: 0,2,3,7 + len: 11 + parameter: + - cmd : packet identification (0x308a) + - type : 0 - TABLE_INVENTORY, 1 - TABLE_CART, 2 - TABLE_STORAGE + - account_id + - char_id + desc: + - Request inventory/cart/storage data for a player/guild if type = 3 + +0x308b + Type: ZI + Structure: .W .B .L .L .?B + index: 0,2,4,5,9,13 + len: 11 + parameter: + - cmd : packet identification (0x308a) + - type : 0 - TABLE_INVENTORY, 1 - TABLE_CART, 2 - TABLE_STORAGE + - account_id + - char_id + - entries : Inventory/cart/storage entries that will be saved + desc: + - Request to save inventory/cart/storage entries + 0x3090: Type: ZI Structure: .W .W .L .?B @@ -2137,6 +2164,34 @@ Currently the max packet size is 0xFFFF (see 'WFIFOSET()' in 'src/common/socket. desc: - Send pet deletion status +0x388a + Type: IZ + Structure: .W .W .B .L .B .?B + index: 0,2,4,5,9 + len: 9+variable + parameter: + - cmd : packet identification (0x388a) + - size + - type : Storage type, 0 - TABLE_INVENTORY, 1 - TABLE_CART, 2 - TABLE_STORAGE + - account_id + - result : True if data loaded, false if failed + - entries : Inventory/cart/storage entries + desc: + - Process inventory/cart/storage entries for player from inter-server + +0x388b + Type: IZ + Structure: .W .L .B .B + index: 0,2,6,7 + len: 11 + parameter: + - cmd : packet identification (0x388b) + - account_id + - result : 1 - success, 0 - failed + - type : Storage type, 0 - TABLE_INVENTORY, 1 - TABLE_CART, 2 - TABLE_STORAGE + desc: + - Info about inventory/cart/storage data is saved + 0x3890 Type: IZ Structure: .W .W .L .B .?B diff --git a/doc/script_commands.txt b/doc/script_commands.txt index addfc4d95c..aab0f1efaf 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -3,7 +3,7 @@ //===== By: ================================================== //= rAthena Dev Team //===== Last Updated: ======================================== -//= 20150610 +//= 20160325 //===== Description: ========================================= //= A reference manual for the rAthena scripting language. //= Commands are sorted depending on their functionality. @@ -4572,9 +4572,14 @@ database. If the name is not found, nothing will be deleted. *cartdelitem "",{,}; *storagedelitem ,{,}; *storagedelitem "",{,}; +*guildstoragedelitem ,{,}; +*guildstoragedelitem "",{,}; This command behaves identically to 'delitem', but deletes items from the player's -cart or storage. If no cart is mounted, 'cartdelitem' will fail. +cart or storage. + +If no cart is mounted, 'cartdelitem' will return -1. +If player is not in a guild or storage is open, 'guildstoragedelitem' will return -1. --------------------------------------- @@ -4590,9 +4595,14 @@ See 'getitem2' for an explanation of the expanded parameters. *cartdelitem2 "",,,,,,,,{,}; *storagedelitem2 ,,,,,,,,{,}; *storagedelitem2 "",,,,,,,,{,}; +*guildstoragedelitem2 ,,,,,,,,{,}; +*guildstoragedelitem2 "",,,,,,,,{,}; This command behaves identically to 'delitem2', but deletes items from the player's -cart or storage. If no cart is mounted, 'cartdelitem2' will fail. +cart or storage. + +If no cart is mounted, 'cartdelitem2' will return -1. +If player is not in a guild or storage is open, 'guildstoragedelitem2' will return -1. --------------------------------------- @@ -4618,13 +4628,18 @@ adding up strings: --------------------------------------- -*cartcountitem() -*cartcountitem("") -*storagecountitem() -*storagecountitem("") +*cartcountitem({,}) +*cartcountitem(""{,}) +*storagecountitem({,}) +*storagecountitem(""{,}) +*guildstoragecountitem({,}) +*guildstoragecountitem(""{,}) This command behaves identically to 'countitem', but counts items from the player's -cart or storage. If no cart is mounted, 'cartcountitem' will return -1. +cart, storage or guild storage. + +If no cart is mounted, 'cartcountitem' will return -1. +If player is not in a guild or storage is open, 'guildstoragecountitem' will return -1. --------------------------------------- @@ -4639,13 +4654,18 @@ See 'getitem2' for an explanation of the expanded parameters. --------------------------------------- -*cartcountitem2(,,,,,,,) -*cartcountitem2("",,,,,,,) -*storagecountitem2(,,,,,,,) -*storagecountitem2("",,,,,,,) +*cartcountitem2(,,,,,,,{,}) +*cartcountitem2("",,,,,,,{,}) +*storagecountitem2(,,,,,,,{,}) +*storagecountitem2("",,,,,,,{,}) +*guildstoragecountitem2(,,,,,,,{,}) +*guildstoragecountitem2("",,,,,,,{,}) This command behaves identically to 'countitem2', but counts items from the player's -cart or storage. If no cart is mounted, 'cartcountitem2' will return -1. +cart, storage or guild storage. + +If no cart is mounted, 'cartcountitem2' will return -1. +If player is not in a guild or storage is open, 'guildstoragecountitem2' will return -1. --------------------------------------- diff --git a/src/char/char.c b/src/char/char.c index 0220063211..c50a3a1537 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -23,7 +23,6 @@ #include "int_mercenary.h" #include "int_elemental.h" #include "int_party.h" -#include "int_storage.h" #include "inter.h" #include "char_logif.h" #include "char_mapif.h" @@ -280,30 +279,6 @@ int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p){ StringBuf_Init(&buf); memset(save_status, 0, sizeof(save_status)); - //map inventory data - if( memcmp(p->inventory, cp->inventory, sizeof(p->inventory)) ) { - if (!char_inventory_to_sql(p->inventory, MAX_INVENTORY, p->char_id)) - strcat(save_status, " inventory"); - else - errors++; - } - - //map cart data - if( memcmp(p->cart, cp->cart, sizeof(p->cart)) ) { - if (!char_memitemdata_to_sql(p->cart, MAX_CART, p->char_id, TABLE_CART)) - strcat(save_status, " cart"); - else - errors++; - } - - //map storage data - if( memcmp(p->storage.items, cp->storage.items, sizeof(p->storage.items)) ) { - if (!char_memitemdata_to_sql(p->storage.items, MAX_STORAGE, p->account_id, TABLE_STORAGE)) - strcat(save_status, " storage"); - else - errors++; - } - if ( (p->base_exp != cp->base_exp) || (p->base_level != cp->base_level) || (p->job_level != cp->job_level) || (p->job_exp != cp->job_exp) || @@ -555,13 +530,12 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl int errors = 0; switch (tableswitch) { - case TABLE_INVENTORY: tablename = schema_config.inventory_db; selectoption = "char_id"; break; - case TABLE_CART: tablename = schema_config.cart_db; selectoption = "char_id"; break; - case TABLE_STORAGE: tablename = schema_config.storage_db; selectoption = "account_id"; break; - case TABLE_GUILD_STORAGE: tablename = schema_config.guild_storage_db; selectoption = "guild_id"; break; - default: - ShowError("Invalid table name!\n"); - return 1; + case TABLE_CART: tablename = schema_config.cart_db; selectoption = "char_id"; break; + case TABLE_STORAGE: tablename = schema_config.storage_db; selectoption = "account_id"; break; + case TABLE_GUILD_STORAGE: tablename = schema_config.guild_storage_db; selectoption = "guild_id"; break; + default: + ShowError("Invalid table name!\n"); + return 1; } @@ -692,6 +666,8 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl errors++; } + ShowInfo("Saved %s data for %s: %d\n", (tableswitch == TABLE_CART ? "Cart" : (tableswitch == TABLE_STORAGE ? "Storage" : "Guild Storage") ), selectoption, id); + StringBuf_Destroy(&buf); aFree(flag); @@ -699,7 +675,7 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl } /* pretty much a copy of memitemdata_to_sql except it handles inventory_db exclusively, * - this is required because inventory db is the only one with the 'favorite' column. */ -int char_inventory_to_sql(const struct item items[], int max, int id) { +int char_inventory_to_sql(const struct item items[], int max, int char_id) { StringBuf buf; SqlStmt* stmt; int i; @@ -719,11 +695,11 @@ int char_inventory_to_sql(const struct item items[], int max, int id) { StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `bound`, `unique_id`"); 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, id); + StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`='%d'", schema_config.inventory_db, char_id); 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); @@ -820,7 +796,7 @@ int char_inventory_to_sql(const struct item items[], int max, int id) { found = true; StringBuf_Printf(&buf, "('%d', '%hu', '%d', '%d', '%d', '%d', '%d', '%u', '%d', '%d', '%"PRIu64"'", - id, items[i].nameid, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time, items[i].favorite, items[i].bound, items[i].unique_id); + char_id, items[i].nameid, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time, items[i].favorite, items[i].bound, items[i].unique_id); for( j = 0; j < MAX_SLOTS; ++j ) StringBuf_Printf(&buf, ", '%hu'", items[i].card[j]); StringBuf_AppendStr(&buf, ")"); @@ -831,6 +807,8 @@ int char_inventory_to_sql(const struct item items[], int max, int id) { errors++; } + ShowInfo("Saved Inventory data for char_id: %d.\n", char_id); + StringBuf_Destroy(&buf); aFree(flag); @@ -989,15 +967,13 @@ int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf) { //===================================================================================================== int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_everything) { - int i,j; + int i; struct mmo_charstatus* cp; - StringBuf buf; SqlStmt* stmt; char last_map[MAP_NAME_LENGTH_EXT]; char save_map[MAP_NAME_LENGTH_EXT]; char point_map[MAP_NAME_LENGTH_EXT]; struct point tmp_point; - struct item tmp_item; struct s_skill tmp_skill; uint16 skill_count = 0; struct s_friend tmp_friend; @@ -1144,72 +1120,6 @@ int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_ev } StringBuf_AppendStr(&msg_buf, " memo"); - //read inventory - //`inventory` (`id`,`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`, `expire_time`, `favorite`, `unique_id`) - StringBuf_Init(&buf); - StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `bound`, `unique_id`"); - for( i = 0; i < MAX_SLOTS; ++i ) - StringBuf_Printf(&buf, ", `card%d`", i); - StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", schema_config.inventory_db, MAX_INVENTORY); - - if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) - || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) - || SQL_ERROR == SqlStmt_Execute(stmt) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &tmp_item.id, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 1, SQLDT_USHORT, &tmp_item.nameid, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 2, SQLDT_SHORT, &tmp_item.amount, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 3, SQLDT_UINT, &tmp_item.equip, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 4, SQLDT_CHAR, &tmp_item.identify, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 5, SQLDT_CHAR, &tmp_item.refine, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 6, SQLDT_CHAR, &tmp_item.attribute, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 7, SQLDT_UINT, &tmp_item.expire_time, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 8, SQLDT_CHAR, &tmp_item.favorite, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 9, SQLDT_CHAR, &tmp_item.bound, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt,10, SQLDT_UINT64, &tmp_item.unique_id, 0, NULL, NULL) ) - SqlStmt_ShowDebug(stmt); - for( i = 0; i < MAX_SLOTS; ++i ) - if( SQL_ERROR == SqlStmt_BindColumn(stmt, 11+i, SQLDT_USHORT, &tmp_item.card[i], 0, NULL, NULL) ) - SqlStmt_ShowDebug(stmt); - - for( i = 0; i < MAX_INVENTORY && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) - memcpy(&p->inventory[i], &tmp_item, sizeof(tmp_item)); - - StringBuf_AppendStr(&msg_buf, " inventory"); - - //read cart - //`cart_inventory` (`id`,`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`, expire_time`, `unique_id`) - StringBuf_Clear(&buf); - StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`"); - for( j = 0; j < MAX_SLOTS; ++j ) - StringBuf_Printf(&buf, ", `card%d`", j); - StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", schema_config.cart_db, MAX_CART); - - if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) - || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) - || SQL_ERROR == SqlStmt_Execute(stmt) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &tmp_item.id, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 1, SQLDT_USHORT, &tmp_item.nameid, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 2, SQLDT_SHORT, &tmp_item.amount, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 3, SQLDT_UINT, &tmp_item.equip, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 4, SQLDT_CHAR, &tmp_item.identify, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 5, SQLDT_CHAR, &tmp_item.refine, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 6, SQLDT_CHAR, &tmp_item.attribute, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 7, SQLDT_UINT, &tmp_item.expire_time, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 8, SQLDT_CHAR, &tmp_item.bound, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 9, SQLDT_UINT64, &tmp_item.unique_id, 0, NULL, NULL) ) - SqlStmt_ShowDebug(stmt); - for( i = 0; i < MAX_SLOTS; ++i ) - if( SQL_ERROR == SqlStmt_BindColumn(stmt, 10+i, SQLDT_USHORT, &tmp_item.card[i], 0, NULL, NULL) ) - SqlStmt_ShowDebug(stmt); - - for( i = 0; i < MAX_CART && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) - memcpy(&p->cart[i], &tmp_item, sizeof(tmp_item)); - StringBuf_AppendStr(&msg_buf, " cart"); - - //read storage - storage_fromsql(p->account_id, &p->storage); - StringBuf_AppendStr(&msg_buf, " storage"); - //read skill //`skill` (`char_id`, `id`, `lv`) if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `id`, `lv`,`flag` FROM `%s` WHERE `char_id`=? LIMIT %d", schema_config.skill_db, MAX_SKILL) @@ -1274,9 +1184,9 @@ int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_ev StringBuf_AppendStr(&msg_buf, " mercenary"); - if (charserv_config.save_log) ShowInfo("Loaded char (%d - %s): %s\n", char_id, p->name, StringBuf_Value(&msg_buf)); //ok. all data load successfuly! + if (charserv_config.save_log) + ShowInfo("Loaded char (%d - %s): %s\n", char_id, p->name, StringBuf_Value(&msg_buf)); //ok. all data load successfully! SqlStmt_Free(stmt); - StringBuf_Destroy(&buf); cp = (struct mmo_charstatus *)idb_ensure(char_db_, char_id, char_create_charstatus); memcpy(cp, p, sizeof(struct mmo_charstatus)); diff --git a/src/char/char.h b/src/char/char.h index 1be94121db..13e197d825 100644 --- a/src/char/char.h +++ b/src/char/char.h @@ -25,13 +25,6 @@ enum E_CHARSERVER_ST { CHARSERVER_ST_LAST }; -enum { - TABLE_INVENTORY, - TABLE_CART, - TABLE_STORAGE, - TABLE_GUILD_STORAGE, -}; - struct Schema_Config { int db_use_sqldbs; char db_path[1024]; @@ -198,8 +191,7 @@ DBMap* char_get_onlinedb(); // uint32 account_id -> struct online_char_data* struct char_session_data { bool auth; // whether the session is authed or not - uint32 account_id, login_id1, login_id2; - int sex; + uint32 account_id, login_id1, login_id2, sex; int found_char[MAX_CHARS]; // ids of chars on this account char email[40]; // e-mail (default: a@a.com) by [Yor] time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited) @@ -260,6 +252,7 @@ int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf); int char_delete_char_sql(uint32 char_id); int char_rename_char_sql(struct char_session_data *sd, uint32 char_id); int char_divorce_char_sql(int partner_id1, int partner_id2); +int char_inventory_to_sql(const struct item items[], int max, int char_id); int char_memitemdata_to_sql(const struct item items[], int max, int id, int tableswitch); void disconnect_player(uint32 account_id); diff --git a/src/char/char_clif.c b/src/char/char_clif.c index 1c4e96ef10..b98f6b8cad 100644 --- a/src/char/char_clif.c +++ b/src/char/char_clif.c @@ -528,8 +528,7 @@ int chclif_parse_char_delete2_accept(int fd, struct char_session_data* sd) { FIFOSD_CHECK(12) { char birthdate[8+1]; - uint32 char_id; - int i, k; + uint32 char_id, i, k; unsigned int base_level; char* data; time_t delete_date; @@ -604,8 +603,7 @@ int chclif_parse_char_delete2_accept(int fd, struct char_session_data* sd) { // CH: <082b>.W .L int chclif_parse_char_delete2_cancel(int fd, struct char_session_data* sd) { - uint32 char_id; - int i; + uint32 char_id, i; FIFOSD_CHECK(6) diff --git a/src/char/int_auction.c b/src/char/int_auction.c index 4c11fae321..0eb32e10eb 100644 --- a/src/char/int_auction.c +++ b/src/char/int_auction.c @@ -3,7 +3,6 @@ #include "../common/mmo.h" #include "../common/malloc.h" -#include "../common/db.h" #include "../common/showmsg.h" #include "../common/socket.h" #include "../common/strlib.h" @@ -15,8 +14,6 @@ #include "int_mail.h" #include "int_auction.h" -#include -#include #include static DBMap* auction_db_ = NULL; // int auction_id -> struct auction_data* @@ -24,7 +21,7 @@ static DBMap* auction_db_ = NULL; // int auction_id -> struct auction_data* void auction_delete(struct auction_data *auction); static int auction_end_timer(int tid, unsigned int tick, int id, intptr_t data); -static int auction_count(int char_id, bool buy) +static int auction_count(uint32 char_id, bool buy) { int i = 0; struct auction_data *auction; @@ -125,7 +122,7 @@ unsigned int auction_create(struct auction_data *auction) return auction->auction_id; } -static void mapif_Auction_message(int char_id, unsigned char result) +static void mapif_Auction_message(uint32 char_id, unsigned char result) { unsigned char buf[74]; @@ -237,7 +234,7 @@ void inter_auctions_fromsql(void) Sql_FreeResult(sql_handle); } -static void mapif_Auction_sendlist(int fd, int char_id, short count, short pages, unsigned char *buf) +static void mapif_Auction_sendlist(int fd, uint32 char_id, short count, short pages, unsigned char *buf) { int len = (sizeof(struct auction_data) * count) + 12; @@ -254,7 +251,7 @@ static void mapif_Auction_sendlist(int fd, int char_id, short count, short pages static void mapif_parse_Auction_requestlist(int fd) { char searchtext[NAME_LENGTH]; - int char_id = RFIFOL(fd,4), len = sizeof(struct auction_data); + uint32 char_id = RFIFOL(fd,4), len = sizeof(struct auction_data); int price = RFIFOL(fd,10); short type = RFIFOW(fd,8), page = max(1,RFIFOW(fd,14)); unsigned char buf[5 * sizeof(struct auction_data)]; @@ -318,7 +315,7 @@ static void mapif_parse_Auction_register(int fd) mapif_Auction_register(fd, &auction); } -static void mapif_Auction_cancel(int fd, int char_id, unsigned char result) +static void mapif_Auction_cancel(int fd, uint32 char_id, unsigned char result) { WFIFOHEAD(fd,7); WFIFOW(fd,0) = 0x3852; @@ -329,7 +326,7 @@ static void mapif_Auction_cancel(int fd, int char_id, unsigned char result) static void mapif_parse_Auction_cancel(int fd) { - int char_id = RFIFOL(fd,2), auction_id = RFIFOL(fd,6); + uint32 char_id = RFIFOL(fd,2), auction_id = RFIFOL(fd,6); struct auction_data *auction; if( (auction = (struct auction_data *)idb_get(auction_db_, auction_id)) == NULL ) @@ -356,7 +353,7 @@ static void mapif_parse_Auction_cancel(int fd) mapif_Auction_cancel(fd, char_id, 0); // The auction has been canceled } -static void mapif_Auction_close(int fd, int char_id, unsigned char result) +static void mapif_Auction_close(int fd, uint32 char_id, unsigned char result) { WFIFOHEAD(fd,7); WFIFOW(fd,0) = 0x3853; @@ -367,7 +364,7 @@ static void mapif_Auction_close(int fd, int char_id, unsigned char result) static void mapif_parse_Auction_close(int fd) { - int char_id = RFIFOL(fd,2), auction_id = RFIFOL(fd,6); + uint32 char_id = RFIFOL(fd,2), auction_id = RFIFOL(fd,6); struct auction_data *auction; if( (auction = (struct auction_data *)idb_get(auction_db_, auction_id)) == NULL ) @@ -398,7 +395,7 @@ static void mapif_parse_Auction_close(int fd) mapif_Auction_close(fd, char_id, 0); // You have ended the auction } -static void mapif_Auction_bid(int fd, int char_id, int bid, unsigned char result) +static void mapif_Auction_bid(int fd, uint32 char_id, int bid, unsigned char result) { WFIFOHEAD(fd,11); WFIFOW(fd,0) = 0x3855; @@ -410,8 +407,8 @@ static void mapif_Auction_bid(int fd, int char_id, int bid, unsigned char result static void mapif_parse_Auction_bid(int fd) { - int char_id = RFIFOL(fd,4), bid = RFIFOL(fd,12); - unsigned int auction_id = RFIFOL(fd,8); + uint32 char_id = RFIFOL(fd,4), auction_id = RFIFOL(fd,8); + int bid = RFIFOL(fd,12); struct auction_data *auction; if( (auction = (struct auction_data *)idb_get(auction_db_, auction_id)) == NULL || auction->price >= bid || auction->seller_id == char_id ) diff --git a/src/char/int_storage.c b/src/char/int_storage.c index 5be031ebe6..f9a43b1486 100644 --- a/src/char/int_storage.c +++ b/src/char/int_storage.c @@ -14,77 +14,262 @@ #define STORAGE_MEMINC 16 -/// Save storage data to sql -int storage_tosql(int account_id, struct storage_data* p) +/** + * Save inventory entries to SQL + * @param char_id: Character ID to save + * @param p: Inventory entries + * @return 0 if success, or error count + */ +static int inventory_tosql(uint32 char_id, struct s_storage* p) { - char_memitemdata_to_sql(p->items, MAX_STORAGE, account_id, TABLE_STORAGE); - return 0; + return char_inventory_to_sql(p->u.items_inventory, MAX_INVENTORY, char_id); } -/// Load storage data to mem -int storage_fromsql(uint32 account_id, struct storage_data* p) +/** + * Save storage entries to SQL + * @param char_id: Character ID to save + * @param p: Storage entries + * @return 0 if success, or error count + */ +static int storage_tosql(uint32 account_id, struct s_storage* p) { + return char_memitemdata_to_sql(p->u.items_storage, MAX_STORAGE, account_id, TABLE_STORAGE); +} + +/** + * Save cart entries to SQL + * @param char_id: Character ID to save + * @param p: Cart entries + * @return 0 if success, or error count + */ +static int cart_tosql(uint32 char_id, struct s_storage* p) +{ + return char_memitemdata_to_sql(p->u.items_cart, MAX_CART, char_id, TABLE_CART); +} + +/** + * Fetch inventory entries from table + * @param char_id: Character ID to fetch + * @param p: Inventory list to save the entries + * @return True if success, False if failed + */ +static bool inventory_fromsql(uint32 char_id, struct s_storage* p) +{ + int i; StringBuf buf; - int i, j; + SqlStmt* stmt; + struct item tmp_item; - memset(p, 0, sizeof(struct storage_data)); //clean up memory - p->storage_amount = 0; + memset(p, 0, sizeof(struct s_storage)); //clean up memory + p->amount = 0; - // storage {`account_id`/`id`/`nameid`/`amount`/`equip`/`identify`/`refine`/`attribute`/`card0`/`card1`/`card2`/`card3`} - StringBuf_Init(&buf); - StringBuf_AppendStr(&buf, "SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`expire_time`,`bound`,`unique_id`"); - for( j = 0; j < MAX_SLOTS; ++j ) - StringBuf_Printf(&buf, ",`card%d`", j); - StringBuf_Printf(&buf, " FROM `%s` WHERE `account_id`='%d' ORDER BY `nameid`", schema_config.storage_db, account_id); - - if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) ) - Sql_ShowDebug(sql_handle); - - StringBuf_Destroy(&buf); - - for( i = 0; i < MAX_STORAGE && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) - { - struct item* item; - char* data; - item = &p->items[i]; - Sql_GetData(sql_handle, 0, &data, NULL); item->id = atoi(data); - Sql_GetData(sql_handle, 1, &data, NULL); item->nameid = atoi(data); - Sql_GetData(sql_handle, 2, &data, NULL); item->amount = atoi(data); - Sql_GetData(sql_handle, 3, &data, NULL); item->equip = atoi(data); - Sql_GetData(sql_handle, 4, &data, NULL); item->identify = atoi(data); - Sql_GetData(sql_handle, 5, &data, NULL); item->refine = atoi(data); - Sql_GetData(sql_handle, 6, &data, NULL); item->attribute = atoi(data); - Sql_GetData(sql_handle, 7, &data, NULL); item->expire_time = (unsigned int)atoi(data); - Sql_GetData(sql_handle, 8, &data, NULL); item->bound = atoi(data); - Sql_GetData(sql_handle, 9, &data, NULL); item->unique_id = strtoull(data, NULL, 10); - for( j = 0; j < MAX_SLOTS; ++j ){ - Sql_GetData(sql_handle, 10+j, &data, NULL); item->card[j] = atoi(data); - } + stmt = SqlStmt_Malloc(sql_handle); + if (stmt == NULL) { + SqlStmt_ShowDebug(stmt); + return false; } - p->storage_amount = i; - Sql_FreeResult(sql_handle); - ShowInfo("storage load complete from DB - id: %d (total: %d)\n", account_id, p->storage_amount); - return 1; + StringBuf_Init(&buf); + StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `bound`, `unique_id`"); + for( i = 0; i < MAX_SLOTS; ++i ) + StringBuf_Printf(&buf, ", `card%d`", i); + StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", schema_config.inventory_db, MAX_INVENTORY); + + if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) + || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) + || SQL_ERROR == SqlStmt_Execute(stmt) ) + { + SqlStmt_ShowDebug(stmt); + SqlStmt_Free(stmt); + StringBuf_Destroy(&buf); + return false; + } + + SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &tmp_item.id, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 1, SQLDT_USHORT, &tmp_item.nameid, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 2, SQLDT_SHORT, &tmp_item.amount, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 3, SQLDT_UINT, &tmp_item.equip, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 4, SQLDT_CHAR, &tmp_item.identify, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 5, SQLDT_CHAR, &tmp_item.refine, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 6, SQLDT_CHAR, &tmp_item.attribute, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 7, SQLDT_UINT, &tmp_item.expire_time, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 8, SQLDT_CHAR, &tmp_item.favorite, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 9, SQLDT_CHAR, &tmp_item.bound, 0, NULL, NULL); + SqlStmt_BindColumn(stmt,10, SQLDT_ULONGLONG, &tmp_item.unique_id, 0, NULL, NULL); + for( i = 0; i < MAX_SLOTS; ++i ) + SqlStmt_BindColumn(stmt, 11+i, SQLDT_USHORT, &tmp_item.card[i], 0, NULL, NULL); + + for( i = 0; i < MAX_INVENTORY && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) + memcpy(&p->u.items_inventory[i], &tmp_item, sizeof(tmp_item)); + + p->amount = i; + ShowInfo("Loaded inventory data from DB - CID: %d (total: %d)\n", char_id, p->amount); + + SqlStmt_FreeResult(stmt); + SqlStmt_Free(stmt); + StringBuf_Destroy(&buf); + return true; } -/// Save guild_storage data to sql -int guild_storage_tosql(int guild_id, struct guild_storage* p) -{ - char_memitemdata_to_sql(p->items, MAX_GUILD_STORAGE, guild_id, TABLE_GUILD_STORAGE); - ShowInfo ("guild storage save to DB - guild: %d\n", guild_id); - return 0; -} - -/// Load guild_storage data to mem -int guild_storage_fromsql(int guild_id, struct guild_storage* p) +/** + * Fetch cart entries from table + * @param char_id: Character ID to fetch + * @param p: Cart list to save the entries + * @return True if success, False if failed + */ +static bool cart_fromsql(uint32 char_id, struct s_storage* p) { + int i,j; StringBuf buf; - int i, j; + SqlStmt* stmt; + struct item tmp_item; - memset(p, 0, sizeof(struct guild_storage)); //clean up memory - p->storage_amount = 0; - p->guild_id = guild_id; + memset(p, 0, sizeof(struct s_storage)); //clean up memory + p->amount = 0; + + stmt = SqlStmt_Malloc(sql_handle); + if (stmt == NULL) { + SqlStmt_ShowDebug(stmt); + return false; + } + + StringBuf_Init(&buf); + StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`"); + for( j = 0; j < MAX_SLOTS; ++j ) + StringBuf_Printf(&buf, ", `card%d`", j); + StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", schema_config.cart_db, MAX_CART); + + if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) + || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) + || SQL_ERROR == SqlStmt_Execute(stmt) ) + { + SqlStmt_ShowDebug(stmt); + SqlStmt_Free(stmt); + StringBuf_Destroy(&buf); + return false; + } + + SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &tmp_item.id, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 1, SQLDT_USHORT, &tmp_item.nameid, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 2, SQLDT_SHORT, &tmp_item.amount, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 3, SQLDT_UINT, &tmp_item.equip, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 4, SQLDT_CHAR, &tmp_item.identify, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 5, SQLDT_CHAR, &tmp_item.refine, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 6, SQLDT_CHAR, &tmp_item.attribute, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 7, SQLDT_UINT, &tmp_item.expire_time, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 8, SQLDT_CHAR, &tmp_item.bound, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 9, SQLDT_ULONGLONG, &tmp_item.unique_id, 0, NULL, NULL); + for( i = 0; i < MAX_SLOTS; ++i ) + SqlStmt_BindColumn(stmt, 10+i, SQLDT_USHORT, &tmp_item.card[i], 0, NULL, NULL); + + for( i = 0; i < MAX_CART && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) + memcpy(&p->u.items_cart[i], &tmp_item, sizeof(tmp_item)); + + p->amount = i; + ShowInfo("Loaded Cart data from DB - CID: %d (total: %d)\n", char_id, p->amount); + + SqlStmt_FreeResult(stmt); + SqlStmt_Free(stmt); + StringBuf_Destroy(&buf); + return true; +} + +/** + * Fetch storage entries from table + * @param char_id: Character ID to fetch + * @param p: Storage list to save the entries + * @return True if success, False if failed + */ +static bool storage_fromsql(uint32 account_id, struct s_storage* p) +{ + int i, j; + StringBuf buf; + SqlStmt* stmt; + struct item tmp_item; + + memset(p, 0, sizeof(struct s_storage)); //clean up memory + p->amount = 0; + + stmt = SqlStmt_Malloc(sql_handle); + if (stmt == NULL) { + SqlStmt_ShowDebug(stmt); + return false; + } + + StringBuf_Init(&buf); + StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`"); + for( j = 0; j < MAX_SLOTS; ++j ) + StringBuf_Printf(&buf, ", `card%d`", j); + StringBuf_Printf(&buf, " FROM `%s` WHERE `account_id`=? ORDER BY `nameid` LIMIT %d", schema_config.storage_db, account_id, MAX_STORAGE); + + if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) + || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &account_id, 0) + || SQL_ERROR == SqlStmt_Execute(stmt) ) + { + SqlStmt_ShowDebug(stmt); + SqlStmt_Free(stmt); + StringBuf_Destroy(&buf); + return false; + } + + SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &tmp_item.id, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 1, SQLDT_USHORT, &tmp_item.nameid, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 2, SQLDT_SHORT, &tmp_item.amount, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 3, SQLDT_UINT, &tmp_item.equip, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 4, SQLDT_CHAR, &tmp_item.identify, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 5, SQLDT_CHAR, &tmp_item.refine, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 6, SQLDT_CHAR, &tmp_item.attribute, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 7, SQLDT_UINT, &tmp_item.expire_time, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 8, SQLDT_CHAR, &tmp_item.bound, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 9, SQLDT_ULONGLONG, &tmp_item.unique_id, 0, NULL, NULL); + for( i = 0; i < MAX_SLOTS; ++i ) + SqlStmt_BindColumn(stmt, 10+i, SQLDT_USHORT, &tmp_item.card[i], 0, NULL, NULL); + + for( i = 0; i < MAX_STORAGE && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) + memcpy(&p->u.items_storage[i], &tmp_item, sizeof(tmp_item)); + + p->amount = i; + ShowInfo("Loaded Storage data from DB - AID: %d (total: %d)\n", account_id, p->amount); + + SqlStmt_FreeResult(stmt); + SqlStmt_Free(stmt); + StringBuf_Destroy(&buf); + return true; +} + +/** + * Save guild_storage data to sql + * @param guild_id: Character ID to save + * @param p: Guild Storage list to save the entries + * @return 0 if success, or error count + */ +bool guild_storage_tosql(int guild_id, struct s_storage* p) +{ + //ShowInfo("Guild Storage has been saved (GID: %d)\n", guild_id); + return char_memitemdata_to_sql(p->u.items_guild, MAX_GUILD_STORAGE, guild_id, TABLE_GUILD_STORAGE); +} + +/** + * Fetch guild_storage entries from table + * @param char_id: Character ID to fetch + * @param p: Storage list to save the entries + * @return True if success, False if failed + */ +bool guild_storage_fromsql(int guild_id, struct s_storage* p) +{ + int i,j; + StringBuf buf; + SqlStmt* stmt; + struct item tmp_item; + + memset(p, 0, sizeof(struct s_storage)); //clean up memory + p->amount = 0; + + stmt = SqlStmt_Malloc(sql_handle); + if (stmt == NULL) { + SqlStmt_ShowDebug(stmt); + return false; + } // storage {`guild_id`/`id`/`nameid`/`amount`/`equip`/`identify`/`refine`/`attribute`/`card0`/`card1`/`card2`/`card3`} StringBuf_Init(&buf); @@ -93,43 +278,48 @@ int guild_storage_fromsql(int guild_id, struct guild_storage* p) StringBuf_Printf(&buf, ",`card%d`", j); StringBuf_Printf(&buf, " FROM `%s` WHERE `guild_id`='%d' ORDER BY `nameid`", schema_config.guild_storage_db, guild_id); - if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) ) - Sql_ShowDebug(sql_handle); - - StringBuf_Destroy(&buf); - - for( i = 0; i < MAX_GUILD_STORAGE && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) + || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &guild_id, 0) + || SQL_ERROR == SqlStmt_Execute(stmt) ) { - struct item* item; - char* data; - item = &p->items[i]; - Sql_GetData(sql_handle, 0, &data, NULL); item->id = atoi(data); - Sql_GetData(sql_handle, 1, &data, NULL); item->nameid = atoi(data); - Sql_GetData(sql_handle, 2, &data, NULL); item->amount = atoi(data); - Sql_GetData(sql_handle, 3, &data, NULL); item->equip = atoi(data); - Sql_GetData(sql_handle, 4, &data, NULL); item->identify = atoi(data); - Sql_GetData(sql_handle, 5, &data, NULL); item->refine = atoi(data); - Sql_GetData(sql_handle, 6, &data, NULL); item->attribute = atoi(data); - Sql_GetData(sql_handle, 7, &data, NULL); item->bound = atoi(data); - Sql_GetData(sql_handle, 8, &data, NULL); item->unique_id = strtoull(data, NULL, 10); - item->expire_time = 0; - for( j = 0; j < MAX_SLOTS; ++j ){ - Sql_GetData(sql_handle, 9+j, &data, NULL); item->card[j] = atoi(data); - } + SqlStmt_ShowDebug(stmt); + SqlStmt_Free(stmt); + StringBuf_Destroy(&buf); + return false; } - p->storage_amount = i; - Sql_FreeResult(sql_handle); - ShowInfo("guild storage load complete from DB - id: %d (total: %d)\n", guild_id, p->storage_amount); - return 0; + SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &tmp_item.id, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 1, SQLDT_USHORT, &tmp_item.nameid, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 2, SQLDT_SHORT, &tmp_item.amount, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 3, SQLDT_UINT, &tmp_item.equip, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 4, SQLDT_CHAR, &tmp_item.identify, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 5, SQLDT_CHAR, &tmp_item.refine, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 6, SQLDT_CHAR, &tmp_item.attribute, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 7, SQLDT_CHAR, &tmp_item.bound, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 8, SQLDT_ULONGLONG, &tmp_item.unique_id, 0, NULL, NULL); + tmp_item.expire_time = 0; + for( i = 0; i < MAX_SLOTS; ++i ) + SqlStmt_BindColumn(stmt, 9+i, SQLDT_USHORT, &tmp_item.card[i], 0, NULL, NULL); + + for( i = 0; i < MAX_GUILD_STORAGE && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) + memcpy(&p->u.items_guild[i], &tmp_item, sizeof(tmp_item)); + + p->amount = i; + ShowInfo("Loaded Guild Storage data from DB - GID: %d (total: %d)\n", guild_id, p->amount); + + SqlStmt_FreeResult(stmt); + SqlStmt_Free(stmt); + StringBuf_Destroy(&buf); + return true; } //--------------------------------------------------------- // storage data initialize -int inter_storage_sql_init(void) +void inter_storage_sql_init(void) { - return 1; + return; } + // storage data finalize void inter_storage_sql_final(void) { @@ -137,37 +327,36 @@ void inter_storage_sql_final(void) } // Delete char storage -int inter_storage_delete(uint32 account_id) +void inter_storage_delete(uint32 account_id) { if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id`='%d'", schema_config.storage_db, account_id) ) Sql_ShowDebug(sql_handle); - return 0; } -int inter_guild_storage_delete(int guild_id) + +void inter_guild_storage_delete(int guild_id) { if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id`='%d'", schema_config.guild_storage_db, guild_id) ) Sql_ShowDebug(sql_handle); - return 0; } //--------------------------------------------------------- // packet from map server -int mapif_load_guild_storage(int fd,uint32 account_id,int guild_id, char flag) +bool mapif_load_guild_storage(int fd,uint32 account_id,int guild_id, char flag) { if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", schema_config.guild_db, guild_id) ) Sql_ShowDebug(sql_handle); else if( Sql_NumRows(sql_handle) > 0 ) {// guild exists - WFIFOHEAD(fd, sizeof(struct guild_storage)+13); + WFIFOHEAD(fd, sizeof(struct s_storage)+13); WFIFOW(fd,0) = 0x3818; - WFIFOW(fd,2) = sizeof(struct guild_storage)+13; + WFIFOW(fd,2) = sizeof(struct s_storage)+13; WFIFOL(fd,4) = account_id; WFIFOL(fd,8) = guild_id; WFIFOB(fd,12) = flag; //1 open storage, 0 don't open - guild_storage_fromsql(guild_id, (struct guild_storage*)WFIFOP(fd,13)); + guild_storage_fromsql(guild_id, (struct s_storage*)WFIFOP(fd,13)); WFIFOSET(fd, WFIFOW(fd,2)); - return 0; + return false; } // guild does not exist Sql_FreeResult(sql_handle); @@ -177,9 +366,10 @@ int mapif_load_guild_storage(int fd,uint32 account_id,int guild_id, char flag) WFIFOL(fd,4) = account_id; WFIFOL(fd,8) = 0; WFIFOSET(fd, 12); - return 0; + return true; } -int mapif_save_guild_storage_ack(int fd,uint32 account_id,int guild_id,int fail) + +void mapif_save_guild_storage_ack(int fd,uint32 account_id,int guild_id,int fail) { WFIFOHEAD(fd,11); WFIFOW(fd,0)=0x3819; @@ -187,20 +377,18 @@ int mapif_save_guild_storage_ack(int fd,uint32 account_id,int guild_id,int fail) WFIFOL(fd,6)=guild_id; WFIFOB(fd,10)=fail; WFIFOSET(fd,11); - return 0; } //--------------------------------------------------------- // packet from map server -int mapif_parse_LoadGuildStorage(int fd) +void mapif_parse_LoadGuildStorage(int fd) { RFIFOHEAD(fd); mapif_load_guild_storage(fd,RFIFOL(fd,2),RFIFOL(fd,6),1); - return 0; } -int mapif_parse_SaveGuildStorage(int fd) +bool mapif_parse_SaveGuildStorage(int fd) { int guild_id; int len; @@ -209,9 +397,9 @@ int mapif_parse_SaveGuildStorage(int fd) guild_id = RFIFOL(fd,8); len = RFIFOW(fd,2); - if( sizeof(struct guild_storage) != len - 12 ) + if( sizeof(struct s_storage) != len - 12 ) { - ShowError("inter storage: data size error %d != %d\n", sizeof(struct guild_storage), len - 12); + ShowError("inter storage: data size error %d != %d\n", sizeof(struct s_storage), len - 12); } else { @@ -220,21 +408,21 @@ int mapif_parse_SaveGuildStorage(int fd) else if( Sql_NumRows(sql_handle) > 0 ) {// guild exists Sql_FreeResult(sql_handle); - guild_storage_tosql(guild_id, (struct guild_storage*)RFIFOP(fd,12)); + guild_storage_tosql(guild_id, (struct s_storage*)RFIFOP(fd,12)); mapif_save_guild_storage_ack(fd, RFIFOL(fd,4), guild_id, 0); - return 0; + return false; } Sql_FreeResult(sql_handle); } mapif_save_guild_storage_ack(fd, RFIFOL(fd,4), guild_id, 1); - return 0; + return true; } #ifdef BOUND_ITEMS /** -* IZ 0x3856 .L .W -* Tells map-server if the process if complete, unlock the guild storage -*/ + * 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); @@ -246,17 +434,17 @@ static void mapif_itembound_ack(int fd, int account_id, int guild_id) } /** -* 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] -*/ + * 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; @@ -274,11 +462,11 @@ static void mapif_itembound_store2gstorage(int fd, int guild_id, struct item ite } /** -* ZI 0x3056 .L .L .W -* Pulls guild bound items for offline characters -* @author [Akinari] -*/ -int mapif_parse_itembound_retrieve(int fd) + * ZI 0x3056 .L .L .W + * Pulls guild bound items for offline characters + * @author [Akinari] + */ +bool mapif_parse_itembound_retrieve(int fd) { StringBuf buf; SqlStmt* stmt; @@ -303,7 +491,7 @@ int mapif_parse_itembound_retrieve(int fd) SqlStmt_Free(stmt); StringBuf_Destroy(&buf); mapif_itembound_ack(fd,account_id,guild_id); - return 1; + return true; } SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &item.id, 0, NULL, NULL); @@ -328,7 +516,7 @@ int mapif_parse_itembound_retrieve(int fd) StringBuf_Destroy(&buf); SqlStmt_Free(stmt); mapif_itembound_ack(fd,account_id,guild_id); - return 1; + return true; } char_set_session_flag(account_id, 1); @@ -343,7 +531,7 @@ int mapif_parse_itembound_retrieve(int fd) SqlStmt_Free(stmt); StringBuf_Destroy(&buf); mapif_itembound_ack(fd,account_id,guild_id); - return 1; + return true; } // Send the deleted items to map-server to store them in guild storage [Cydh] @@ -389,7 +577,7 @@ int mapif_parse_itembound_retrieve(int fd) StringBuf_Destroy(&buf); StringBuf_Destroy(&buf2); mapif_itembound_ack(fd,account_id,guild_id); - return 1; + return true; } StringBuf_Destroy(&buf2); } @@ -398,21 +586,126 @@ int mapif_parse_itembound_retrieve(int fd) SqlStmt_Free(stmt); char_unset_session_flag(account_id, 1); - return 0; + return false; } #endif -int inter_storage_parse_frommap(int fd) +/*========================================== + * Storages (Inventory/Storage/Cart) + *------------------------------------------*/ + +/** + * Sending inventory/cart/storage data to player + * IZ 0x388a .W .B .L .B .?B + * @param fd + * @param account_id + * @param type + * @param entries Inventory/cart/storage entries + * @param result + */ +static void mapif_storage_data_loaded(int fd, uint32 account_id, char type, struct s_storage entries, bool result) { + uint16 size = sizeof(struct s_storage) + 10; + + WFIFOHEAD(fd, size); + WFIFOW(fd, 0) = 0x388a; + WFIFOW(fd, 2) = size; + WFIFOB(fd, 4) = type; + WFIFOL(fd, 5) = account_id; + WFIFOB(fd, 9) = result; + memcpy(WFIFOP(fd, 10), &entries, sizeof(struct s_storage)); + WFIFOSET(fd, size); +} + +/** + * Tells player if inventory/cart/storage is saved + * IZ 0x388b .L .B .B + * @param fd + * @param account_id + * @param type + */ +void mapif_storage_saved(int fd, uint32 account_id, bool sucess, char type) { + WFIFOHEAD(fd,8); + WFIFOW(fd, 0) = 0x388b; + WFIFOL(fd, 2) = account_id; + WFIFOB(fd, 6) = sucess; + WFIFOB(fd, 7) = type; + WFIFOSET(fd,8); +} + +/** + * Requested inventory/cart/storage data for a player + * ZI 0x308a .B .L .L + * @param fd + */ +bool mapif_parse_StorageLoad(int fd) { + uint32 aid, cid; + int type; + struct s_storage stor; + bool res = true; + + RFIFOHEAD(fd); + type = RFIFOB(fd,2); + aid = RFIFOL(fd,3); + cid = RFIFOL(fd,7); + + memset(&stor, 0, sizeof(struct s_storage)); + + //ShowInfo("Loading storage for AID=%d.\n", aid); + switch (type) { + case TABLE_INVENTORY: res = inventory_fromsql(cid, &stor); break; + case TABLE_STORAGE: res = storage_fromsql(aid, &stor); break; + case TABLE_CART: res = cart_fromsql(cid, &stor); break; + default: return false; + } + mapif_storage_data_loaded(fd, aid, type, stor, res); + return true; +} + +/** + * Asking to save player's inventory/cart/storage data + * ZI 0x308b .W .B .L .L .?B + * @param fd + */ +bool mapif_parse_StorageSave(int fd) { + int aid, cid, type; + struct s_storage stor; + + RFIFOHEAD(fd); + type = RFIFOB(fd, 4); + aid = RFIFOL(fd, 5); + cid = RFIFOL(fd, 9); + + memset(&stor, 0, sizeof(struct s_storage)); + memcpy(&stor, RFIFOP(fd, 13), sizeof(struct s_storage)); + + //ShowInfo("Saving storage data for AID=%d.\n", aid); + switch(type){ + case TABLE_INVENTORY: inventory_tosql(cid, &stor); break; + case TABLE_STORAGE: storage_tosql(aid, &stor); break; + case TABLE_CART: cart_tosql(cid, &stor); break; + default: return false; + } + mapif_storage_saved(fd, aid, true, type); + return false; +} + + +/*========================================== + * Parse packet from map-server + *------------------------------------------*/ +bool inter_storage_parse_frommap(int fd) { RFIFOHEAD(fd); switch(RFIFOW(fd,0)){ - case 0x3018: mapif_parse_LoadGuildStorage(fd); break; - case 0x3019: mapif_parse_SaveGuildStorage(fd); break; + case 0x3018: mapif_parse_LoadGuildStorage(fd); break; + case 0x3019: mapif_parse_SaveGuildStorage(fd); break; #ifdef BOUND_ITEMS - case 0x3056: mapif_parse_itembound_retrieve(fd); break; + case 0x3056: mapif_parse_itembound_retrieve(fd); break; #endif - default: - return 0; + case 0x308a: mapif_parse_StorageLoad(fd); break; + case 0x308b: mapif_parse_StorageSave(fd); break; + default: + return false; } - return 1; + return true; } diff --git a/src/char/int_storage.h b/src/char/int_storage.h index a68c04d960..9c391e4b45 100644 --- a/src/char/int_storage.h +++ b/src/char/int_storage.h @@ -4,18 +4,15 @@ #ifndef _INT_STORAGE_SQL_H_ #define _INT_STORAGE_SQL_H_ -struct storage_data; -struct guild_storage; +struct s_storage; -int inter_storage_sql_init(void); +void inter_storage_sql_init(void); void inter_storage_sql_final(void); -int inter_storage_delete(uint32 account_id); -int inter_guild_storage_delete(int guild_id); +void inter_storage_delete(uint32 account_id); +void inter_guild_storage_delete(int guild_id); -int inter_storage_parse_frommap(int fd); +bool inter_storage_parse_frommap(int fd); -int storage_fromsql(uint32 account_id, struct storage_data* p); -int storage_tosql(uint32 account_id,struct storage_data *p); -int guild_storage_tosql(int guild_id, struct guild_storage *p); +bool guild_storage_tosql(int guild_id, struct s_storage *p); #endif /* _INT_STORAGE_SQL_H_ */ diff --git a/src/char/inter.c b/src/char/inter.c index e1304c2647..3e1716a958 100644 --- a/src/char/inter.c +++ b/src/char/inter.c @@ -42,7 +42,7 @@ char default_codepage[32] = ""; //Feature by irmin. unsigned int party_share_level = 10; -// recv. packet list +/// Received packet Lengths from map-server int inter_recv_packet_length[] = { -1,-1, 7,-1, -1,13,36, (2+4+4+4+1+NAME_LENGTH), 0,-1, 0, 0, 0, 0, 0, 0, // 3000- 6,-1, 0, 0, 0, 0, 0, 0, 10,-1, 0, 0, 0, 0, 0, 0, // 3010- @@ -52,7 +52,7 @@ int inter_recv_packet_length[] = { -1,-1,10,10, 0,-1,12, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3050- Auction System [Zephyrus] 6,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3060- Quest system [Kevin] [Inkfish] -1,10, 6,-1, 0, 0, 0, 0, 0, 0, 0, 0, -1,10, 6,-1, // 3070- Mercenary packets [Zephyrus], Elemental packets [pakpil] - 48,14,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3080- + 48,14,-1, 6, 0, 0, 0, 0, 0, 0,11,-1, 0, 0, 0, 0, // 3080- Pet System, Storage -1,10,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3090- Homunculus packets [albator] }; @@ -399,7 +399,7 @@ void mapif_parse_accinfo(int fd) { int u_fd = RFIFOL(fd,2), u_aid = RFIFOL(fd,6), u_group = RFIFOL(fd,10); char type= RFIFOB(fd,14); char query[NAME_LENGTH], query_esq[NAME_LENGTH*2+1]; - int account_id = 0; + uint32 account_id = 0; char *data; safestrncpy(query, (char*) RFIFOP(fd,15), NAME_LENGTH); @@ -492,7 +492,7 @@ void mapif_accinfo_ack(bool success, int map_fd, int u_fd, int u_aid, int accoun } } else { while ( SQL_SUCCESS == Sql_NextRow(sql_handle) ) { - int char_id, class_; + uint32 char_id, class_; short char_num, base_level, job_level, online; char name[NAME_LENGTH]; char *data; @@ -810,7 +810,7 @@ int inter_init_sql(const char *file) ShowInfo("Connect Character DB server.... (Character Server)\n"); if( SQL_ERROR == Sql_Connect(sql_handle, char_server_id, char_server_pw, char_server_ip, (uint16)char_server_port, char_server_db) ) { - ShowError("Couldn't connect with uname='%s',passwd='%s',host='%s',port='%d',database='%s'\n", + ShowError("Couldn't connect with username = '%s', password = '%s', host = '%s', port = '%d', database = '%s'\n", char_server_id, char_server_pw, char_server_ip, char_server_port, char_server_db); Sql_ShowDebug(sql_handle); Sql_Free(sql_handle); diff --git a/src/common/mmo.h b/src/common/mmo.h index f0dce7e232..3127b2dbd9 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -62,7 +62,7 @@ #define DEFAULT_WALK_SPEED 150 ///Default walk speed #define MIN_WALK_SPEED 20 ///Min walk speed #define MAX_WALK_SPEED 1000 ///Max walk speed -#define MAX_STORAGE 600 ///Max number of storage slots a player can have, (up to ~850 tested) +#define MAX_STORAGE 600 ///Max number of storage slots a player can have #define MAX_GUILD_STORAGE 600 ///Max number of storage slots a guild #define MAX_PARTY 12 ///Max party member #define MAX_GUILD 16+10*6 ///Increased max guild members +6 per 1 extension levels [Lupus] @@ -283,19 +283,26 @@ struct skill_cooldown_data { long tick; }; -struct storage_data { - int storage_amount; - struct item items[MAX_STORAGE]; +enum storage_type { + TABLE_INVENTORY, + TABLE_CART, + TABLE_STORAGE, + TABLE_GUILD_STORAGE, }; -/// Guild storgae struct -struct guild_storage { - bool dirty; ///< Dirty status, need to be saved - int guild_id; ///< Guild ID - short storage_amount; ///< Amount of item on storage - struct item items[MAX_GUILD_STORAGE]; ///< Item entries - bool locked; ///< If locked, can't use storage when item bound retrieval - uint32 opened; ///< Holds the char_id that open the storage +struct s_storage { + bool dirty; ///< Dirty status, data needs to be saved + bool status; ///< Current status of storage (opened or closed) + int amount; ///< Amount of items in storage + bool lock; ///< If locked, can't use storage when item bound retrieval + uint32 id; ///< Account ID / Character ID / Guild ID (owner of storage) + enum storage_type type; ///< Type of storage (inventory, cart, storage, guild storage) + union { // Max for inventory, storage, cart, and guild storage are 1637 each without changing this struct and struct item [2014/10/27] + struct item items_inventory[MAX_INVENTORY]; + struct item items_storage[MAX_STORAGE]; + struct item items_cart[MAX_CART]; + struct item items_guild[MAX_GUILD_STORAGE]; + } u; }; struct s_pet { @@ -418,8 +425,6 @@ struct mmo_charstatus { uint16 mapport; struct point last_point,save_point,memo_point[MAX_MEMOPOINTS]; - struct item inventory[MAX_INVENTORY],cart[MAX_CART]; - struct storage_data storage; struct s_skill skill[MAX_SKILL]; struct s_friend friends[MAX_FRIENDS]; //New friend system [Skotlex] diff --git a/src/login/account.c b/src/login/account.c index 1b3b172c3d..62e64f8aad 100644 --- a/src/login/account.c +++ b/src/login/account.c @@ -17,7 +17,6 @@ #include /// global defines -#define ACCOUNT_SQL_DB_VERSION 20140928 /// internal structure typedef struct AccountDB_SQL { @@ -117,15 +116,12 @@ static bool account_db_sql_init(AccountDB* self) { db->accounts = Sql_Malloc(); sql_handle = db->accounts; - if( db->db_hostname[0] != '\0' ) - {// local settings - username = db->db_username; - password = db->db_password; - hostname = db->db_hostname; - port = db->db_port; - database = db->db_database; - codepage = db->codepage; - } + username = db->db_username; + password = db->db_password; + hostname = db->db_hostname; + port = db->db_port; + database = db->db_database; + codepage = db->codepage; if( SQL_ERROR == Sql_Connect(sql_handle, username, password, hostname, port, database) ) { @@ -462,7 +458,7 @@ static void account_db_sql_iter_destroy(AccountDBIterator* self) { */ static bool account_db_sql_iter_next(AccountDBIterator* self, struct mmo_account* acc) { AccountDBIterator_SQL* iter = (AccountDBIterator_SQL*)self; - AccountDB_SQL* db = (AccountDB_SQL*)iter->db; + AccountDB_SQL* db = iter->db; Sql* sql_handle = db->accounts; char* data; @@ -526,15 +522,15 @@ static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, uint32 Sql_GetData(sql_handle, 2, &data, NULL); safestrncpy(acc->pass, data, sizeof(acc->pass)); Sql_GetData(sql_handle, 3, &data, NULL); acc->sex = data[0]; Sql_GetData(sql_handle, 4, &data, NULL); safestrncpy(acc->email, data, sizeof(acc->email)); - Sql_GetData(sql_handle, 5, &data, NULL); acc->group_id = atoi(data); - Sql_GetData(sql_handle, 6, &data, NULL); acc->state = strtoul(data, NULL, 10); + Sql_GetData(sql_handle, 5, &data, NULL); acc->group_id = (unsigned int) atoi(data); + Sql_GetData(sql_handle, 6, &data, NULL); acc->state = (unsigned int) strtoul(data, NULL, 10); Sql_GetData(sql_handle, 7, &data, NULL); acc->unban_time = atol(data); Sql_GetData(sql_handle, 8, &data, NULL); acc->expiration_time = atol(data); - Sql_GetData(sql_handle, 9, &data, NULL); acc->logincount = strtoul(data, NULL, 10); + Sql_GetData(sql_handle, 9, &data, NULL); acc->logincount = (unsigned int) strtoul(data, NULL, 10); Sql_GetData(sql_handle, 10, &data, NULL); safestrncpy(acc->lastlogin, data, sizeof(acc->lastlogin)); Sql_GetData(sql_handle, 11, &data, NULL); safestrncpy(acc->last_ip, data, sizeof(acc->last_ip)); Sql_GetData(sql_handle, 12, &data, NULL); safestrncpy(acc->birthdate, data, sizeof(acc->birthdate)); - Sql_GetData(sql_handle, 13, &data, NULL); acc->char_slots = atoi(data); + Sql_GetData(sql_handle, 13, &data, NULL); acc->char_slots = (uint8) atoi(data); Sql_GetData(sql_handle, 14, &data, NULL); safestrncpy(acc->pincode, data, sizeof(acc->pincode)); Sql_GetData(sql_handle, 15, &data, NULL); acc->pincode_change = atol(data); #ifdef VIP_ENABLE diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 860894f78a..4466b50e75 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -922,7 +922,7 @@ ACMD_FUNC(guildstorage) return -1; } - gstorage_storageopen(sd); + storage_guild_storageopen(sd); clif_displaymessage(fd, msg_txt(sd,920)); // Guild storage opened. return 0; } @@ -1374,8 +1374,8 @@ ACMD_FUNC(itemreset) nullpo_retr(-1, sd); for (i = 0; i < MAX_INVENTORY; i++) { - if (sd->status.inventory[i].amount && sd->status.inventory[i].equip == 0) { - pc_delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_COMMAND); + if (sd->inventory.u.items_inventory[i].amount && sd->inventory.u.items_inventory[i].equip == 0) { + pc_delitem(sd, i, sd->inventory.u.items_inventory[i].amount, 0, 0, LOG_TYPE_COMMAND); } } clif_displaymessage(fd, msg_txt(sd,20)); // All of your items have been removed. @@ -2243,15 +2243,15 @@ ACMD_FUNC(refine) if (pc_is_same_equip_index((enum equip_index)j, sd->equip_index, i)) continue; - if(position && !(sd->status.inventory[i].equip & position)) + if(position && !(sd->inventory.u.items_inventory[i].equip & position)) continue; - final_refine = cap_value(sd->status.inventory[i].refine + refine, 0, MAX_REFINE); - if (sd->status.inventory[i].refine != final_refine) { - sd->status.inventory[i].refine = final_refine; - current_position = sd->status.inventory[i].equip; + final_refine = cap_value(sd->inventory.u.items_inventory[i].refine + refine, 0, MAX_REFINE); + if (sd->inventory.u.items_inventory[i].refine != final_refine) { + sd->inventory.u.items_inventory[i].refine = final_refine; + current_position = sd->inventory.u.items_inventory[i].equip; pc_unequipitem(sd, i, 3); - clif_refine(fd, 0, i, sd->status.inventory[i].refine); + clif_refine(fd, 0, i, sd->inventory.u.items_inventory[i].refine); clif_delitem(sd, i, 1, 3); clif_additem(sd, i, 1, 0); pc_equipitem(sd, i, current_position); @@ -4372,9 +4372,9 @@ ACMD_FUNC(repairall) count = 0; for (i = 0; i < MAX_INVENTORY; i++) { - if (sd->status.inventory[i].nameid && sd->status.inventory[i].attribute == 1) { - sd->status.inventory[i].attribute = 0; - clif_produceeffect(sd, 0, sd->status.inventory[i].nameid); + if (sd->inventory.u.items_inventory[i].nameid && sd->inventory.u.items_inventory[i].attribute == 1) { + sd->inventory.u.items_inventory[i].attribute = 0; + clif_produceeffect(sd, 0, sd->inventory.u.items_inventory[i].nameid); count++; } } @@ -5377,20 +5377,20 @@ ACMD_FUNC(dropall) } for( i = 0; i < MAX_INVENTORY; i++ ) { - if( sd->status.inventory[i].amount ) { - if( (item_data = itemdb_exists(sd->status.inventory[i].nameid)) == NULL ) { - ShowDebug("Non-existant item %d on dropall list (account_id: %d, char_id: %d)\n", sd->status.inventory[i].nameid, sd->status.account_id, sd->status.char_id); + if( sd->inventory.u.items_inventory[i].amount ) { + if( (item_data = itemdb_exists(sd->inventory.u.items_inventory[i].nameid)) == NULL ) { + ShowDebug("Non-existant item %d on dropall list (account_id: %d, char_id: %d)\n", sd->inventory.u.items_inventory[i].nameid, sd->status.account_id, sd->status.char_id); continue; } - if( !pc_candrop(sd,&sd->status.inventory[i]) ) + if( !pc_candrop(sd,&sd->inventory.u.items_inventory[i]) ) continue; if( type == -1 || type == (uint8)item_data->type ) { - if( sd->status.inventory[i].equip != 0 ) + if( sd->inventory.u.items_inventory[i].equip != 0 ) pc_unequipitem(sd, i, 3); - if(pc_dropitem(sd, i, sd->status.inventory[i].amount)) - count += sd->status.inventory[i].amount; - else count2 += sd->status.inventory[i].amount; + if(pc_dropitem(sd, i, sd->inventory.u.items_inventory[i].amount)) + count += sd->inventory.u.items_inventory[i].amount; + else count2 += sd->inventory.u.items_inventory[i].amount; } } } @@ -5417,10 +5417,10 @@ ACMD_FUNC(storeall) } for (i = 0; i < MAX_INVENTORY; i++) { - if (sd->status.inventory[i].amount) { - if(sd->status.inventory[i].equip != 0) + if (sd->inventory.u.items_inventory[i].amount) { + if(sd->inventory.u.items_inventory[i].equip != 0) pc_unequipitem(sd, i, 3); - storage_storageadd(sd, i, sd->status.inventory[i].amount); + storage_storageadd(sd, i, sd->inventory.u.items_inventory[i].amount); } } storage_storageclose(sd); @@ -5439,10 +5439,11 @@ ACMD_FUNC(clearstorage) return -1; } - j = sd->status.storage.storage_amount; + j = sd->storage.amount; for (i = 0; i < j; ++i) { - storage_delitem(sd, i, sd->status.storage.items[i].amount); + storage_delitem(sd, i, sd->storage.u.items_storage[i].amount); } + sd->state.storage_flag = 1; storage_storageclose(sd); clif_displaymessage(fd, msg_txt(sd,1394)); // Your storage was cleaned. @@ -5453,7 +5454,7 @@ ACMD_FUNC(cleargstorage) { int i, j; struct guild *g; - struct guild_storage *gstorage; + struct s_storage *gstorage; nullpo_retr(-1, sd); g = sd->guild; @@ -5473,24 +5474,18 @@ ACMD_FUNC(cleargstorage) return -1; } - 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. + gstorage = guild2storage2(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; } - if (gstorage->opened) { - struct map_session_data *tsd = map_charid2sd(gstorage->opened); - if (tsd) - gstorage_storageclose(tsd); - } - - j = gstorage->storage_amount; - gstorage->locked = true; // Lock @gstorage: do not allow any item to be retrieved or stored from any guild member + j = gstorage->amount; + gstorage->lock = 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); + storage_guild_delitem(sd, gstorage, i, gstorage->u.items_guild[i].amount); } - gstorage_storageclose(sd); - gstorage->locked = false; // Cleaning done, release lock + storage_guild_storageclose(sd); + gstorage->lock = false; // Cleaning done, release lock clif_displaymessage(fd, msg_txt(sd,1395)); // Your guild storage was cleaned. return 0; @@ -5510,9 +5505,10 @@ ACMD_FUNC(clearcart) return -1; } - for( i = 0; i < MAX_CART; i++ ) - if(sd->status.cart[i].nameid > 0) - pc_cart_delitem(sd, i, sd->status.cart[i].amount, 1, LOG_TYPE_OTHER); + for (i = 0; i < MAX_CART; i++) { + if (sd->cart.u.items_cart[i].nameid > 0) + pc_cart_delitem(sd, i, sd->cart.u.items_cart[i].amount, 1, LOG_TYPE_OTHER); + } clif_clearcart(fd); clif_updatestatus(sd,SP_CARTINFO); @@ -6925,7 +6921,7 @@ ACMD_FUNC(identify) nullpo_retr(-1, sd); for(i=num=0;istatus.inventory[i].nameid > 0 && sd->status.inventory[i].identify!=1){ + if(sd->inventory.u.items_inventory[i].nameid > 0 && sd->inventory.u.items_inventory[i].identify != 1) { num++; } } @@ -6946,8 +6942,8 @@ ACMD_FUNC(identifyall) int i; nullpo_retr(-1, sd); for(i=0; istatus.inventory[i].nameid > 0 && sd->status.inventory[i].identify!=1) { - sd->status.inventory[i].identify=1; + if (sd->inventory.u.items_inventory[i].nameid > 0 && sd->inventory.u.items_inventory[i].identify != 1) { + sd->inventory.u.items_inventory[i].identify = 1; clif_item_identified(sd,i,0); } } @@ -8545,15 +8541,15 @@ ACMD_FUNC(itemlist) if( strcmp(parent_cmd, "storagelist") == 0 ) { location = "storage"; - items = sd->status.storage.items; + items = sd->storage.u.items_storage; size = sd->storage_size; } else if( strcmp(parent_cmd, "cartlist") == 0 ) { location = "cart"; - items = sd->status.cart; + items = sd->cart.u.items_cart; size = MAX_CART; } else if( strcmp(parent_cmd, "itemlist") == 0 ) { location = "inventory"; - items = sd->status.inventory; + items = sd->inventory.u.items_inventory; size = MAX_INVENTORY; } else return 1; @@ -8799,11 +8795,11 @@ ACMD_FUNC(delitem) // delete items while( amount && ( idx = pc_search_inventory(sd, nameid) ) != -1 ) { - int delamount = ( amount < sd->status.inventory[idx].amount ) ? amount : sd->status.inventory[idx].amount; + int delamount = ( amount < sd->inventory.u.items_inventory[idx].amount ) ? amount : sd->inventory.u.items_inventory[idx].amount; - if( sd->inventory_data[idx]->type == IT_PETEGG && sd->status.inventory[idx].card[0] == CARD0_PET ) + if( sd->inventory_data[idx]->type == IT_PETEGG && sd->inventory.u.items_inventory[idx].card[0] == CARD0_PET ) {// delete pet - intif_delete_petdata(MakeDWord(sd->status.inventory[idx].card[1], sd->status.inventory[idx].card[2])); + intif_delete_petdata(MakeDWord(sd->inventory.u.items_inventory[idx].card[1], sd->inventory.u.items_inventory[idx].card[2])); } pc_delitem(sd, idx, delamount, 0, 0, LOG_TYPE_COMMAND); @@ -9671,7 +9667,7 @@ ACMD_FUNC(cloneequip) { if (pc_is_same_equip_index((enum equip_index) i, pl_sd->equip_index, idx)) continue; - tmp_item = pl_sd->status.inventory[idx]; + tmp_item = pl_sd->inventory.u.items_inventory[idx]; if (itemdb_isspecial(tmp_item.card[0])) memset(tmp_item.card, 0, sizeof(tmp_item.card)); tmp_item.bound = 0; diff --git a/src/map/battle.c b/src/map/battle.c index 8bd97c2674..f8d34bfe06 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -3289,7 +3289,7 @@ static struct Damage battle_calc_multi_attack(struct Damage wd, struct block_lis sc_start(src,src,SC_QD_SHOT_READY,100,target->id,skill_get_time(RL_QD_SHOT,1)); } else if(sc && sc->data[SC_FEARBREEZE] && sd->weapontype1==W_BOW - && (i = sd->equip_index[EQI_AMMO]) >= 0 && sd->inventory_data[i] && sd->status.inventory[i].amount > 1) + && (i = sd->equip_index[EQI_AMMO]) >= 0 && sd->inventory_data[i] && sd->inventory.u.items_inventory[i].amount > 1) { int chance = rnd()%100; switch(sc->data[SC_FEARBREEZE]->val1) { @@ -3299,7 +3299,7 @@ static struct Damage battle_calc_multi_attack(struct Damage wd, struct block_lis case 2: case 1: if( chance < 13) { wd.div_ = 2; break; } // 12 % chance to attack 2 times. } - wd.div_ = min(wd.div_,sd->status.inventory[i].amount); + wd.div_ = min(wd.div_,sd->inventory.u.items_inventory[i].amount); sc->data[SC_FEARBREEZE]->val4 = wd.div_-1; if (wd.div_ > 1) wd.type = DMG_MULTI_HIT; @@ -3361,7 +3361,7 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s if (index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON) skillratio += -100 + sd->inventory_data[index]->weight / 10 + sstatus->rhw.atk + - 100 * sd->inventory_data[index]->wlv * (sd->status.inventory[index].refine + 6); + 100 * sd->inventory_data[index]->wlv * (sd->inventory.u.items_inventory[index].refine + 6); } status_change_end(src,SC_CRUSHSTRIKE,INVALID_TIMER); skill_break_equip(src,src,EQP_WEAPON,2000,BCT_SELF); @@ -4321,7 +4321,7 @@ static int64 battle_calc_skill_constant_addition(struct Damage wd, struct block_ short index = sd->equip_index[EQI_HAND_L]; if (index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR) - damagevalue = sstatus->vit * sd->status.inventory[index].refine; + damagevalue = sstatus->vit * sd->inventory.u.items_inventory[index].refine; atk = damagevalue; } break; @@ -5391,7 +5391,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl short index = sd->equip_index[EQI_HAND_L]; if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR ) - ATK_ADD(wd.damage, wd.damage2, 10*sd->status.inventory[index].refine); + ATK_ADD(wd.damage, wd.damage2, 10*sd->inventory.u.items_inventory[index].refine); } #ifndef RENEWAL //Card Fix for attacker (sd), 2 is added to the "left" flag meaning "attacker cards only" @@ -7185,7 +7185,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t if( sd && battle_config.arrow_decrement && sc->data[SC_FEARBREEZE] && sc->data[SC_FEARBREEZE]->val4 > 0) { short idx = sd->equip_index[EQI_AMMO]; - if (idx >= 0 && sd->status.inventory[idx].amount >= sc->data[SC_FEARBREEZE]->val4) { + if (idx >= 0 && sd->inventory.u.items_inventory[idx].amount >= sc->data[SC_FEARBREEZE]->val4) { pc_delitem(sd,idx,sc->data[SC_FEARBREEZE]->val4,0,1,LOG_TYPE_CONSUME); sc->data[SC_FEARBREEZE]->val4 = 0; } diff --git a/src/map/buyingstore.c b/src/map/buyingstore.c index 910366c01d..ead241e1a9 100644 --- a/src/map/buyingstore.c +++ b/src/map/buyingstore.c @@ -182,7 +182,7 @@ int8 buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha break; } - if( sd->status.inventory[idx].amount+amount > BUYINGSTORE_MAX_AMOUNT ) + if( sd->inventory.u.items_inventory[idx].amount + amount > BUYINGSTORE_MAX_AMOUNT ) {// too many items of same kind break; } @@ -386,13 +386,13 @@ void buyingstore_trade(struct map_session_data* sd, uint32 account_id, unsigned } } - if( index < 0 || index >= ARRAYLENGTH(sd->status.inventory) || sd->inventory_data[index] == NULL || sd->status.inventory[index].nameid != nameid || sd->status.inventory[index].amount < amount ) + if( index < 0 || index >= ARRAYLENGTH(sd->inventory.u.items_inventory) || sd->inventory_data[index] == NULL || sd->inventory.u.items_inventory[index].nameid != nameid || sd->inventory.u.items_inventory[index].amount < amount ) {// invalid input clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); return; } - if( sd->status.inventory[index].expire_time || (sd->status.inventory[index].bound && !pc_can_give_bounded_items(sd)) || !itemdb_cantrade(&sd->status.inventory[index], pc_get_group_level(sd), pc_get_group_level(pl_sd)) || memcmp(sd->status.inventory[index].card, buyingstore_blankslots, sizeof(buyingstore_blankslots)) ) + if( sd->inventory.u.items_inventory[index].expire_time || (sd->inventory.u.items_inventory[index].bound && !pc_can_give_bounded_items(sd)) || !itemdb_cantrade(&sd->inventory.u.items_inventory[index], pc_get_group_level(sd), pc_get_group_level(pl_sd)) || memcmp(sd->inventory.u.items_inventory[index].card, buyingstore_blankslots, sizeof(buyingstore_blankslots)) ) {// non-tradable item clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); return; @@ -447,7 +447,7 @@ void buyingstore_trade(struct map_session_data* sd, uint32 account_id, unsigned zeny = amount*pl_sd->buyingstore.items[listidx].price; // move item - pc_additem(pl_sd, &sd->status.inventory[index], amount, LOG_TYPE_BUYING_STORE); + pc_additem(pl_sd, &sd->inventory.u.items_inventory[index], amount, LOG_TYPE_BUYING_STORE); pc_delitem(sd, index, amount, 1, 0, LOG_TYPE_BUYING_STORE); pl_sd->buyingstore.items[listidx].amount-= amount; diff --git a/src/map/chrif.c b/src/map/chrif.c index 8e728fa7e9..51121f32e8 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -297,9 +297,14 @@ int chrif_save(struct map_session_data *sd, int flag) { chrif_bsdata_save(sd, (flag && (flag != 3))); + if (sd->state.storage_flag == 1) + intif_storage_save(sd,TABLE_STORAGE); + intif_storage_save(sd,TABLE_INVENTORY); + intif_storage_save(sd,TABLE_CART); + //For data sync if (sd->state.storage_flag == 2) - gstorage_storagesave(sd->status.account_id, sd->status.guild_id, flag); + storage_guild_storagesave(sd->status.account_id, sd->status.guild_id, flag); if (flag) sd->state.storage_flag = 0; //Force close it. @@ -1033,14 +1038,14 @@ int chrif_divorceack(uint32 char_id, int partner_id) { if( ( sd = map_charid2sd(char_id) ) != NULL && sd->status.partner_id == partner_id ) { sd->status.partner_id = 0; for(i = 0; i < MAX_INVENTORY; i++) - if (sd->status.inventory[i].nameid == WEDDING_RING_M || sd->status.inventory[i].nameid == WEDDING_RING_F) + if (sd->inventory.u.items_inventory[i].nameid == WEDDING_RING_M || sd->inventory.u.items_inventory[i].nameid == WEDDING_RING_F) pc_delitem(sd, i, 1, 0, 0, LOG_TYPE_OTHER); } if( ( sd = map_charid2sd(partner_id) ) != NULL && sd->status.partner_id == char_id ) { sd->status.partner_id = 0; for(i = 0; i < MAX_INVENTORY; i++) - if (sd->status.inventory[i].nameid == WEDDING_RING_M || sd->status.inventory[i].nameid == WEDDING_RING_F) + if (sd->inventory.u.items_inventory[i].nameid == WEDDING_RING_M || sd->inventory.u.items_inventory[i].nameid == WEDDING_RING_F) pc_delitem(sd, i, 1, 0, 0, LOG_TYPE_OTHER); } @@ -1975,7 +1980,7 @@ void do_final_chrif(void) { *------------------------------------------*/ void do_init_chrif(void) { if(sizeof(struct mmo_charstatus) > 0xFFFF){ - ShowError("mmo_charstatus size = %d is too big to be transmitted. (must be below 0xFFFF) \n", + ShowError("mmo_charstatus size = %d is too big to be transmitted. (must be below 0xFFFF)\n", sizeof(struct mmo_charstatus)); exit(EXIT_FAILURE); } @@ -1986,6 +1991,11 @@ void do_init_chrif(void) { exit(EXIT_FAILURE); } + if(sizeof(struct s_storage) > 0xFFFF) { + ShowError("s_storage size = %d is too big to be transmitted. (must be below 0xFFFF)\n", sizeof(struct s_storage)); + exit(EXIT_FAILURE); + } + auth_db = idb_alloc(DB_OPT_BASE); auth_db_ers = ers_new(sizeof(struct auth_node),"chrif.c::auth_db_ers",ERS_OPT_NONE); diff --git a/src/map/clif.c b/src/map/clif.c index f1e7911bf2..d7064904b1 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -1947,15 +1947,15 @@ void clif_selllist(struct map_session_data *sd) WFIFOW(fd,0)=0xc7; for( i = 0; i < MAX_INVENTORY; i++ ) { - if( sd->status.inventory[i].nameid > 0 && sd->inventory_data[i] ) + if( sd->inventory.u.items_inventory[i].nameid > 0 && sd->inventory_data[i] ) { - if( !itemdb_cansell(&sd->status.inventory[i], pc_get_group_level(sd)) ) + if( !itemdb_cansell(&sd->inventory.u.items_inventory[i], pc_get_group_level(sd)) ) continue; - if( sd->status.inventory[i].expire_time || (sd->status.inventory[i].bound && !pc_can_give_bounded_items(sd)) ) + if( sd->inventory.u.items_inventory[i].expire_time || (sd->inventory.u.items_inventory[i].bound && !pc_can_give_bounded_items(sd)) ) continue; // Cannot Sell Rental Items or Account Bounded Items - if( sd->status.inventory[i].bound && !pc_can_give_bounded_items(sd)) + if( sd->inventory.u.items_inventory[i].bound && !pc_can_give_bounded_items(sd)) continue; // Don't allow sale of bound items val=sd->inventory_data[i]->value_sell; @@ -2514,7 +2514,7 @@ void clif_additem(struct map_session_data *sd, int n, int amount, unsigned char } else { - if( n < 0 || n >= MAX_INVENTORY || sd->status.inventory[n].nameid <=0 || sd->inventory_data[n] == NULL ) + if( n < 0 || n >= MAX_INVENTORY || sd->inventory.u.items_inventory[n].nameid <=0 || sd->inventory_data[n] == NULL ) return; WFIFOW(fd,offs+0) = header; @@ -2523,11 +2523,11 @@ void clif_additem(struct map_session_data *sd, int n, int amount, unsigned char if (sd->inventory_data[n]->view_id > 0) 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; - clif_addcards(WFIFOP(fd,offs+11), &sd->status.inventory[n]); + WFIFOW(fd,offs+6)=sd->inventory.u.items_inventory[n].nameid; + WFIFOB(fd,offs+8)=sd->inventory.u.items_inventory[n].identify; + WFIFOB(fd,offs+9)=sd->inventory.u.items_inventory[n].attribute; + WFIFOB(fd,offs+10)=sd->inventory.u.items_inventory[n].refine; + clif_addcards(WFIFOP(fd,offs+11), &sd->inventory.u.items_inventory[n]); #if PACKETVER < 20120925 WFIFOW(fd,offs+19) = pc_equippoint(sd,n); #else @@ -2537,11 +2537,11 @@ void clif_additem(struct map_session_data *sd, int n, int amount, unsigned char 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->inventory.u.items_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 : sd->inventory_data[n]->flag.bindOnEquip ? BOUND_ONEQUIP : 0; + WFIFOW(fd,offs+27)=(sd->inventory.u.items_inventory[n].bound && !itemdb_isstackable(sd->inventory.u.items_inventory[n].nameid)) ? BOUND_DISPYELLOW : sd->inventory_data[n]->flag.bindOnEquip ? BOUND_ONEQUIP : 0; #endif #if PACKETVER >= 20150226 clif_add_random_options(WFIFOP(fd,31), &sd->status.inventory[n]); @@ -2708,17 +2708,17 @@ void clif_inventorylist(struct map_session_data *sd) { for( i = 0, n = 0, ne = 0; i < MAX_INVENTORY; i++ ) { - if( sd->status.inventory[i].nameid <=0 || sd->inventory_data[i] == NULL ) + if( sd->inventory.u.items_inventory[i].nameid <=0 || sd->inventory_data[i] == NULL ) continue; if( !itemdb_isstackable2(sd->inventory_data[i]) ) { //Non-stackable (Equippable) - clif_item_sub(bufe, ne*se+4, i+2, &sd->status.inventory[i], sd->inventory_data[i], pc_equippoint(sd,i)); + clif_item_sub(bufe, ne*se+4, i+2, &sd->inventory.u.items_inventory[i], sd->inventory_data[i], pc_equippoint(sd,i)); ne++; } else { //Stackable. - clif_item_sub(buf, n*s+4,i+2, &sd->status.inventory[i], sd->inventory_data[i], -2); - if( sd->inventory_data[i]->equip == EQP_AMMO && sd->status.inventory[i].equip ) + clif_item_sub(buf, n*s+4,i+2, &sd->inventory.u.items_inventory[i], sd->inventory_data[i], -2); + if( sd->inventory_data[i]->equip == EQP_AMMO && sd->inventory.u.items_inventory[i].equip ) arrow=i; n++; } @@ -2755,9 +2755,9 @@ void clif_inventorylist(struct map_session_data *sd) { } #if PACKETVER >= 20111122 && PACKETVER < 20120925 for( i = 0; i < MAX_INVENTORY; i++ ) { - if( sd->status.inventory[i].nameid <= 0 || sd->inventory_data[i] == NULL ) + if( sd->inventory.u.items_inventory[i].nameid <= 0 || sd->inventory_data[i] == NULL ) continue; - if ( sd->status.inventory[i].favorite ) + if ( sd->inventory.u.items_inventory[i].favorite ) clif_favorite_item(sd, i); } #endif @@ -2787,13 +2787,13 @@ void clif_equiplist(struct map_session_data *sd) buf = WFIFOP(fd,0); for(i=0,n=0;istatus.inventory[i].nameid <=0 || sd->inventory_data[i] == NULL) + if (sd->inventory.u.items_inventory[i].nameid <=0 || sd->inventory_data[i] == NULL) continue; if(itemdb_isstackable2(sd->inventory_data[i])) continue; //Equippable - clif_item_sub(buf, n*cmd+4,i+2, &sd->status.inventory[i], sd->inventory_data[i], pc_equippoint(sd,i)); + clif_item_sub(buf, n*cmd+4,i+2, &sd->inventory.u.items_inventory[i], sd->inventory_data[i], pc_equippoint(sd,i)); n++; } if (n) { @@ -2935,15 +2935,15 @@ void clif_cartlist(struct map_session_data *sd) for( i = 0, n = 0, ne = 0; i < MAX_CART; i++ ) { - if( sd->status.cart[i].nameid <= 0 ) + if( sd->cart.u.items_cart[i].nameid <= 0 ) continue; - id = itemdb_search(sd->status.cart[i].nameid); + id = itemdb_search(sd->cart.u.items_cart[i].nameid); if( !itemdb_isstackable2(id) ) { //Equippable - clif_item_sub(bufe, ne*cmd+4,i+2, &sd->status.cart[i], id, id->equip); + clif_item_sub(bufe, ne*cmd+4,i+2, &sd->cart.u.items_cart[i], id, id->equip); ne++; } else { //Stackable - clif_item_sub(buf, n*s+4,i+2, &sd->status.cart[i], id,-1); + clif_item_sub(buf, n*s+4,i+2, &sd->cart.u.items_cart[i], id,-1); n++; } } @@ -3471,7 +3471,7 @@ void clif_changelook(struct block_list *bl, int type, int val) { if(sd->inventory_data[n]->view_id > 0) val = sd->inventory_data[n]->view_id; else - val = sd->status.inventory[n].nameid; + val = sd->inventory.u.items_inventory[n].nameid; } else val = 0; } @@ -3656,7 +3656,7 @@ void clif_arrow_create_list(struct map_session_data *sd) short j, nameid = skill_arrow_db[i].nameid; if (nameid > 0 && itemdb_exists(nameid) && (j = pc_search_inventory(sd, nameid)) >= 0 && - !sd->status.inventory[j].equip && sd->status.inventory[j].identify) + !sd->inventory.u.items_inventory[j].equip && sd->inventory.u.items_inventory[j].identify) { if ((j = itemdb_viewid(nameid)) > 0) WFIFOW(fd,c*2+4) = j; @@ -3923,7 +3923,7 @@ void clif_useitemack(struct map_session_data *sd,int index,int amount,bool ok) if(sd->inventory_data[index] && sd->inventory_data[index]->view_id > 0) WBUFW(buf,4)=sd->inventory_data[index]->view_id; else - WBUFW(buf,4)=sd->status.inventory[index].nameid; + WBUFW(buf,4)=sd->inventory.u.items_inventory[index].nameid; WBUFL(buf,6)=sd->bl.id; WBUFW(buf,10)=amount; WBUFB(buf,12)=ok; @@ -4277,20 +4277,20 @@ void clif_tradeadditem(struct map_session_data* sd, struct map_session_data* tsd if(sd->inventory_data[index] && sd->inventory_data[index]->view_id > 0) WBUFW(buf,6) = sd->inventory_data[index]->view_id; else - WBUFW(buf,6) = sd->status.inventory[index].nameid; // type id + WBUFW(buf,6) = sd->inventory.u.items_inventory[index].nameid; // type id #else if(sd->inventory_data[index] && sd->inventory_data[index]->view_id > 0) WBUFW(buf,2) = sd->inventory_data[index]->view_id; else - WBUFW(buf,2) = sd->status.inventory[index].nameid; // type id + WBUFW(buf,2) = sd->inventory.u.items_inventory[index].nameid; // type id WBUFB(buf,4) = sd->inventory_data[index]->type; // item type WBUFL(buf,5) = amount; // amount buf = WBUFP(buf,1); //Advance 1B #endif - WBUFB(buf,8) = sd->status.inventory[index].identify; //identify flag - WBUFB(buf,9) = sd->status.inventory[index].attribute; // attribute - WBUFB(buf,10)= sd->status.inventory[index].refine; //refine - clif_addcards(WBUFP(buf, 11), &sd->status.inventory[index]); + WBUFB(buf,8) = sd->inventory.u.items_inventory[index].identify; //identify flag + WBUFB(buf,9) = sd->inventory.u.items_inventory[index].attribute; // attribute + WBUFB(buf,10)= sd->inventory.u.items_inventory[index].refine; //refine + clif_addcards(WBUFP(buf, 11), &sd->inventory.u.items_inventory[index]); #if PACKETVER >= 20150226 clif_add_random_options(WBUFP(buf, 19), &sd->status.inventory[index]); #endif @@ -6356,10 +6356,10 @@ void clif_use_card(struct map_session_data *sd,int idx) continue; if(sd->inventory_data[i]->type!=IT_WEAPON && sd->inventory_data[i]->type!=IT_ARMOR) continue; - if(itemdb_isspecial(sd->status.inventory[i].card[0])) //Can't slot it + if(itemdb_isspecial(sd->inventory.u.items_inventory[i].card[0])) //Can't slot it continue; - if(sd->status.inventory[i].identify==0 ) //Not identified + if(sd->inventory.u.items_inventory[i].identify==0 ) //Not identified continue; if((sd->inventory_data[i]->equip&ep)==0) //Not equippable on this part. @@ -6368,11 +6368,11 @@ void clif_use_card(struct map_session_data *sd,int idx) if(sd->inventory_data[i]->type==IT_WEAPON && ep==EQP_SHIELD) //Shield card won't go on left weapon. continue; - ARR_FIND( 0, sd->inventory_data[i]->slot, j, sd->status.inventory[i].card[j] == 0 ); + ARR_FIND( 0, sd->inventory_data[i]->slot, j, sd->inventory.u.items_inventory[i].card[j] == 0 ); if( j == sd->inventory_data[i]->slot ) // No room continue; - if( sd->status.inventory[i].equip > 0 ) // Do not check items that are already equipped + if( sd->inventory.u.items_inventory[i].equip > 0 ) // Do not check items that are already equipped continue; WFIFOW(fd,4+c*2)=i+2; @@ -6421,7 +6421,7 @@ void clif_item_identify_list(struct map_session_data *sd) WFIFOHEAD(fd,MAX_INVENTORY * 2 + 4); WFIFOW(fd,0)=0x177; for(i=c=0;istatus.inventory[i].nameid > 0 && !sd->status.inventory[i].identify){ + if(sd->inventory.u.items_inventory[i].nameid > 0 && !sd->inventory.u.items_inventory[i].identify){ WFIFOW(fd,c*2+4)=i+2; c++; } @@ -6468,11 +6468,11 @@ void clif_item_repair_list(struct map_session_data *sd,struct map_session_data * WFIFOW(fd,0)=0x1fc; for(i=c=0;istatus.inventory[i].nameid) > 0 && dstsd->status.inventory[i].attribute!=0){// && skill_can_repair(sd,nameid)){ + if((nameid=dstsd->inventory.u.items_inventory[i].nameid) > 0 && dstsd->inventory.u.items_inventory[i].attribute!=0){// && skill_can_repair(sd,nameid)){ WFIFOW(fd,c*13+4) = i; WFIFOW(fd,c*13+6) = nameid; - WFIFOB(fd,c*13+8) = dstsd->status.inventory[i].refine; - clif_addcards(WFIFOP(fd,c*13+9), &dstsd->status.inventory[i]); + WFIFOB(fd,c*13+8) = dstsd->inventory.u.items_inventory[i].refine; + clif_addcards(WFIFOP(fd,c*13+9), &dstsd->inventory.u.items_inventory[i]); c++; } } @@ -6546,16 +6546,16 @@ void clif_item_refine_list(struct map_session_data *sd) refine_item[3] = refine_item[4] = pc_search_inventory(sd,ITEMID_ORIDECON); WFIFOHEAD(fd, MAX_INVENTORY * 13 + 4); - WFIFOW(fd,0)=0x221; - for(i=c=0;istatus.inventory[i].nameid > 0 && sd->status.inventory[i].refine < skill_lv && - sd->status.inventory[i].identify && (wlv=itemdb_wlv(sd->status.inventory[i].nameid)) >=1 && - refine_item[wlv]!=-1 && !(sd->status.inventory[i].equip&EQP_ARMS)){ + if(sd->inventory.u.items_inventory[i].nameid > 0 && sd->inventory.u.items_inventory[i].refine < skill_lv && + sd->inventory.u.items_inventory[i].identify && (wlv = itemdb_wlv(sd->inventory.u.items_inventory[i].nameid)) >=1 && + refine_item[wlv] != -1 && !(sd->inventory.u.items_inventory[i].equip&EQP_ARMS)){ WFIFOW(fd,c*13+ 4)=i+2; - WFIFOW(fd,c*13+ 6)=sd->status.inventory[i].nameid; - WFIFOB(fd,c*13+ 8)=sd->status.inventory[i].refine; - clif_addcards(WFIFOP(fd,c*13+9), &sd->status.inventory[i]); + WFIFOW(fd,c*13+ 6) = sd->inventory.u.items_inventory[i].nameid; + WFIFOB(fd,c*13+ 8) = sd->inventory.u.items_inventory[i].refine; + clif_addcards(WFIFOP(fd,c*13+9), &sd->inventory.u.items_inventory[i]); c++; } } @@ -6611,7 +6611,7 @@ void clif_cart_additem(struct map_session_data *sd,int n,int amount,int fail) nullpo_retv(sd); fd=sd->fd; - if(n<0 || n>=MAX_CART || sd->status.cart[n].nameid<=0) + if(n < 0 || n >= MAX_CART || sd->cart.u.items_cart[n].nameid <= 0) return; WFIFOHEAD(fd,packet_len(cmd)); @@ -6619,20 +6619,20 @@ void clif_cart_additem(struct map_session_data *sd,int n,int amount,int fail) WBUFW(buf,0)=cmd; WBUFW(buf,2)=n+2; WBUFL(buf,4)=amount; - if((view = itemdb_viewid(sd->status.cart[n].nameid)) > 0) + if((view = itemdb_viewid(sd->cart.u.items_cart[n].nameid)) > 0) WBUFW(buf,8)=view; else - WBUFW(buf,8)=sd->status.cart[n].nameid; + WBUFW(buf,8)=sd->cart.u.items_cart[n].nameid; #if PACKETVER >= 5 - WBUFB(buf,10)=itemdb_type(sd->status.cart[n].nameid); + WBUFB(buf,10)=itemdb_type(sd->cart.u.items_cart[n].nameid); offset += 1; #endif - WBUFB(buf,10+offset)=sd->status.cart[n].identify; - WBUFB(buf,11+offset)=sd->status.cart[n].attribute; - WBUFB(buf,12+offset)=sd->status.cart[n].refine; - clif_addcards(WBUFP(buf,13+offset), &sd->status.cart[n]); + WBUFB(buf,10+offset)=sd->cart.u.items_cart[n].identify; + WBUFB(buf,11+offset)=sd->cart.u.items_cart[n].attribute; + WBUFB(buf,12+offset)=sd->cart.u.items_cart[n].refine; + clif_addcards(WBUFP(buf,13+offset), &sd->cart.u.items_cart[n]); #if PACKETVER >= 20150226 - clif_add_random_options(WBUFP(buf,21+offset), &sd->status.cart[n]); + clif_add_random_options(WBUFP(buf,21+offset), &sd->cart.u.items_cart[n]); #endif WFIFOSET(fd,packet_len(cmd)); } @@ -6895,6 +6895,9 @@ void clif_openvendingreq(struct map_session_data* sd, int num) nullpo_retv(sd); + intif_storage_save(sd, TABLE_CART); // Save cart item data + intif_storage_request(sd, TABLE_CART); // Update cart item ID information + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x12d)); WFIFOW(fd,0) = 0x12d; @@ -6985,18 +6988,18 @@ void clif_vendinglist(struct map_session_data* sd, int id, struct s_vending* ven for( i = 0; i < count; i++ ) { int index = vending[i].index; - struct item_data* data = itemdb_search(vsd->status.cart[index].nameid); + struct item_data* data = itemdb_search(vsd->cart.u.items_cart[index].nameid); WFIFOL(fd,offset+ 0+i*item_length) = vending[i].value; WFIFOW(fd,offset+ 4+i*item_length) = vending[i].amount; WFIFOW(fd,offset+ 6+i*item_length) = vending[i].index + 2; WFIFOB(fd,offset+ 8+i*item_length) = itemtype(data->nameid); - WFIFOW(fd,offset+ 9+i*item_length) = ( data->view_id > 0 ) ? data->view_id : vsd->status.cart[index].nameid; - WFIFOB(fd,offset+11+i*item_length) = vsd->status.cart[index].identify; - WFIFOB(fd,offset+12+i*item_length) = vsd->status.cart[index].attribute; - WFIFOB(fd,offset+13+i*item_length) = vsd->status.cart[index].refine; - clif_addcards(WFIFOP(fd,offset+14+i*item_length), &vsd->status.cart[index]); + WFIFOW(fd,offset+ 9+i*item_length) = ( data->view_id > 0 ) ? data->view_id : vsd->cart.u.items_cart[index].nameid; + WFIFOB(fd,offset+11+i*item_length) = vsd->cart.u.items_cart[index].identify; + WFIFOB(fd,offset+12+i*item_length) = vsd->cart.u.items_cart[index].attribute; + WFIFOB(fd,offset+13+i*item_length) = vsd->cart.u.items_cart[index].refine; + clif_addcards(WFIFOP(fd,offset+14+i*item_length), &vsd->cart.u.items_cart[index]); #if PACKETVER >= 20150226 - clif_add_random_options(WFIFOP(fd,offset+22+i*item_length), &vsd->status.cart[index]); + clif_add_random_options(WFIFOP(fd,offset+22+i*item_length), &vsd->cart.u.items_cart[index]); #endif } WFIFOSET(fd,WFIFOW(fd,2)); @@ -7070,18 +7073,18 @@ void clif_openvending(struct map_session_data* sd, int id, struct s_vending* ven WFIFOL(fd,4) = id; for( i = 0; i < count; i++ ) { int index = vending[i].index; - struct item_data* data = itemdb_search(sd->status.cart[index].nameid); + struct item_data* data = itemdb_search(sd->cart.u.items_cart[index].nameid); WFIFOL(fd, 8+i*item_length) = vending[i].value; WFIFOW(fd,12+i*item_length) = vending[i].index + 2; WFIFOW(fd,14+i*item_length) = vending[i].amount; WFIFOB(fd,16+i*item_length) = itemtype(data->nameid); - WFIFOW(fd,17+i*item_length) = ( data->view_id > 0 ) ? data->view_id : sd->status.cart[index].nameid; - WFIFOB(fd,19+i*item_length) = sd->status.cart[index].identify; - WFIFOB(fd,20+i*item_length) = sd->status.cart[index].attribute; - WFIFOB(fd,21+i*item_length) = sd->status.cart[index].refine; - clif_addcards(WFIFOP(fd,22+i*item_length), &sd->status.cart[index]); + WFIFOW(fd,17+i*item_length) = ( data->view_id > 0 ) ? data->view_id : sd->cart.u.items_cart[index].nameid; + WFIFOB(fd,19+i*item_length) = sd->cart.u.items_cart[index].identify; + WFIFOB(fd,20+i*item_length) = sd->cart.u.items_cart[index].attribute; + WFIFOB(fd,21+i*item_length) = sd->cart.u.items_cart[index].refine; + clif_addcards(WFIFOP(fd,22+i*item_length), &sd->cart.u.items_cart[index]); #if PACKETVER >= 20150226 - clif_add_random_options(WFIFOP(fd,30+i*item_length), &sd->status.cart[index]); + clif_add_random_options(WFIFOP(fd,30+i*item_length), &sd->cart.u.items_cart[index]); #endif } WFIFOSET(fd,WFIFOW(fd,2)); @@ -7601,9 +7604,9 @@ void clif_sendegg(struct map_session_data *sd) WFIFOHEAD(fd, MAX_INVENTORY * 2 + 4); WFIFOW(fd,0)=0x1a6; for(i=0,n=0;istatus.inventory[i].nameid<=0 || sd->inventory_data[i] == NULL || - sd->inventory_data[i]->type!=IT_PETEGG || - sd->status.inventory[i].amount<=0) + if(sd->inventory.u.items_inventory[i].nameid <= 0 || sd->inventory_data[i] == NULL || + sd->inventory_data[i]->type != IT_PETEGG || + sd->inventory.u.items_inventory[i].amount <= 0) continue; WFIFOW(fd,n*2+4)=i+2; n++; @@ -9126,21 +9129,21 @@ void clif_messagecolor2(struct map_session_data *sd, unsigned long color, const void clif_refresh_storagewindow(struct map_session_data *sd) { // Notify the client that the storage is open if( 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, MAX_STORAGE); + storage_sortitem(sd->storage.u.items_storage, ARRAYLENGTH(sd->storage.u.items_storage)); + clif_storagelist(sd, sd->storage.u.items_storage, ARRAYLENGTH(sd->storage.u.items_storage)); + clif_updatestorageamount(sd, sd->storage.amount, MAX_STORAGE); } // 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 = gstorage_get_storage(sd->status.guild_id); + struct s_storage *gstor = guild2storage2(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); else { - storage_sortitem(gstor->items, ARRAYLENGTH(gstor->items)); - clif_storagelist(sd, gstor->items, ARRAYLENGTH(gstor->items)); - clif_updatestorageamount(sd, gstor->storage_amount, MAX_GUILD_STORAGE); + storage_sortitem(gstor->u.items_guild, ARRAYLENGTH(gstor->u.items_guild)); + clif_storagelist(sd, gstor->u.items_guild, ARRAYLENGTH(gstor->u.items_guild)); + clif_updatestorageamount(sd, gstor->amount, MAX_GUILD_STORAGE); } } } @@ -9674,12 +9677,12 @@ void clif_viewequip_ack(struct map_session_data* sd, struct map_session_data* ts for(i=0,n=0; i < MAX_INVENTORY; i++) { - if (tsd->status.inventory[i].nameid <= 0 || tsd->inventory_data[i] == NULL) // Item doesn't exist + if (tsd->inventory.u.items_inventory[i].nameid <= 0 || tsd->inventory_data[i] == NULL) // Item doesn't exist continue; if (!itemdb_isequip2(tsd->inventory_data[i])) // Is not equippable continue; // Add item info : refine, identify flag, element, etc. - clif_item_sub(WBUFP(buf,0), n*s+43,i + 2, &tsd->status.inventory[i], tsd->inventory_data[i], pc_equippoint(tsd, i)); + clif_item_sub(WBUFP(buf,0), n*s+43,i + 2, &tsd->inventory.u.items_inventory[i], tsd->inventory_data[i], pc_equippoint(tsd, i)); n++; } @@ -11222,7 +11225,7 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd) else if (pc_cant_act2(sd)) return; - if(!sd->status.inventory[index].identify) { + if(!sd->inventory.u.items_inventory[index].identify) { clif_equipitemack(sd,index,0,ITEM_EQUIP_ACK_FAIL); // fail return; } @@ -12312,8 +12315,8 @@ void clif_parse_ItemIdentify(int fd,struct map_session_data *sd) { // - Invalid item ID or item doesn't exist // - Item is already identified if (idx < 0 || idx >= MAX_INVENTORY || - sd->status.inventory[idx].nameid <= 0 || sd->inventory_data[idx] == NULL || - sd->status.inventory[idx].identify) {// cancel pressed + sd->inventory.u.items_inventory[idx].nameid <= 0 || sd->inventory_data[idx] == NULL || + sd->inventory.u.items_inventory[idx].identify) {// cancel pressed clif_menuskill_clear(sd); return; } @@ -12457,7 +12460,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) - gstorage_storageadd(sd, item_index, item_amount); + storage_guild_storageadd(sd, item_index, item_amount); } @@ -12476,7 +12479,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) - gstorage_storageget(sd, item_index, item_amount); + storage_guild_storageget(sd, item_index, item_amount); } @@ -12496,7 +12499,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) - gstorage_storageaddfromcart(sd, idx, amount); + storage_guild_storageaddfromcart(sd, idx, amount); } @@ -12516,7 +12519,7 @@ void clif_parse_MoveFromKafraToCart(int fd, struct map_session_data *sd){ storage_storagegettocart(sd, idx, amount); else if (sd->state.storage_flag == 2) - gstorage_storagegettocart(sd, idx, amount); + storage_guild_storagegettocart(sd, idx, amount); } @@ -12528,7 +12531,7 @@ void clif_parse_CloseKafra(int fd, struct map_session_data *sd) storage_storageclose(sd); else if( sd->state.storage_flag == 2 ) - gstorage_storageclose(sd); + storage_guild_storageclose(sd); } @@ -13857,7 +13860,7 @@ void clif_account_name(int fd, uint32 account_id, const char* accname) //! TODO: Figure out how does this actually work void clif_parse_GMReqAccountName(int fd, struct map_session_data *sd) { - int account_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); + uint32 account_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); /* char query[30]; safesnprintf(query,sizeof(query),"%d", account_id); @@ -15303,23 +15306,22 @@ void clif_parse_Auction_setitem(int fd, struct map_session_data *sd){ return; } - if( amount != 1 || amount > sd->status.inventory[idx].amount ) { // By client, amount is always set to 1. Maybe this is a future implementation. + if( amount != 1 || amount > sd->inventory.u.items_inventory[idx].amount ) { // By client, amount is always set to 1. Maybe this is a future implementation. ShowWarning("Character %s trying to set invalid amount in auctions.\n", sd->status.name); return; } - if( (item = itemdb_exists(sd->status.inventory[idx].nameid)) != NULL && !(item->type == IT_ARMOR || item->type == IT_PETARMOR || item->type == IT_WEAPON || item->type == IT_CARD || item->type == IT_ETC || item->type == IT_SHADOWGEAR) ) + if( (item = itemdb_exists(sd->inventory.u.items_inventory[idx].nameid)) != NULL && !(item->type == IT_ARMOR || item->type == IT_PETARMOR || item->type == IT_WEAPON || item->type == IT_CARD || item->type == IT_ETC || item->type == IT_SHADOWGEAR) ) { // Consumable or pets are not allowed clif_Auction_setitem(sd->fd, idx, true); return; } - if( !pc_can_give_items(sd) || sd->status.inventory[idx].expire_time || - !sd->status.inventory[idx].identify || - (sd->status.inventory[idx].bound && !pc_can_give_bounded_items(sd)) || - !itemdb_available(sd->status.inventory[idx].nameid) || - !itemdb_canauction(&sd->status.inventory[idx],pc_get_group_level(sd)) // Quest Item or something else - ) { + if( !pc_can_give_items(sd) || sd->inventory.u.items_inventory[idx].expire_time || + !sd->inventory.u.items_inventory[idx].identify || + (sd->inventory.u.items_inventory[idx].bound && !pc_can_give_bounded_items(sd)) || + !itemdb_available(sd->inventory.u.items_inventory[idx].nameid) || + !itemdb_canauction(&sd->inventory.u.items_inventory[idx],pc_get_group_level(sd)) ) { // Quest Item or something else clif_Auction_setitem(sd->fd, idx, true); return; } @@ -15398,7 +15400,7 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd) } // Auction checks... - if( sd->status.inventory[sd->auction.index].bound && !pc_can_give_bounded_items(sd) ) { + if( sd->inventory.u.items_inventory[sd->auction.index].bound && !pc_can_give_bounded_items(sd) ) { clif_displaymessage(sd->fd, msg_txt(sd,293)); clif_Auction_message(fd, 2); // The auction has been canceled return; @@ -15420,13 +15422,13 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd) auction.buyer_id = 0; memset(auction.buyer_name, '\0', sizeof(auction.buyer_name)); - if( sd->status.inventory[sd->auction.index].nameid == 0 || sd->status.inventory[sd->auction.index].amount < sd->auction.amount ) + if( sd->inventory.u.items_inventory[sd->auction.index].nameid == 0 || sd->inventory.u.items_inventory[sd->auction.index].amount < sd->auction.amount ) { clif_Auction_message(fd, 2); // The auction has been canceled return; } - if( (item = itemdb_exists(sd->status.inventory[sd->auction.index].nameid)) == NULL ) + if( (item = itemdb_exists(sd->inventory.u.items_inventory[sd->auction.index].nameid)) == NULL ) { // Just in case clif_Auction_message(fd, 2); // The auction has been canceled return; @@ -15434,7 +15436,7 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd) safestrncpy(auction.item_name, item->jname, sizeof(auction.item_name)); auction.type = item->type; - memcpy(&auction.item, &sd->status.inventory[sd->auction.index], sizeof(struct item)); + memcpy(&auction.item, &sd->inventory.u.items_inventory[sd->auction.index], sizeof(struct item)); auction.item.amount = 1; auction.timestamp = 0; @@ -17426,9 +17428,9 @@ int clif_spellbook_list(struct map_session_data *sd) for( i = 0, c = 0; i < MAX_INVENTORY; i ++ ) { - if( itemdb_is_spellbook2(sd->status.inventory[i].nameid) ) + if( itemdb_is_spellbook2(sd->inventory.u.items_inventory[i].nameid) ) { - WFIFOW(fd, c * 2 + 4) = sd->status.inventory[i].nameid; + WFIFOW(fd, c * 2 + 4) = sd->inventory.u.items_inventory[i].nameid; c++; } } @@ -17464,8 +17466,8 @@ int clif_magicdecoy_list(struct map_session_data *sd, uint16 skill_lv, short x, WFIFOW(fd,0) = 0x1ad; // This is the official packet. [pakpil] for( i = 0, c = 0; i < MAX_INVENTORY; i ++ ) { - if( itemdb_is_element(sd->status.inventory[i].nameid) ) { - WFIFOW(fd, c * 2 + 4) = sd->status.inventory[i].nameid; + if( itemdb_is_element(sd->inventory.u.items_inventory[i].nameid) ) { + WFIFOW(fd, c * 2 + 4) = sd->inventory.u.items_inventory[i].nameid; c ++; } } @@ -17497,8 +17499,8 @@ int clif_poison_list(struct map_session_data *sd, uint16 skill_lv) { WFIFOW(fd,0) = 0x1ad; // This is the official packet. [pakpil] for( i = 0, c = 0; i < MAX_INVENTORY; i ++ ) { - if( itemdb_is_poison(sd->status.inventory[i].nameid) ) { - WFIFOW(fd, c * 2 + 4) = sd->status.inventory[i].nameid; + if( itemdb_is_poison(sd->inventory.u.items_inventory[i].nameid) ) { + WFIFOW(fd, c * 2 + 4) = sd->inventory.u.items_inventory[i].nameid; c ++; } } @@ -17638,10 +17640,10 @@ void clif_parse_MoveItem(int fd, struct map_session_data *sd) { if (index < 0 || index >= MAX_INVENTORY) return; - if ( sd->status.inventory[index].favorite && type == 1 ) - sd->status.inventory[index].favorite = 0; + if ( sd->inventory.u.items_inventory[index].favorite && type == 1 ) + sd->inventory.u.items_inventory[index].favorite = 0; else if( type == 0 ) - sd->status.inventory[index].favorite = 1; + sd->inventory.u.items_inventory[index].favorite = 1; else return;/* nothing to do. */ @@ -17658,7 +17660,7 @@ void clif_favorite_item(struct map_session_data* sd, unsigned short index) { WFIFOHEAD(fd,packet_len(0x908)); WFIFOW(fd,0) = 0x908; WFIFOW(fd,2) = index+2; - WFIFOL(fd,4) = (sd->status.inventory[index].favorite == 1) ? 0 : 1; + WFIFOL(fd,4) = (sd->inventory.u.items_inventory[index].favorite == 1) ? 0 : 1; WFIFOSET(fd,packet_len(0x908)); } @@ -18471,7 +18473,7 @@ static bool clif_merge_item_has_pair(struct map_session_data *sd, struct item *i nullpo_retr(false, sd); - ARR_FIND(0, MAX_INVENTORY, i, (it_ = &sd->status.inventory[i]) && it->nameid == it_->nameid && it->bound == it_->bound && memcmp(it_, it, sizeof(struct item)) != 0); + ARR_FIND(0, MAX_INVENTORY, i, (it_ = &sd->inventory.u.items_inventory[i]) && it->nameid == it_->nameid && it->bound == it_->bound && memcmp(it_, it, sizeof(struct item)) != 0); if (i < MAX_INVENTORY) return true; @@ -18521,7 +18523,7 @@ void clif_merge_item_open(struct map_session_data *sd) { // Get entries for (i = 0; i < MAX_INVENTORY; i++) { - if (!clif_merge_item_check(sd->inventory_data[i], (it = &sd->status.inventory[i]))) + if (!clif_merge_item_check(sd->inventory_data[i], (it = &sd->inventory.u.items_inventory[i]))) continue; if (clif_merge_item_has_pair(sd, it)) indexes[n++] = i; @@ -18568,14 +18570,14 @@ void clif_parse_merge_item_req(int fd, struct map_session_data* sd) { for (i = 0, j = 0; i < n; i++) { unsigned short idx = RFIFOW(fd, info->pos[1] + i*2) - 2; - if (!clif_merge_item_check((id = sd->inventory_data[idx]), &sd->status.inventory[idx])) + if (!clif_merge_item_check((id = sd->inventory_data[idx]), &sd->inventory.u.items_inventory[idx])) continue; indexes[j] = idx; if (j && id->nameid != sd->inventory_data[indexes[0]]->nameid) { // Only can merge 1 kind at once clif_merge_item_ack(sd, 0, 0, MERGE_ITEM_FAILED_NOT_MERGE); return; } - count += sd->status.inventory[idx].amount; + count += sd->inventory.u.items_inventory[idx].amount; j++; } @@ -18591,13 +18593,13 @@ void clif_parse_merge_item_req(int fd, struct map_session_data* sd) { // Merrrrge!!!! for (i = 1; i < n; i++) { - unsigned short idx = indexes[i], amt = sd->status.inventory[idx].amount; - log_pick_pc(sd, LOG_TYPE_MERGE_ITEM, -amt, &sd->status.inventory[idx]); - memset(&sd->status.inventory[idx], 0, sizeof(sd->status.inventory[0])); + unsigned short idx = indexes[i], amt = sd->inventory.u.items_inventory[idx].amount; + log_pick_pc(sd, LOG_TYPE_MERGE_ITEM, -amt, &sd->inventory.u.items_inventory[idx]); + memset(&sd->inventory.u.items_inventory[idx], 0, sizeof(sd->inventory.u.items_inventory[0])); sd->inventory_data[idx] = NULL; clif_delitem(sd, idx, amt, 0); } - sd->status.inventory[indexes[0]].amount = count; + sd->inventory.u.items_inventory[indexes[0]].amount = count; clif_merge_item_ack(sd, indexes[0]+2, count, MERGE_ITEM_SUCCESS); } diff --git a/src/map/clif.h b/src/map/clif.h index ab5e34b13e..ecd2e065c6 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -10,8 +10,7 @@ struct Channel; struct item; -struct storage_data; -struct guild_storage; +struct s_storage; //#include "map.h" struct block_list; struct unit_data; diff --git a/src/map/guild.c b/src/map/guild.c index f13faacb16..8aa30ad1be 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -853,7 +853,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. - gstorage_storageclose(sd); + storage_guild_storageclose(sd); guild_send_dot_remove(sd); channel_pcquit(sd,3); //leave guild and ally chan sd->status.guild_id = 0; @@ -884,29 +884,35 @@ void guild_retrieveitembound(uint32 char_id, uint32 account_id, int guild_id) { int j; j = pc_bound_chk(sd,BOUND_GUILD,idxlist); if (j) { - struct guild_storage* stor = gstorage_guild2storage(sd->status.guild_id); + struct s_storage* stor = guild2storage(sd->status.guild_id); + struct guild *g = guild_search(guild_id); int i; - // 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); + if (stor && stor->status) { //Someone is in guild storage, close them + int i; + for (i = 0; i < g->max_member; i++) { + TBL_PC *pl_sd = g->member[i].sd; + if (pl_sd && pl_sd->state.storage_flag == 2) + storage_guild_storageclose(pl_sd); + } } 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_additem(sd,stor,&sd->inventory.u.items_inventory[idxlist[i]],sd->inventory.u.items_inventory[idxlist[i]].amount); + pc_delitem(sd,idxlist[i],sd->inventory.u.items_inventory[idxlist[i]].amount,0,4,LOG_TYPE_GSTORAGE); } - gstorage_storageclose(sd); //Close and save the storage + storage_guild_storageclose(sd); //Close and save the storage } } else { //Character is offline, ask char server to do the job - struct guild_storage* stor = gstorage_get_storage(guild_id); + struct s_storage* stor = guild2storage2(guild_id); struct guild *g = guild_search(guild_id); nullpo_retv(g); - 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); + if (stor && stor->status) { //Someone is in guild storage, close them + int i; + for (i = 0; i < g->max_member; i++) { + TBL_PC *pl_sd = g->member[i].sd; + if (pl_sd && pl_sd->state.storage_flag == 2) + storage_guild_storageclose(pl_sd); + } } intif_itembound_guild_retrieve(char_id,account_id,guild_id); } @@ -1701,7 +1707,7 @@ int guild_broken(int guild_id,int flag) { struct map_session_data *sd = g->member[i].sd; if(sd != NULL){ if(sd->state.storage_flag == 2) - gstorage_storage_quit(sd,1); + storage_guild_storage_quit(sd,1); sd->status.guild_id=0; sd->guild = NULL; sd->state.gmaster_flag = 0; @@ -1716,7 +1722,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); - gstorage_delete(guild_id); + storage_guild_delete(guild_id); if( channel_config.ally_enable ) { channel_delete(g->channel); } @@ -1859,7 +1865,7 @@ int guild_break(struct map_session_data *sd,char *name) { //Guild bound item check - Removes the bound flag j = pc_bound_chk(sd,BOUND_GUILD,idxlist); for(i = 0; i < j; i++) - pc_delitem(sd,idxlist[i],sd->status.inventory[idxlist[i]].amount,0,1,LOG_TYPE_BOUND_REMOVAL); + pc_delitem(sd,idxlist[i],sd->inventory.u.items_inventory[idxlist[i]].amount,0,1,LOG_TYPE_BOUND_REMOVAL); #endif intif_guild_break(g->guild_id); diff --git a/src/map/intif.c b/src/map/intif.c index 5d0b30ddec..af1c2b361e 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -21,10 +21,12 @@ #include "elemental.h" #include "mail.h" #include "quest.h" +#include "status.h" #include -static const int packet_len_table[]={ +/// Received packet Lengths from inter-server +static const int packet_len_table[] = { -1,-1,27,-1, -1, 0,37,-1, 10+NAME_LENGTH,-1, 0, 0, 0, 0, 0, 0, //0x3800-0x380f 0, 0, 0, 0, 0, 0, 0, 0, -1,11, 0, 0, 0, 0, 0, 0, //0x3810 39,-1,15,15, 14,19, 7,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3820 @@ -33,7 +35,7 @@ static const int packet_len_table[]={ -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 + 12,-1, 7, 3, 0, 0, 0, 0, 0, 0,-1, 8, 0, 0, 0, 0, //0x3880 Pet System, Storages -1,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3890 Homunculus [albator] }; @@ -52,6 +54,23 @@ int CheckForCharServer(void) return ((char_fd <= 0) || session[char_fd] == NULL || session[char_fd]->wdata == NULL); } +/** + * Get sd from pc_db (map_id2db) or auth_db (in case if parsing packet from inter-server when sd not added to pc_db yet) + * @param account_id + * @param char_id + * @return sd Found sd or NULL if not found + */ +struct map_session_data *inter_search_sd(uint32 account_id, uint32 char_id) +{ + struct map_session_data *sd = NULL; + struct auth_node *node = chrif_auth_check(account_id, char_id, ST_LOGIN); + if (node) + sd = node->sd; + else + sd = map_id2sd(account_id); + return sd; +} + /** * Request the char-serv to create a pet (to register it actually) * @param account_id @@ -493,40 +512,40 @@ int intif_request_registry(struct map_session_data *sd, int flag) /** * Request to load guild storage from char-serv - * @param account_id : Player account identification - * @param guild_id : Guild of player - * @return 0:error, 1=msg sent + * @param account_id: Player account identification + * @param guild_id: Guild of player + * @return false - error, true - message sent */ -int intif_request_guild_storage(uint32 account_id,int guild_id) +bool intif_request_guild_storage(uint32 account_id, int guild_id) { if (CheckForCharServer()) - return 0; + return false; WFIFOHEAD(inter_fd,10); WFIFOW(inter_fd,0) = 0x3018; WFIFOL(inter_fd,2) = account_id; WFIFOL(inter_fd,6) = guild_id; WFIFOSET(inter_fd,10); - return 1; + return true; } /** * Request to save guild storage - * @param account_id : account requesting the save - * @param gstor : Guild storage struct to save - * @return + * @param account_id: account requesting the save + * @param gstor: Guild storage struct to save + * @return false - error, true - message sent */ -int intif_send_guild_storage(uint32 account_id,struct guild_storage *gstor) +bool intif_send_guild_storage(uint32 account_id, struct s_storage *gstor) { if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,sizeof(struct guild_storage)+12); + return false; + WFIFOHEAD(inter_fd,sizeof(struct s_storage)+12); WFIFOW(inter_fd,0) = 0x3019; - WFIFOW(inter_fd,2) = (unsigned short)sizeof(struct guild_storage)+12; + WFIFOW(inter_fd,2) = (unsigned short)sizeof(struct s_storage)+12; WFIFOL(inter_fd,4) = account_id; - WFIFOL(inter_fd,8) = gstor->guild_id; - memcpy( WFIFOP(inter_fd,12),gstor, sizeof(struct guild_storage) ); + WFIFOL(inter_fd,8) = gstor->id; + memcpy( WFIFOP(inter_fd,12),gstor, sizeof(struct s_storage) ); WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); - return 1; + return true; } /** @@ -1410,7 +1429,7 @@ void intif_parse_Registers(int fd) */ int intif_parse_LoadGuildStorage(int fd) { - struct guild_storage *gstor; + struct s_storage *gstor; struct map_session_data *sd; int guild_id, flag; @@ -1426,12 +1445,12 @@ int intif_parse_LoadGuildStorage(int fd) return 0; } } - gstor = gstorage_guild2storage(guild_id); + gstor = guild2storage(guild_id); if (!gstor) { ShowWarning("intif_parse_LoadGuildStorage: error guild_id %d not exist\n",guild_id); return 0; } - if (gstor->opened) { // Already open.. lets ignore this update + if (gstor->status) { // 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; } @@ -1439,15 +1458,15 @@ int intif_parse_LoadGuildStorage(int fd) ShowWarning("intif_parse_LoadGuildStorage: received storage for an already modified non-saved storage! (User %d:%d)\n", flag?sd->status.account_id:1, flag?sd->status.char_id:1); return 0; } - 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->opened = 0; + if (RFIFOW(fd,2)-13 != sizeof(struct s_storage)) { + ShowError("intif_parse_LoadGuildStorage: data size error %d %d\n",RFIFOW(fd,2)-13 , sizeof(struct s_storage)); + gstor->status = false; return 0; } - memcpy(gstor,RFIFOP(fd,13),sizeof(struct guild_storage)); + memcpy(gstor,RFIFOP(fd,13),sizeof(struct s_storage)); if( flag ) - gstorage_storageopen(sd); + storage_guild_storageopen(sd); return 1; } @@ -1459,7 +1478,7 @@ int intif_parse_LoadGuildStorage(int fd) */ int intif_parse_SaveGuildStorage(int fd) { - gstorage_storagesaved(/*RFIFOL(fd,2), */RFIFOL(fd,6)); + storage_guild_storagesaved(/*RFIFOL(fd,2), */RFIFOL(fd,6)); return 1; } @@ -3056,7 +3075,7 @@ void intif_parse_broadcast_obtain_special_item(int fd) { * @param guild_id : Guild of char */ void intif_itembound_guild_retrieve(uint32 char_id,uint32 account_id,int guild_id) { - struct guild_storage *gstor = gstorage_get_storage(guild_id); + struct s_storage *gstor = guild2storage2(guild_id); if( CheckForCharServer() ) return; @@ -3068,7 +3087,7 @@ void intif_itembound_guild_retrieve(uint32 char_id,uint32 account_id,int guild_i WFIFOW(inter_fd,10) = guild_id; WFIFOSET(inter_fd,12); if (gstor) - gstor->locked = true; //Lock for retrieval process + gstor->lock = 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); } @@ -3080,21 +3099,21 @@ void intif_itembound_guild_retrieve(uint32 char_id,uint32 account_id,int guild_i */ void intif_parse_itembound_ack(int fd) { int guild_id = RFIFOW(fd,6); - struct guild_storage *gstor = gstorage_get_storage(guild_id); + struct s_storage *gstor = guild2storage(guild_id); if (gstor) - gstor->locked = false; //Unlock now that operation is completed + gstor->lock = 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] -*/ + * 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); + struct s_storage *gstor = guild2storage(guild_id); if (!gstor) { ShowError("intif_parse_itembound_store2gstorage: Guild '%d' not found.\n", guild_id); @@ -3106,16 +3125,193 @@ void intif_parse_itembound_store2gstorage(int fd) { struct item *item = (struct item*)RFIFOP(fd, 8 + i*sizeof(struct item)); if (!item) continue; - if (!gstorage_additem2(gstor, item, item->amount)) + if (!storage_guild_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; + gstor->lock = false; + gstor->status = false; } #endif -//----------------------------------------------------------------- +/** + * Receive inventory/cart/storage data for player + * IZ 0x388a .W .B .L .B .?B + * @param fd + */ +static bool intif_parse_StorageReceived(int fd) +{ + char type = RFIFOB(fd,4); + uint32 account_id = RFIFOL(fd, 5); + struct map_session_data *sd = map_id2sd(account_id); + struct s_storage *stor; //storage + size_t sz_stor = sizeof(struct s_storage); + + if (!sd) { + ShowError("intif_parse_StorageReceived: No player online for receiving inventory/cart/storage data (AID: %d)\n", account_id); + return false; + } + + if (!RFIFOB(fd, 9)) { + ShowError("intif_parse_StorageReceived: Failed to load! (AID: %d, type: %d)\n", account_id, type); + return false; + } + + switch (type) { + case TABLE_INVENTORY: stor = &sd->inventory; break; + case TABLE_STORAGE: stor = &sd->storage; break; + case TABLE_CART: stor = &sd->cart; break; + default: return false; + } + + if (stor->status) { // Already open.. lets ignore this update + ShowWarning("intif_parse_StorageReceived: storage received for a client already open (User %d:%d)\n", sd->status.account_id, sd->status.char_id); + return false; + } + if (stor->dirty) { // Already have storage, and it has been modified and not saved yet! Exploit! + ShowWarning("intif_parse_StorageReceived: received storage for an already modified non-saved storage! (User %d:%d)\n", sd->status.account_id, sd->status.char_id); + return false; + } + if (RFIFOW(fd,2)-10 != sz_stor) { + ShowError("intif_parse_StorageReceived: data size error %d %d\n",RFIFOW(fd,2)-10 , sz_stor); + stor->status = false; + return false; + } + + memcpy(stor, RFIFOP(fd,10), sz_stor); //copy the items data to correct destination + + switch (type) { + case TABLE_INVENTORY: { +#ifdef BOUND_ITEMS + int j, idxlist[MAX_INVENTORY]; +#endif + pc_setinventorydata(sd); + pc_setequipindex(sd); + pc_check_expiration(sd); + pc_check_available_item(sd, ITMCHK_INVENTORY); + pc_itemcd_do(sd, true); +#ifdef BOUND_ITEMS + // Party bound item check + if (sd->status.party_id == 0 && (j = pc_bound_chk(sd, BOUND_PARTY, idxlist))) { // Party was deleted while character offline + int i; + for (i = 0; i < j; i++) + pc_delitem(sd, idxlist[i], sd->inventory.u.items_inventory[idxlist[i]].amount, 0, 1, LOG_TYPE_OTHER); + } +#endif + //Set here because we need the inventory data for weapon sprite parsing. + status_set_viewdata(&sd->bl, sd->status.class_); + pc_load_combo(sd); + status_calc_weight(sd, 1|2); // Refresh item weight data + break; + } + + case TABLE_CART: + pc_check_available_item(sd, ITMCHK_CART); + status_calc_cart_weight(sd, 1|2); + if (sd->state.autotrade) { + clif_parse_LoadEndAck(sd->fd, sd); + sd->autotrade_tid = add_timer(gettick() + battle_config.feature_autotrade_open_delay, pc_autotrade_timer, sd->bl.id, 0); + } + break; + + case TABLE_STORAGE: + pc_check_available_item(sd, ITMCHK_STORAGE); + break; + } + return true; +} + +/** + * Save inventory/cart/storage data for a player + * IZ 0x388b .L .B .B + * @param fd + */ +static void intif_parse_StorageSaved(int fd) +{ + TBL_PC *sd = map_id2sd(RFIFOL(fd,2)); + + if (RFIFOB(fd, 6)) { + switch (RFIFOB(fd, 7)) { + case TABLE_INVENTORY: //inventory + //ShowInfo("Inventory has been saved (AID: %d).\n", RFIFOL(fd, 2)); + break; + case TABLE_STORAGE: //storage + if (sd && sd->state.storage_flag == 1) + sd->state.storage_flag = 0; + //ShowInfo("Storage has been saved (AID: %d).\n", RFIFOL(fd, 2)); + break; + case TABLE_CART: // cart + //ShowInfo("Cart has been saved (AID: %d).\n", RFIFOL(fd, 2)); + break; + default: + break; + } + } else + ShowError("Failed to save inventory/cart/storage data (AID: %d, type: %d).\n", RFIFOL(fd, 2), RFIFOB(fd, 7)); +} + +/** + * Request inventory/cart/storage data for a player + * ZI 0x308a .B .L .L + * @param sd: Player data + * @param type: Storage type + * @return false - error, true - message sent + */ +bool intif_storage_request(struct map_session_data *sd, enum storage_type type) +{ + if (CheckForCharServer()) + return false; + + WFIFOHEAD(inter_fd, 11); + WFIFOW(inter_fd, 0) = 0x308a; + WFIFOB(inter_fd, 2) = type; + WFIFOL(inter_fd, 3) = sd->status.account_id; + WFIFOL(inter_fd, 7) = sd->status.char_id; + WFIFOSET(inter_fd, 11); + return true; +} + +/** + * Request to save inventory/cart/storage data from player + * ZI 0x308b .W .B .L .L .?B + * @param sd: Player data + * @param type: Storage type + * @ return false - error, true - message sent + */ +bool intif_storage_save(struct map_session_data *sd, enum storage_type type) +{ + int stor_size = sizeof(struct s_storage); + struct s_storage *stor; + + nullpo_retr(false, sd); + + if (CheckForCharServer()) + return false; + + switch(type) { + case TABLE_INVENTORY: + stor = &sd->inventory; + break; + case TABLE_STORAGE: + stor = &sd->storage; + break; + case TABLE_CART: + stor = &sd->cart; + break; + default: + return false; + } + + WFIFOHEAD(inter_fd, stor_size+13); + WFIFOW(inter_fd, 0) = 0x308b; + WFIFOW(inter_fd, 2) = stor_size+13; + WFIFOB(inter_fd, 4) = type; + WFIFOL(inter_fd, 5) = sd->status.account_id; + WFIFOL(inter_fd, 9) = sd->status.char_id; + memcpy(WFIFOP(inter_fd, 13), stor, stor_size); + WFIFOSET(inter_fd, stor_size+13); + return true; +} /** * Communication from the inter server, Main entry point interface (inter<=>map) @@ -3229,7 +3425,11 @@ int intif_parse(int fd) case 0x3882: intif_parse_SavePetOk(fd); break; case 0x3883: intif_parse_DeletePetOk(fd); break; - // Homunculus + // Storage + case 0x388a: intif_parse_StorageReceived(fd); break; + case 0x388b: intif_parse_StorageSaved(fd); break; + + // Homunculus System case 0x3890: intif_parse_CreateHomunculus(fd); break; case 0x3891: intif_parse_RecvHomunculusData(fd); break; case 0x3892: intif_parse_SaveHomunculusOk(fd); break; @@ -3239,7 +3439,9 @@ int intif_parse(int fd) ShowError("intif_parse : unknown packet %d %x\n",fd,RFIFOW(fd,0)); return 0; } + // Skip packet RFIFOSKIP(fd,packet_len); + return 1; } diff --git a/src/map/intif.h b/src/map/intif.h index 5026ba5ff8..a2d108a4db 100644 --- a/src/map/intif.h +++ b/src/map/intif.h @@ -29,8 +29,8 @@ int intif_wis_message_to_gm(char *Wisp_name, int permission, char *mes); int intif_saveregistry(struct map_session_data *sd); int intif_request_registry(struct map_session_data *sd, int flag); -int intif_request_guild_storage(uint32 account_id, int guild_id); -int intif_send_guild_storage(uint32 account_id, struct guild_storage *gstor); +bool intif_request_guild_storage(uint32 account_id, int guild_id); +bool intif_send_guild_storage(uint32 account_id, struct s_storage *gstor); int intif_create_party(struct party_member *member,char *name,int item,int item2); int intif_request_partyinfo(int party_id, uint32 char_id); @@ -110,6 +110,10 @@ int intif_elemental_save(struct s_elemental *ele); int intif_request_accinfo(int u_fd, int aid, int group_lv, char* query, char type); +// STORAGE +bool intif_storage_request(struct map_session_data *sd, enum storage_type type); +bool intif_storage_save(struct map_session_data *sd, enum storage_type type); + int CheckForCharServer(void); #endif /* _INTIF_H_ */ diff --git a/src/map/itemdb.c b/src/map/itemdb.c index 74e1fb8236..91a79da598 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -1743,7 +1743,7 @@ void itemdb_reload(void) { for( sd = (struct map_session_data*)mapit_first(iter); mapit_exists(iter); sd = (struct map_session_data*)mapit_next(iter) ) { memset(sd->item_delay, 0, sizeof(sd->item_delay)); // reset item delays pc_setinventorydata(sd); - pc_check_available_item(sd); // Check for invalid(ated) items. + pc_check_available_item(sd, ITMCHK_ALL); // Check for invalid(ated) items. /* clear combo bonuses */ if( sd->combos.count ) { aFree(sd->combos.bonus); diff --git a/src/map/mail.c b/src/map/mail.c index e6550eb440..dd7da22640 100644 --- a/src/map/mail.c +++ b/src/map/mail.c @@ -83,16 +83,16 @@ bool mail_setitem(struct map_session_data *sd, short idx, uint32 amount) { if( idx < 0 || idx >= MAX_INVENTORY ) return false; - if( amount > sd->status.inventory[idx].amount ) + if( amount > sd->inventory.u.items_inventory[idx].amount ) return false; - if( !pc_can_give_items(sd) || sd->status.inventory[idx].expire_time - || !itemdb_available(sd->status.inventory[idx].nameid) - || !itemdb_canmail(&sd->status.inventory[idx],pc_get_group_level(sd)) - || (sd->status.inventory[idx].bound && !pc_can_give_bounded_items(sd)) ) + if( !pc_can_give_items(sd) || sd->inventory.u.items_inventory[idx].expire_time + || !itemdb_available(sd->inventory.u.items_inventory[idx].nameid) + || !itemdb_canmail(&sd->inventory.u.items_inventory[idx],pc_get_group_level(sd)) + || (sd->inventory.u.items_inventory[idx].bound && !pc_can_give_bounded_items(sd)) ) return false; sd->mail.index = idx; - sd->mail.nameid = sd->status.inventory[idx].nameid; + sd->mail.nameid = sd->inventory.u.items_inventory[idx].nameid; sd->mail.amount = amount; return true; } @@ -111,16 +111,16 @@ bool mail_setattachment(struct map_session_data *sd, struct mail_message *msg) n = sd->mail.index; if( sd->mail.amount ) { - if( sd->status.inventory[n].nameid != sd->mail.nameid ) + if( sd->inventory.u.items_inventory[n].nameid != sd->mail.nameid ) return false; - if( sd->status.inventory[n].amount < sd->mail.amount ) + if( sd->inventory.u.items_inventory[n].amount < sd->mail.amount ) return false; if( sd->weight > sd->max_weight ) return false; - memcpy(&msg->item, &sd->status.inventory[n], sizeof(struct item)); + memcpy(&msg->item, &sd->inventory.u.items_inventory[n], sizeof(struct item)); msg->item.amount = sd->mail.amount; } else diff --git a/src/map/map.c b/src/map/map.c index 8afcea2bc5..c52a16ed82 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -2066,8 +2066,6 @@ int map_quit(struct map_session_data *sd) { if (sd->ed) // Remove effects here rather than unit_remove_map_pc so we don't clear on Teleport/map change. elemental_clean_effect(sd->ed); - if( sd->state.storage_flag == 1 ) sd->state.storage_flag = 0; // No need to Double Save Storage on Quit. - if (sd->state.permanent_speed == 1) sd->state.permanent_speed = 0; // Remove lock so speed is set back to normal at login. if( map[sd->bl.m].instance_id ) @@ -4654,6 +4652,9 @@ int do_init(int argc, char *argv[]) rnd_init(); map_config_read(MAP_CONF_NAME); + if (save_settings == CHARSAVE_NONE) + ShowWarning("Value of 'save_settings' is not set, player's data only will be saved every 'autosave_time' (%d seconds).\n", autosave_interval/1000); + // loads npcs map_reloadnpc(false); diff --git a/src/map/npc.c b/src/map/npc.c index 7f9f224799..c63bc28b78 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -1527,8 +1527,8 @@ void npc_shop_currency_type(struct map_session_data *sd, struct npc_data *nd, in } for (i = 0; i < MAX_INVENTORY; i++) { - if (sd->status.inventory[i].nameid == id->nameid) - total += sd->status.inventory[i].amount; + if (sd->inventory.u.items_inventory[i].nameid == id->nameid) + total += sd->inventory.u.items_inventory[i].amount; } } @@ -1858,19 +1858,19 @@ static int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short* idx = item_list[i*2]-2; - script_setarray_pc(sd, "@sold_nameid", i, (void*)(intptr_t)sd->status.inventory[idx].nameid, &key_nameid); + script_setarray_pc(sd, "@sold_nameid", i, (void*)(intptr_t)sd->inventory.u.items_inventory[idx].nameid, &key_nameid); script_setarray_pc(sd, "@sold_quantity", i, (void*)(intptr_t)item_list[i*2+1], &key_amount); - if( itemdb_isequip(sd->status.inventory[idx].nameid) ) + if( itemdb_isequip(sd->inventory.u.items_inventory[idx].nameid) ) {// process equipment based information into the arrays - script_setarray_pc(sd, "@sold_refine", i, (void*)(intptr_t)sd->status.inventory[idx].refine, &key_refine); - script_setarray_pc(sd, "@sold_attribute", i, (void*)(intptr_t)sd->status.inventory[idx].attribute, &key_attribute); - script_setarray_pc(sd, "@sold_identify", i, (void*)(intptr_t)sd->status.inventory[idx].identify, &key_identify); + script_setarray_pc(sd, "@sold_refine", i, (void*)(intptr_t)sd->inventory.u.items_inventory[idx].refine, &key_refine); + script_setarray_pc(sd, "@sold_attribute", i, (void*)(intptr_t)sd->inventory.u.items_inventory[idx].attribute, &key_attribute); + script_setarray_pc(sd, "@sold_identify", i, (void*)(intptr_t)sd->inventory.u.items_inventory[idx].identify, &key_identify); for( j = 0; j < MAX_SLOTS; j++ ) {// store each of the cards from the equipment in the array snprintf(card_slot, sizeof(card_slot), "@sold_card%d", j + 1); - script_setarray_pc(sd, card_slot, i, (void*)(intptr_t)sd->status.inventory[idx].card[j], &key_card[j]); + script_setarray_pc(sd, card_slot, i, (void*)(intptr_t)sd->inventory.u.items_inventory[idx].card[j], &key_card[j]); } } } @@ -1916,9 +1916,9 @@ uint8 npc_selllist(struct map_session_data* sd, int n, unsigned short *item_list return 1; } - nameid = sd->status.inventory[idx].nameid; + nameid = sd->inventory.u.items_inventory[idx].nameid; - if( !nameid || !sd->inventory_data[idx] || sd->status.inventory[idx].amount < amount ) + if( !nameid || !sd->inventory_data[idx] || sd->inventory.u.items_inventory[idx].amount < amount ) { return 1; } @@ -1946,11 +1946,11 @@ uint8 npc_selllist(struct map_session_data* sd, int n, unsigned short *item_list idx = item_list[i*2]-2; amount = item_list[i*2+1]; - if( sd->inventory_data[idx]->type == IT_PETEGG && sd->status.inventory[idx].card[0] == CARD0_PET ) + if( sd->inventory_data[idx]->type == IT_PETEGG && sd->inventory.u.items_inventory[idx].card[0] == CARD0_PET ) { - if( search_petDB_index(sd->status.inventory[idx].nameid, PET_EGG) >= 0 ) + if( search_petDB_index(sd->inventory.u.items_inventory[idx].nameid, PET_EGG) >= 0 ) { - intif_delete_petdata(MakeDWord(sd->status.inventory[idx].card[1], sd->status.inventory[idx].card[2])); + intif_delete_petdata(MakeDWord(sd->inventory.u.items_inventory[idx].card[1], sd->inventory.u.items_inventory[idx].card[2])); } } diff --git a/src/map/party.c b/src/map/party.c index 0cf8b9f975..35a54395ac 100644 --- a/src/map/party.c +++ b/src/map/party.c @@ -626,7 +626,7 @@ int party_member_withdraw(int party_id, uint32 account_id, uint32 char_id) 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_BOUND_REMOVAL); + pc_delitem(sd,idxlist[i],sd->inventory.u.items_inventory[idxlist[i]].amount,0,1,LOG_TYPE_BOUND_REMOVAL); #endif sd->status.party_id = 0; diff --git a/src/map/pc.c b/src/map/pc.c index 3969cdd42c..d51b35af5d 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -475,18 +475,18 @@ void pc_inventory_rentals(struct map_session_data *sd) unsigned int expire_tick, next_tick = UINT_MAX; for( i = 0; i < MAX_INVENTORY; i++ ) { // Check for Rentals on Inventory - if( sd->status.inventory[i].nameid == 0 ) + if( sd->inventory.u.items_inventory[i].nameid == 0 ) continue; // Nothing here - if( sd->status.inventory[i].expire_time == 0 ) + if( sd->inventory.u.items_inventory[i].expire_time == 0 ) continue; - if( sd->status.inventory[i].expire_time <= time(NULL) ) { + if( sd->inventory.u.items_inventory[i].expire_time <= time(NULL) ) { if (sd->inventory_data[i]->unequip_script) run_script(sd->inventory_data[i]->unequip_script, 0, sd->bl.id, fake_nd->bl.id); - clif_rental_expired(sd->fd, i, sd->status.inventory[i].nameid); - pc_delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_OTHER); + clif_rental_expired(sd->fd, i, sd->inventory.u.items_inventory[i].nameid); + pc_delitem(sd, i, sd->inventory.u.items_inventory[i].amount, 0, 0, LOG_TYPE_OTHER); } else { - expire_tick = (unsigned int)(sd->status.inventory[i].expire_time - time(NULL)) * 1000; - clif_rental_time(sd->fd, sd->status.inventory[i].nameid, (int)(expire_tick / 1000)); + expire_tick = (unsigned int)(sd->inventory.u.items_inventory[i].expire_time - time(NULL)) * 1000; + clif_rental_time(sd->fd, sd->inventory.u.items_inventory[i].nameid, (int)(expire_tick / 1000)); next_tick = umin(expire_tick, next_tick); c++; } @@ -646,14 +646,14 @@ void pc_setinventorydata(struct map_session_data *sd) nullpo_retv(sd); for(i = 0; i < MAX_INVENTORY; i++) { - unsigned short id = sd->status.inventory[i].nameid; + unsigned short id = sd->inventory.u.items_inventory[i].nameid; sd->inventory_data[i] = id?itemdb_search(id):NULL; } } /** * 'Calculates' weapon type -* @param sd : player +* @param sd : Player */ void pc_calcweapontype(struct map_session_data *sd) { @@ -711,22 +711,22 @@ void pc_setequipindex(struct map_session_data *sd) sd->equip_index[i] = -1; for (i = 0; i < MAX_INVENTORY; i++) { - if (sd->status.inventory[i].nameid <= 0) + if (sd->inventory.u.items_inventory[i].nameid <= 0) continue; - if (sd->status.inventory[i].equip) { + if (sd->inventory.u.items_inventory[i].equip) { uint8 j; for (j = 0; j < EQI_MAX; j++) - if (sd->status.inventory[i].equip & equip_pos[j]) + if (sd->inventory.u.items_inventory[i].equip & equip_pos[j]) sd->equip_index[j] = i; - if (sd->status.inventory[i].equip & EQP_HAND_R) { + if (sd->inventory.u.items_inventory[i].equip & EQP_HAND_R) { if (sd->inventory_data[i]) sd->weapontype1 = sd->inventory_data[i]->look; else sd->weapontype1 = 0; } - if( sd->status.inventory[i].equip & EQP_HAND_L ) { + if( sd->inventory.u.items_inventory[i].equip & EQP_HAND_L ) { if( sd->inventory_data[i] && sd->inventory_data[i]->type == IT_WEAPON ) sd->weapontype2 = sd->inventory_data[i]->look; else @@ -740,7 +740,7 @@ void pc_setequipindex(struct map_session_data *sd) //static int pc_isAllowedCardOn(struct map_session_data *sd,int s,int eqindex,int flag) //{ // int i; -// struct item *item = &sd->status.inventory[eqindex]; +// struct item *item = &sd->inventory.u.items_inventory[eqindex]; // struct item_data *data; // // //Crafted/made/hatched items. @@ -779,7 +779,7 @@ bool pc_isequipped(struct map_session_data *sd, unsigned short nameid) if( sd->inventory_data[index]->nameid == nameid ) return true; for( j = 0; j < sd->inventory_data[index]->slot; j++ ){ - if( sd->status.inventory[index].card[j] == nameid ) + if( sd->inventory.u.items_inventory[index].card[j] == nameid ) return true; } } @@ -1018,10 +1018,6 @@ uint8 pc_isequip(struct map_session_data *sd,int n) bool pc_authok(struct map_session_data *sd, uint32 login_id2, time_t expiration_time, int group_id, struct mmo_charstatus *st, bool changing_mapservers) { int i; -#ifdef BOUND_ITEMS - int j; - int idxlist[MAX_INVENTORY]; -#endif unsigned long tick = gettick(); uint32 ip = session[sd->fd]->client_addr; @@ -1056,7 +1052,8 @@ bool pc_authok(struct map_session_data *sd, uint32 login_id2, time_t expiration_ sd->status.body = cap_value(sd->status.body,MIN_BODY_STYLE,MAX_BODY_STYLE); //Initializations to null/0 unneeded since map_session_data was filled with 0 upon allocation. - if(!sd->status.hp) pc_setdead(sd); + if (!sd->status.hp) + pc_setdead(sd); sd->state.connect_new = 1; sd->followtimer = INVALID_TIMER; // [MouseJstr] @@ -1106,8 +1103,7 @@ bool pc_authok(struct map_session_data *sd, uint32 login_id2, time_t expiration_ if (!(battle_config.display_skill_fail&2)) sd->state.showdelay = 1; - pc_setinventorydata(sd); - pc_setequipindex(sd); + pc_setequipindex(sd); // required at the moment, to complete auth_ok [lighta] if( sd->status.option&OPTION_INVISIBLE && !pc_can_use_command( sd, "hide", COMMAND_ATCOMMAND ) ){ sd->status.option &= ~OPTION_INVISIBLE; @@ -1116,8 +1112,7 @@ bool pc_authok(struct map_session_data *sd, uint32 login_id2, time_t expiration_ status_change_init(&sd->bl); sd->sc.option = sd->status.option; //This is the actual option used in battle. - //Set here because we need the inventory data for weapon sprite parsing. - status_set_viewdata(&sd->bl, sd->status.class_); + unit_dataset(&sd->bl); sd->guild_x = -1; @@ -1198,20 +1193,8 @@ bool pc_authok(struct map_session_data *sd, uint32 login_id2, time_t expiration_ clif_changemap(sd,sd->bl.m,sd->bl.x,sd->bl.y); } - /** - * Check if player have any item cooldowns on - **/ - pc_itemcd_do(sd,true); pc_validate_skill(sd); -#ifdef BOUND_ITEMS - // Party bound item check - if(sd->status.party_id == 0 && (j = pc_bound_chk(sd,BOUND_PARTY,idxlist))) { // Party was deleted while character offline - for(i=0;istatus.inventory[idxlist[i]].amount,0,1,LOG_TYPE_OTHER); - } -#endif - /* [Ind] */ sd->sc_display = NULL; sd->sc_display_count = 0; @@ -1282,6 +1265,8 @@ bool pc_set_hate_mob(struct map_session_data *sd, int pos, struct block_list *bl /*========================================== * Invoked once after the char/account/account2 registry variables are received. [Skotlex] + * We didn't receive item information at this point so DO NOT attempt to do item operations here. + * See intif_parse_StorageReceived() for item operations [lighta] *------------------------------------------*/ void pc_reg_received(struct map_session_data *sd) { @@ -1418,12 +1403,9 @@ void pc_reg_received(struct map_session_data *sd) clif_changeoption( &sd->bl ); } - pc_check_expiration(sd); - - if( sd->state.autotrade ) { - clif_parse_LoadEndAck(sd->fd, sd); - sd->autotrade_tid = add_timer(gettick() + battle_config.feature_autotrade_open_delay, pc_autotrade_timer, sd->bl.id, 0); - } + intif_storage_request(sd,TABLE_STORAGE); // Request storage data + intif_storage_request(sd,TABLE_CART); // Request cart data + intif_storage_request(sd,TABLE_INVENTORY); // Request inventory data } static int pc_calc_skillpoint(struct map_session_data* sd) @@ -2209,7 +2191,7 @@ void pc_delautobonus(struct map_session_data* sd, struct s_autobonus *autobonus, //Create a list of all equipped positions to see if all items needed for the autobonus are still present [Playtester] for(j = 0; j < EQI_MAX; j++) { if(sd->equip_index[j] >= 0) - equip_pos_idx |= sd->status.inventory[sd->equip_index[j]].equip; + equip_pos_idx |= sd->inventory.u.items_inventory[sd->equip_index[j]].equip; } if((equip_pos_idx&autobonus[i].pos) == autobonus[i].pos) script_run_autobonus(autobonus[i].bonus_script,sd,autobonus[i].pos); @@ -2243,7 +2225,7 @@ void pc_exeautobonus(struct map_session_data *sd,struct s_autobonus *autobonus) //Create a list of all equipped positions to see if all items needed for the autobonus are still present [Playtester] for(j = 0; j < EQI_MAX; j++) { if(sd->equip_index[j] >= 0) - equip_pos_idx |= sd->status.inventory[sd->equip_index[j]].equip; + equip_pos_idx |= sd->inventory.u.items_inventory[sd->equip_index[j]].equip; } if((equip_pos_idx&autobonus->pos) == autobonus->pos) script_run_autobonus(autobonus->other_script,sd,autobonus->pos); @@ -3959,31 +3941,31 @@ int pc_insert_card(struct map_session_data* sd, int idx_card, int idx_equip) return 0; //Invalid item index. if( idx_card < 0 || idx_card >= MAX_INVENTORY || sd->inventory_data[idx_card] == NULL ) return 0; //Invalid card index. - if( sd->status.inventory[idx_equip].nameid <= 0 || sd->status.inventory[idx_equip].amount < 1 ) + if( sd->inventory.u.items_inventory[idx_equip].nameid <= 0 || sd->inventory.u.items_inventory[idx_equip].amount < 1 ) return 0; // target item missing - if( sd->status.inventory[idx_card].nameid <= 0 || sd->status.inventory[idx_card].amount < 1 ) + if( sd->inventory.u.items_inventory[idx_card].nameid <= 0 || sd->inventory.u.items_inventory[idx_card].amount < 1 ) return 0; // target card missing if( sd->inventory_data[idx_equip]->type != IT_WEAPON && sd->inventory_data[idx_equip]->type != IT_ARMOR ) return 0; // only weapons and armor are allowed if( sd->inventory_data[idx_card]->type != IT_CARD ) return 0; // must be a card - if( sd->status.inventory[idx_equip].identify == 0 ) + if( sd->inventory.u.items_inventory[idx_equip].identify == 0 ) return 0; // target must be identified - if( itemdb_isspecial(sd->status.inventory[idx_equip].card[0]) ) + if( itemdb_isspecial(sd->inventory.u.items_inventory[idx_equip].card[0]) ) return 0; // card slots reserved for other purposes if( (sd->inventory_data[idx_equip]->equip & sd->inventory_data[idx_card]->equip) == 0 ) return 0; // card cannot be compounded on this item type if( sd->inventory_data[idx_equip]->type == IT_WEAPON && sd->inventory_data[idx_card]->equip == EQP_SHIELD ) return 0; // attempted to place shield card on left-hand weapon. - if( sd->status.inventory[idx_equip].equip != 0 ) + if( sd->inventory.u.items_inventory[idx_equip].equip != 0 ) return 0; // item must be unequipped - ARR_FIND( 0, sd->inventory_data[idx_equip]->slot, i, sd->status.inventory[idx_equip].card[i] == 0 ); + ARR_FIND( 0, sd->inventory_data[idx_equip]->slot, i, sd->inventory.u.items_inventory[idx_equip].card[i] == 0 ); if( i == sd->inventory_data[idx_equip]->slot ) return 0; // no free slots // remember the card id to insert - nameid = sd->status.inventory[idx_card].nameid; + nameid = sd->inventory.u.items_inventory[idx_card].nameid; if( pc_delitem(sd,idx_card,1,1,0,LOG_TYPE_OTHER) == 1 ) {// failed @@ -3991,9 +3973,9 @@ int pc_insert_card(struct map_session_data* sd, int idx_card, int idx_equip) } else {// success - log_pick_pc(sd, LOG_TYPE_OTHER, -1, &sd->status.inventory[idx_equip]); - sd->status.inventory[idx_equip].card[i] = nameid; - log_pick_pc(sd, LOG_TYPE_OTHER, 1, &sd->status.inventory[idx_equip]); + log_pick_pc(sd, LOG_TYPE_OTHER, -1, &sd->inventory.u.items_inventory[idx_equip]); + sd->inventory.u.items_inventory[idx_equip].card[i] = nameid; + log_pick_pc(sd, LOG_TYPE_OTHER, 1, &sd->inventory.u.items_inventory[idx_equip]); clif_insert_card(sd,idx_equip,idx_card,0); } @@ -4067,8 +4049,8 @@ char pc_checkadditem(struct map_session_data *sd, unsigned short nameid, int amo for(i=0;istatus.inventory[i].nameid==nameid){ - if( amount > MAX_AMOUNT - sd->status.inventory[i].amount || ( data->stack.inventory && amount > data->stack.amount - sd->status.inventory[i].amount ) ) + if(sd->inventory.u.items_inventory[i].nameid == nameid){ + if( amount > MAX_AMOUNT - sd->inventory.u.items_inventory[i].amount || ( data->stack.inventory && amount > data->stack.amount - sd->inventory.u.items_inventory[i].amount ) ) return CHKADDITEM_OVERAMOUNT; return CHKADDITEM_EXIST; } @@ -4090,7 +4072,7 @@ uint8 pc_inventoryblank(struct map_session_data *sd) nullpo_ret(sd); for(i = 0, b = 0; i < MAX_INVENTORY; i++){ - if(sd->status.inventory[i].nameid==0) + if(sd->inventory.u.items_inventory[i].nameid == 0) b++; } @@ -4301,7 +4283,7 @@ short pc_search_inventory(struct map_session_data *sd, unsigned short nameid) { short i; nullpo_retr(-1, sd); - ARR_FIND( 0, MAX_INVENTORY, i, sd->status.inventory[i].nameid == nameid && (sd->status.inventory[i].amount > 0 || nameid == 0) ); + ARR_FIND( 0, MAX_INVENTORY, i, sd->inventory.u.items_inventory[i].nameid == nameid && (sd->inventory.u.items_inventory[i].amount > 0 || nameid == 0) ); return ( i < MAX_INVENTORY ) ? i : -1; } @@ -4352,16 +4334,14 @@ char pc_additem(struct map_session_data *sd,struct item *item,int amount,e_log_p // Stackable | Non Rental if( itemdb_isstackable2(id) && item->expire_time == 0 ) { for( i = 0; i < MAX_INVENTORY; i++ ) { - if( sd->status.inventory[i].nameid == item->nameid && - sd->status.inventory[i].bound == item->bound && - sd->status.inventory[i].expire_time == 0 && - sd->status.inventory[i].unique_id == item->unique_id && - memcmp(&sd->status.inventory[i].card, &item->card, sizeof(item->card)) == 0 - ) - { - if( amount > MAX_AMOUNT - sd->status.inventory[i].amount || ( id->stack.inventory && amount > id->stack.amount - sd->status.inventory[i].amount ) ) + if( sd->inventory.u.items_inventory[i].nameid == item->nameid && + sd->inventory.u.items_inventory[i].bound == item->bound && + sd->inventory.u.items_inventory[i].expire_time == 0 && + sd->inventory.u.items_inventory[i].unique_id == item->unique_id && + memcmp(&sd->inventory.u.items_inventory[i].card, &item->card, sizeof(item->card)) == 0 ) { + if( amount > MAX_AMOUNT - sd->inventory.u.items_inventory[i].amount || ( id->stack.inventory && amount > id->stack.amount - sd->inventory.u.items_inventory[i].amount ) ) return ADDITEM_OVERAMOUNT; - sd->status.inventory[i].amount += amount; + sd->inventory.u.items_inventory[i].amount += amount; clif_additem(sd,i,amount,0); break; } @@ -4373,24 +4353,24 @@ char pc_additem(struct map_session_data *sd,struct item *item,int amount,e_log_p if( i < 0 ) return ADDITEM_OVERITEM; - memcpy(&sd->status.inventory[i], item, sizeof(sd->status.inventory[0])); + memcpy(&sd->inventory.u.items_inventory[i], item, sizeof(sd->inventory.u.items_inventory[0])); // clear equip and favorite fields first, just in case if( item->equip ) - sd->status.inventory[i].equip = 0; + sd->inventory.u.items_inventory[i].equip = 0; if( item->favorite ) - sd->status.inventory[i].favorite = 0; + sd->inventory.u.items_inventory[i].favorite = 0; - sd->status.inventory[i].amount = amount; + sd->inventory.u.items_inventory[i].amount = amount; sd->inventory_data[i] = id; sd->last_addeditem_index = i; if (!itemdb_isstackable2(id) || id->flag.guid) - sd->status.inventory[i].unique_id = item->unique_id ? item->unique_id : pc_generate_unique_id(sd); + sd->inventory.u.items_inventory[i].unique_id = item->unique_id ? item->unique_id : pc_generate_unique_id(sd); clif_additem(sd,i,amount,0); } - log_pick_pc(sd, log_type, amount, &sd->status.inventory[i]); + log_pick_pc(sd, log_type, amount, &sd->inventory.u.items_inventory[i]); sd->weight += w; clif_updatestatus(sd,SP_WEIGHT); @@ -4401,11 +4381,11 @@ char pc_additem(struct map_session_data *sd,struct item *item,int amount,e_log_p /* rental item check */ if( item->expire_time ) { if( time(NULL) > item->expire_time ) { - clif_rental_expired(sd->fd, i, sd->status.inventory[i].nameid); - pc_delitem(sd, i, sd->status.inventory[i].amount, 1, 0, LOG_TYPE_OTHER); + clif_rental_expired(sd->fd, i, sd->inventory.u.items_inventory[i].nameid); + pc_delitem(sd, i, sd->inventory.u.items_inventory[i].amount, 1, 0, LOG_TYPE_OTHER); } else { unsigned int seconds = (unsigned int)( item->expire_time - time(NULL) ); - clif_rental_time(sd->fd, sd->status.inventory[i].nameid, seconds); + clif_rental_time(sd->fd, sd->inventory.u.items_inventory[i].nameid, seconds); pc_inventory_rental_add(sd, seconds); } } @@ -4427,17 +4407,17 @@ char pc_delitem(struct map_session_data *sd,int n,int amount,int type, short rea { nullpo_retr(1, sd); - if(n < 0 || sd->status.inventory[n].nameid==0 || amount <= 0 || sd->status.inventory[n].amountinventory_data[n] == NULL) + if(n < 0 || sd->inventory.u.items_inventory[n].nameid == 0 || amount <= 0 || sd->inventory.u.items_inventory[n].amountinventory_data[n] == NULL) return 1; - log_pick_pc(sd, log_type, -amount, &sd->status.inventory[n]); + log_pick_pc(sd, log_type, -amount, &sd->inventory.u.items_inventory[n]); - sd->status.inventory[n].amount -= amount; + sd->inventory.u.items_inventory[n].amount -= amount; sd->weight -= sd->inventory_data[n]->weight*amount ; - if( sd->status.inventory[n].amount <= 0 ){ - if(sd->status.inventory[n].equip) + if( sd->inventory.u.items_inventory[n].amount <= 0 ){ + if(sd->inventory.u.items_inventory[n].equip) pc_unequipitem(sd,n,3); - memset(&sd->status.inventory[n],0,sizeof(sd->status.inventory[0])); + memset(&sd->inventory.u.items_inventory[n],0,sizeof(sd->inventory.u.items_inventory[0])); sd->inventory_data[n] = NULL; } if(!(type&1)) @@ -4465,9 +4445,9 @@ bool pc_dropitem(struct map_session_data *sd,int n,int amount) if(amount <= 0) return false; - if(sd->status.inventory[n].nameid <= 0 || - sd->status.inventory[n].amount <= 0 || - sd->status.inventory[n].amount < amount || + if(sd->inventory.u.items_inventory[n].nameid <= 0 || + sd->inventory.u.items_inventory[n].amount <= 0 || + sd->inventory.u.items_inventory[n].amount < amount || sd->state.trading || sd->state.vending || !sd->inventory_data[n] //pc_delitem would fail on this case. ) @@ -4479,13 +4459,13 @@ bool pc_dropitem(struct map_session_data *sd,int n,int amount) return false; //Can't drop items in nodrop mapflag maps. } - if( !pc_candrop(sd,&sd->status.inventory[n]) ) + if( !pc_candrop(sd,&sd->inventory.u.items_inventory[n]) ) { clif_displaymessage (sd->fd, msg_txt(sd,263)); return false; } - if (!map_addflooritem(&sd->status.inventory[n], amount, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 2, 0)) + if (!map_addflooritem(&sd->inventory.u.items_inventory[n], amount, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 2, 0)) return false; pc_delitem(sd, n, amount, 1, 0, LOG_TYPE_PICKDROP_PLAYER); @@ -4582,7 +4562,7 @@ bool pc_isUseitem(struct map_session_data *sd,int n) nullpo_ret(sd); item = sd->inventory_data[n]; - nameid = sd->status.inventory[n].nameid; + nameid = sd->inventory.u.items_inventory[n].nameid; if( item == NULL ) return false; @@ -4775,7 +4755,7 @@ int pc_useitem(struct map_session_data *sd,int n) return 0; #endif } - item = sd->status.inventory[n]; + item = sd->inventory.u.items_inventory[n]; id = sd->inventory_data[n]; if (item.nameid == 0 || item.amount <= 0) @@ -4889,17 +4869,14 @@ unsigned char pc_cart_additem(struct map_session_data *sd,struct item *item,int if( (w = data->weight*amount) + sd->cart_weight > sd->cart_weight_max ) return 1; - // ID no longer points to inventory/kafra ID. While we get a new one we don't want to mess up vending creation. - item->id = 0; - i = MAX_CART; if( itemdb_isstackable2(data) && !item->expire_time ) { for (i = 0; i < MAX_CART; i++) { - if (sd->status.cart[i].nameid == item->nameid - && sd->status.cart[i].bound == item->bound - && sd->status.cart[i].unique_id == item->unique_id - && memcmp(sd->status.cart[i].card, item->card, sizeof(item->card)) == 0 + if (sd->cart.u.items_cart[i].nameid == item->nameid + && sd->cart.u.items_cart[i].bound == item->bound + && sd->cart.u.items_cart[i].unique_id == item->unique_id + && memcmp(sd->cart.u.items_cart[i].card, item->card, sizeof(item->card)) == 0 ) break; } @@ -4907,25 +4884,25 @@ unsigned char pc_cart_additem(struct map_session_data *sd,struct item *item,int if( i < MAX_CART ) {// item already in cart, stack it - if( amount > MAX_AMOUNT - sd->status.cart[i].amount || ( data->stack.cart && amount > data->stack.amount - sd->status.cart[i].amount ) ) + if( amount > MAX_AMOUNT - sd->cart.u.items_cart[i].amount || ( data->stack.cart && amount > data->stack.amount - sd->cart.u.items_cart[i].amount ) ) return 2; // no slot - sd->status.cart[i].amount+=amount; + sd->cart.u.items_cart[i].amount += amount; clif_cart_additem(sd,i,amount,0); } else {// item not stackable or not present, add it - ARR_FIND( 0, MAX_CART, i, sd->status.cart[i].nameid == 0 ); + ARR_FIND( 0, MAX_CART, i, sd->cart.u.items_cart[i].nameid == 0 ); if( i == MAX_CART ) return 2; // no slot - memcpy(&sd->status.cart[i],item,sizeof(sd->status.cart[0])); - sd->status.cart[i].amount=amount; + memcpy(&sd->cart.u.items_cart[i],item,sizeof(sd->cart.u.items_cart[0])); + sd->cart.u.items_cart[i].amount = amount; sd->cart_num++; clif_cart_additem(sd,i,amount,0); } - sd->status.cart[i].favorite = 0;/* clear */ - log_pick_pc(sd, log_type, amount, &sd->status.cart[i]); + sd->cart.u.items_cart[i].favorite = 0; // clear + log_pick_pc(sd, log_type, amount, &sd->cart.u.items_cart[i]); sd->cart_weight += w; clif_updatestatus(sd,SP_CARTINFO); @@ -4940,16 +4917,16 @@ void pc_cart_delitem(struct map_session_data *sd,int n,int amount,int type,e_log { nullpo_retv(sd); - if(sd->status.cart[n].nameid == 0 || - sd->status.cart[n].amountcart.u.items_cart[n].nameid == 0 || + sd->cart.u.items_cart[n].amount < amount) return; - log_pick_pc(sd, log_type, -amount, &sd->status.cart[n]); + log_pick_pc(sd, log_type, -amount, &sd->cart.u.items_cart[n]); - sd->status.cart[n].amount -= amount; - sd->cart_weight -= itemdb_weight(sd->status.cart[n].nameid)*amount ; - if(sd->status.cart[n].amount <= 0){ - memset(&sd->status.cart[n],0,sizeof(sd->status.cart[0])); + sd->cart.u.items_cart[n].amount -= amount; + sd->cart_weight -= itemdb_weight(sd->cart.u.items_cart[n].nameid) * amount; + if(sd->cart.u.items_cart[n].amount <= 0) { + memset(&sd->cart.u.items_cart[n],0,sizeof(sd->cart.u.items_cart[0])); sd->cart_num--; } if(!type) { @@ -4971,7 +4948,7 @@ void pc_putitemtocart(struct map_session_data *sd,int idx,int amount) if (idx < 0 || idx >= MAX_INVENTORY) //Invalid index check [Skotlex] return; - item_data = &sd->status.inventory[idx]; + item_data = &sd->inventory.u.items_inventory[idx]; if( item_data->nameid == 0 || amount < 1 || item_data->amount < amount || sd->state.vending ) return; @@ -4996,7 +4973,7 @@ int pc_cartitem_amount(struct map_session_data* sd, int idx, int amount) nullpo_retr(-1, sd); - item_data = &sd->status.cart[idx]; + item_data = &sd->cart.u.items_cart[idx]; if( item_data->nameid == 0 || item_data->amount == 0 ) return -1; @@ -5016,7 +4993,7 @@ void pc_getitemfromcart(struct map_session_data *sd,int idx,int amount) if (idx < 0 || idx >= MAX_CART) //Invalid index check [Skotlex] return; - item_data=&sd->status.cart[idx]; + item_data=&sd->cart.u.items_cart[idx]; if(item_data->nameid == 0 || amount < 1 || item_data->amount < amount || sd->state.vending ) return; @@ -5038,9 +5015,9 @@ void pc_getitemfromcart(struct map_session_data *sd,int idx,int amount) *------------------------------------------*/ int pc_bound_chk(TBL_PC *sd,enum bound_type type,int *idxlist) { - int i=0, j=0; - for(i=0;istatus.inventory[i].nameid > 0 && sd->status.inventory[i].amount > 0 && sd->status.inventory[i].bound == type) { + int i = 0, j = 0; + for(i = 0; i < MAX_INVENTORY; i++) { + if(sd->inventory.u.items_inventory[i].nameid > 0 && sd->inventory.u.items_inventory[i].amount > 0 && sd->inventory.u.items_inventory[i].bound == type) { idxlist[j] = i; j++; } @@ -5603,7 +5580,7 @@ bool pc_checkequip2(struct map_session_data *sd, unsigned short nameid, int min, if(equip_pos[i]) { int idx = sd->equip_index[i]; - if (sd->status.inventory[idx].nameid == nameid) + if (sd->inventory.u.items_inventory[idx].nameid == nameid) return true; } } @@ -7602,8 +7579,8 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) int eq_num=0,eq_n[MAX_INVENTORY]; memset(eq_n,0,sizeof(eq_n)); for(i=0;istatus.inventory[i].equip) - || (type == 2 && sd->status.inventory[i].equip) + if( (type == 1 && !sd->inventory.u.items_inventory[i].equip) + || (type == 2 && sd->inventory.u.items_inventory[i].equip) || type == 3) { int l; @@ -7617,7 +7594,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) if(eq_num > 0){ int n = eq_n[rnd()%eq_num]; if(rnd()%10000 < per) { - if(sd->status.inventory[n].equip) + if(sd->inventory.u.items_inventory[n].equip) pc_unequipitem(sd,n,3); pc_dropitem(sd,n,1); } @@ -7625,12 +7602,12 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) } else if(id > 0) { for(i=0;istatus.inventory[i].nameid == id + if(sd->inventory.u.items_inventory[i].nameid == id && rnd()%10000 < per - && ((type == 1 && !sd->status.inventory[i].equip) - || (type == 2 && sd->status.inventory[i].equip) + && ((type == 1 && !sd->inventory.u.items_inventory[i].equip) + || (type == 2 && sd->inventory.u.items_inventory[i].equip) || type == 3) ){ - if(sd->status.inventory[i].equip) + if(sd->inventory.u.items_inventory[i].equip) pc_unequipitem(sd,i,3); pc_dropitem(sd,i,1); break; @@ -9216,16 +9193,16 @@ static int pc_checkcombo(struct map_session_data *sd, struct item_data *data) { continue; } combo_idx[j].idx = index; - pos |= sd->status.inventory[index].equip; + pos |= sd->inventory.u.items_inventory[index].equip; found = true; break; } else { //Cards uint16 z; - if ( sd->inventory_data[index]->slot == 0 || itemdb_isspecial(sd->status.inventory[index].card[0]) ) + if ( sd->inventory_data[index]->slot == 0 || itemdb_isspecial(sd->inventory.u.items_inventory[index].card[0]) ) continue; for (z = 0; z < sd->inventory_data[index]->slot; z++) { bool do_continue=false; - if (sd->status.inventory[index].card[z] != id) + if (sd->inventory.u.items_inventory[index].card[z] != id) continue; if(j>0){ int c1, c2; @@ -9244,7 +9221,7 @@ static int pc_checkcombo(struct map_session_data *sd, struct item_data *data) { continue; combo_idx[j].idx = index; combo_idx[j].card[z] = id; - pos |= sd->status.inventory[index].equip; + pos |= sd->inventory.u.items_inventory[index].equip; found = true; break; } @@ -9350,13 +9327,13 @@ int pc_load_combo(struct map_session_data *sd) { continue; if( id->combos_count ) ret += pc_checkcombo(sd,id); - if(!itemdb_isspecial(sd->status.inventory[idx].card[0])) { + if(!itemdb_isspecial(sd->inventory.u.items_inventory[idx].card[0])) { struct item_data *data; int j; for( j = 0; j < id->slot; j++ ) { - if (!sd->status.inventory[idx].card[j]) + if (!sd->inventory.u.items_inventory[idx].card[j]) continue; - if ( ( data = itemdb_exists(sd->status.inventory[idx].card[j]) ) != NULL ) { + if ( ( data = itemdb_exists(sd->inventory.u.items_inventory[idx].card[j]) ) != NULL ) { if( data->combos_count ) ret += pc_checkcombo(sd,data); } @@ -9391,14 +9368,14 @@ bool pc_equipitem(struct map_session_data *sd,short n,int req_pos) pos = pc_equippoint(sd,n); //With a few exceptions, item should go in all specified slots. if(battle_config.battle_log) - ShowInfo("equip %hu(%d) %x:%x\n",sd->status.inventory[n].nameid,n,id?id->equip:0,req_pos); + ShowInfo("equip %hu (%d) %x:%x\n",sd->inventory.u.items_inventory[n].nameid,n,id?id->equip:0,req_pos); if((res = pc_isequip(sd,n))) { clif_equipitemack(sd,n,0,res); // fail return false; } - if (!(pos&req_pos) || sd->status.inventory[n].equip != 0 || sd->status.inventory[n].attribute==1 ) { // [Valaris] + if (!(pos&req_pos) || sd->inventory.u.items_inventory[n].equip != 0 || sd->inventory.u.items_inventory[n].attribute==1 ) { // [Valaris] clif_equipitemack(sd,n,0,ITEM_EQUIP_ACK_FAIL); // fail return false; } @@ -9440,8 +9417,8 @@ bool pc_equipitem(struct map_session_data *sd,short n,int req_pos) } } - if (id->flag.bindOnEquip && !sd->status.inventory[n].bound) { - sd->status.inventory[n].bound = (char)battle_config.default_bind_on_equip; + if (id->flag.bindOnEquip && !sd->inventory.u.items_inventory[n].bound) { + sd->inventory.u.items_inventory[n].bound = (char)battle_config.default_bind_on_equip; clif_notify_bindOnEquip(sd,n); } @@ -9488,7 +9465,7 @@ bool pc_equipitem(struct map_session_data *sd,short n,int req_pos) else clif_equipitemack(sd,n,pos,ITEM_EQUIP_ACK_OK); - sd->status.inventory[n].equip=pos; + sd->inventory.u.items_inventory[n].equip = pos; if(pos & EQP_HAND_R) { if(id) @@ -9576,14 +9553,14 @@ bool pc_equipitem(struct map_session_data *sd,short n,int req_pos) /* check for combos (MUST be before status_calc_pc) */ if( id->combos_count ) pc_checkcombo(sd,id); - if(itemdb_isspecial(sd->status.inventory[n].card[0])) + if(itemdb_isspecial(sd->inventory.u.items_inventory[n].card[0])) ; //No cards else { for( i = 0; i < id->slot; i++ ) { struct item_data *data; - if (!sd->status.inventory[n].card[i]) + if (!sd->inventory.u.items_inventory[n].card[i]) continue; - if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) { + if ( ( data = itemdb_exists(sd->inventory.u.items_inventory[n].card[i]) ) != NULL ) { if( data->combos_count ) pc_checkcombo(sd,data); } @@ -9599,14 +9576,14 @@ bool pc_equipitem(struct map_session_data *sd,short n,int req_pos) //only run the script if item isn't restricted if (id->equip_script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) || !itemdb_isNoEquip(id,sd->bl.m))) run_script(id->equip_script,0,sd->bl.id,fake_nd->bl.id); - if(itemdb_isspecial(sd->status.inventory[n].card[0])) + if(itemdb_isspecial(sd->inventory.u.items_inventory[n].card[0])) ; //No cards else { for( i = 0; i < id->slot; i++ ) { struct item_data *data; - if (!sd->status.inventory[n].card[i]) + if (!sd->inventory.u.items_inventory[n].card[i]) continue; - if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) { + if ( ( data = itemdb_exists(sd->inventory.u.items_inventory[n].card[i]) ) != NULL ) { if (data->equip_script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) || !itemdb_isNoEquip(data,sd->bl.m))) run_script(data->equip_script,0,sd->bl.id,fake_nd->bl.id); } @@ -9636,7 +9613,7 @@ bool pc_unequipitem(struct map_session_data *sd, int n, int flag) { clif_unequipitemack(sd,0,0,0); return false; } - if (!sd->status.inventory[n].equip) { + if (!sd->inventory.u.items_inventory[n].equip) { clif_unequipitemack(sd,n,0,0); return false; //Nothing to unequip } @@ -9654,14 +9631,18 @@ bool pc_unequipitem(struct map_session_data *sd, int n, int flag) { } if (battle_config.battle_log) - ShowInfo("unequip %d %x:%x\n",n,pc_equippoint(sd,n),sd->status.inventory[n].equip); + ShowInfo("unequip %d %x:%x\n",n,pc_equippoint(sd,n),sd->inventory.u.items_inventory[n].equip); + if (!sd->inventory.u.items_inventory[n].equip) { //Nothing to unequip + clif_unequipitemack(sd, n, 0, 0); + return false; + } for(i = 0; i < EQI_MAX; i++) { - if (sd->status.inventory[n].equip & equip_pos[i]) + if (sd->inventory.u.items_inventory[n].equip & equip_pos[i]) sd->equip_index[i] = -1; } - if(sd->status.inventory[n].equip & EQP_HAND_R) { + if(sd->inventory.u.items_inventory[n].equip & EQP_HAND_R) { sd->weapontype1 = 0; sd->status.weapon = sd->weapontype2; pc_calcweapontype(sd); @@ -9669,57 +9650,57 @@ bool pc_unequipitem(struct map_session_data *sd, int n, int flag) { if( !battle_config.dancing_weaponswitch_fix ) status_change_end(&sd->bl, SC_DANCING, INVALID_TIMER); // Unequipping => stop dancing. } - if(sd->status.inventory[n].equip & EQP_HAND_L) { + if(sd->inventory.u.items_inventory[n].equip & EQP_HAND_L) { sd->status.shield = sd->weapontype2 = 0; pc_calcweapontype(sd); clif_changelook(&sd->bl,LOOK_SHIELD,sd->status.shield); } - if(sd->status.inventory[n].equip & EQP_HEAD_LOW && pc_checkequip(sd,EQP_COSTUME_HEAD_LOW) == -1 ) { + if(sd->inventory.u.items_inventory[n].equip & EQP_HEAD_LOW && pc_checkequip(sd,EQP_COSTUME_HEAD_LOW) == -1 ) { sd->status.head_bottom = 0; clif_changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom); } - if(sd->status.inventory[n].equip & EQP_HEAD_TOP && pc_checkequip(sd,EQP_COSTUME_HEAD_TOP) == -1 ) { + if(sd->inventory.u.items_inventory[n].equip & EQP_HEAD_TOP && pc_checkequip(sd,EQP_COSTUME_HEAD_TOP) == -1 ) { sd->status.head_top = 0; clif_changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top); } - if(sd->status.inventory[n].equip & EQP_HEAD_MID && pc_checkequip(sd,EQP_COSTUME_HEAD_MID) == -1 ) { + if(sd->inventory.u.items_inventory[n].equip & EQP_HEAD_MID && pc_checkequip(sd,EQP_COSTUME_HEAD_MID) == -1 ) { sd->status.head_mid = 0; clif_changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid); } - if(sd->status.inventory[n].equip & EQP_COSTUME_HEAD_TOP) { + if(sd->inventory.u.items_inventory[n].equip & EQP_COSTUME_HEAD_TOP) { sd->status.head_top = ( pc_checkequip(sd,EQP_HEAD_TOP) >= 0 ) ? sd->inventory_data[pc_checkequip(sd,EQP_HEAD_TOP)]->look : 0; clif_changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top); } - if(sd->status.inventory[n].equip & EQP_COSTUME_HEAD_MID) { + if(sd->inventory.u.items_inventory[n].equip & EQP_COSTUME_HEAD_MID) { sd->status.head_mid = ( pc_checkequip(sd,EQP_HEAD_MID) >= 0 ) ? sd->inventory_data[pc_checkequip(sd,EQP_HEAD_MID)]->look : 0; clif_changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid); } - if(sd->status.inventory[n].equip & EQP_COSTUME_HEAD_LOW) { + if(sd->inventory.u.items_inventory[n].equip & EQP_COSTUME_HEAD_LOW) { sd->status.head_bottom = ( pc_checkequip(sd,EQP_HEAD_LOW) >= 0 ) ? sd->inventory_data[pc_checkequip(sd,EQP_HEAD_LOW)]->look : 0; clif_changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom); } - if(sd->status.inventory[n].equip & EQP_SHOES) + if(sd->inventory.u.items_inventory[n].equip & EQP_SHOES) clif_changelook(&sd->bl,LOOK_SHOES,0); - if(sd->status.inventory[n].equip&EQP_GARMENT && pc_checkequip(sd,EQP_COSTUME_GARMENT) == -1) { + if(sd->inventory.u.items_inventory[n].equip&EQP_GARMENT && pc_checkequip(sd,EQP_COSTUME_GARMENT) == -1) { sd->status.robe = 0; clif_changelook(&sd->bl, LOOK_ROBE, 0); } - if(sd->status.inventory[n].equip & EQP_COSTUME_GARMENT) { + if(sd->inventory.u.items_inventory[n].equip & EQP_COSTUME_GARMENT) { sd->status.robe = ( pc_checkequip(sd,EQP_GARMENT) >= 0 ) ? sd->inventory_data[pc_checkequip(sd,EQP_GARMENT)]->look : 0; clif_changelook(&sd->bl,LOOK_ROBE,sd->status.robe); } - clif_unequipitemack(sd,n,sd->status.inventory[n].equip,1); + clif_unequipitemack(sd,n,sd->inventory.u.items_inventory[n].equip,1); status_change_end(&sd->bl,SC_HEAT_BARREL,INVALID_TIMER); // On weapon change (right and left hand) - if ((sd->status.inventory[n].equip & EQP_ARMS) && sd->inventory_data[n]->type == IT_WEAPON) { + if ((sd->inventory.u.items_inventory[n].equip & EQP_ARMS) && sd->inventory_data[n]->type == IT_WEAPON) { if (!sd->sc.data[SC_SEVENWIND] || sd->sc.data[SC_ASPERSIO]) //Check for seven wind (but not level seven!) skill_enchant_elemental_end(&sd->bl, SC_NONE); status_change_end(&sd->bl, SC_FEARBREEZE, INVALID_TIMER); @@ -9728,7 +9709,7 @@ bool pc_unequipitem(struct map_session_data *sd, int n, int flag) { } // On armor change - if (sd->status.inventory[n].equip & EQP_ARMOR) { + if (sd->inventory.u.items_inventory[n].equip & EQP_ARMOR) { if (sd->sc.data[SC_HOVERING] && sd->inventory_data[n]->nameid == ITEMID_HOVERING_BOOSTER) status_change_end(&sd->bl, SC_HOVERING, INVALID_TIMER); //status_change_end(&sd->bl, SC_BENEDICTIO, INVALID_TIMER); // No longer is removed? Need confirmation @@ -9739,10 +9720,10 @@ bool pc_unequipitem(struct map_session_data *sd, int n, int flag) { if (sd->inventory_data[n]->type == IT_AMMO) status_change_end(&sd->bl, SC_P_ALTER, INVALID_TIMER); - if( sd->state.autobonus&sd->status.inventory[n].equip ) - sd->state.autobonus &= ~sd->status.inventory[n].equip; //Check for activated autobonus [Inkfish] + if (sd->state.autobonus&sd->inventory.u.items_inventory[n].equip) + sd->state.autobonus &= ~sd->inventory.u.items_inventory[n].equip; //Check for activated autobonus [Inkfish] - sd->status.inventory[n].equip = 0; + sd->inventory.u.items_inventory[n].equip = 0; iflag = sd->npc_item_flag; /* check for combos (MUST be before status_calc_pc) */ @@ -9750,15 +9731,15 @@ bool pc_unequipitem(struct map_session_data *sd, int n, int flag) { if( sd->inventory_data[n]->combos_count ) { if( pc_removecombo(sd,sd->inventory_data[n]) ) status_cacl = true; - } if(itemdb_isspecial(sd->status.inventory[n].card[0])) + } if(itemdb_isspecial(sd->inventory.u.items_inventory[n].card[0])) ; //No cards else { for( i = 0; i < sd->inventory_data[n]->slot; i++ ) { struct item_data *data; - if (!sd->status.inventory[n].card[i]) + if (!sd->inventory.u.items_inventory[n].card[i]) continue; - if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) { + if ( ( data = itemdb_exists(sd->inventory.u.items_inventory[n].card[i]) ) != NULL ) { if( data->combos_count ) { if( pc_removecombo(sd,data) ) status_cacl = true; @@ -9780,15 +9761,15 @@ bool pc_unequipitem(struct map_session_data *sd, int n, int flag) { if (sd->inventory_data[n]) { if (sd->inventory_data[n]->unequip_script) run_script(sd->inventory_data[n]->unequip_script,0,sd->bl.id,fake_nd->bl.id); - if(itemdb_isspecial(sd->status.inventory[n].card[0])) + if(itemdb_isspecial(sd->inventory.u.items_inventory[n].card[0])) ; //No cards else { for( i = 0; i < sd->inventory_data[n]->slot; i++ ) { struct item_data *data; - if (!sd->status.inventory[n].card[i]) + if (!sd->inventory.u.items_inventory[n].card[i]) continue; - if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) { + if ( ( data = itemdb_exists(sd->inventory.u.items_inventory[n].card[i]) ) != NULL ) { if( data->unequip_script ) run_script(data->unequip_script,0,sd->bl.id,fake_nd->bl.id); } @@ -9814,10 +9795,10 @@ void pc_checkitem(struct map_session_data *sd) { if( sd->state.vending ) //Avoid reorganizing items when we are vending, as that leads to exploits (pointed out by End of Exam) return; - pc_check_available_item(sd); // Check for invalid(ated) items. + pc_check_available_item(sd, ITMCHK_NONE); // Check for invalid(ated) items. for( i = 0; i < MAX_INVENTORY; i++ ) { - it = sd->status.inventory[i]; + it = sd->inventory.u.items_inventory[i]; if( it.nameid == 0 ) continue; @@ -9844,8 +9825,13 @@ void pc_checkitem(struct map_session_data *sd) { /*========================================== * Checks for unavailable items and removes them. + * @param sd: Player data + * @param type Forced check: + * 1 - Inventory + * 2 - Cart + * 4 - Storage *------------------------------------------*/ -void pc_check_available_item(struct map_session_data *sd) +void pc_check_available_item(struct map_session_data *sd, uint8 type) { int i; unsigned short nameid; @@ -9853,57 +9839,57 @@ void pc_check_available_item(struct map_session_data *sd) nullpo_retv(sd); - if (battle_config.item_check&0x1) { // Check for invalid(ated) items in inventory. + if (battle_config.item_check&ITMCHK_INVENTORY || type&ITMCHK_INVENTORY) { // Check for invalid(ated) items in inventory. for(i = 0; i < MAX_INVENTORY; i++) { - nameid = sd->status.inventory[i].nameid; + nameid = sd->inventory.u.items_inventory[i].nameid; if (!nameid) continue; if (!itemdb_available(nameid)) { sprintf(output, msg_txt(sd, 709), nameid); // Item %hu has been removed from your inventory. clif_displaymessage(sd->fd, output); - ShowWarning("Removed invalid/disabled item id %hu from inventory (amount=%d, char_id=%d).\n", nameid, sd->status.inventory[i].amount, sd->status.char_id); - pc_delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_OTHER); + ShowWarning("Removed invalid/disabled item (ID: %hu, amount: %d) from inventory (char_id: %d).\n", nameid, sd->inventory.u.items_inventory[i].amount, sd->status.char_id); + pc_delitem(sd, i, sd->inventory.u.items_inventory[i].amount, 0, 0, LOG_TYPE_OTHER); continue; } - if (!sd->status.inventory[i].unique_id && !itemdb_isstackable(nameid)) - sd->status.inventory[i].unique_id = pc_generate_unique_id(sd); + if (!sd->inventory.u.items_inventory[i].unique_id && !itemdb_isstackable(nameid)) + sd->inventory.u.items_inventory[i].unique_id = pc_generate_unique_id(sd); } } - if (battle_config.item_check&0x2) { // Check for invalid(ated) items in cart. + if (battle_config.item_check&ITMCHK_CART || type&ITMCHK_CART) { // Check for invalid(ated) items in cart. for(i = 0; i < MAX_CART; i++) { - nameid = sd->status.cart[i].nameid; + nameid = sd->cart.u.items_cart[i].nameid; if (!nameid) continue; if (!itemdb_available(nameid)) { sprintf(output, msg_txt(sd, 710), nameid); // Item %hu has been removed from your cart. clif_displaymessage(sd->fd, output); - ShowWarning("Removed invalid/disabled item id %hu from cart (amount=%d, char_id=%d).\n", nameid, sd->status.cart[i].amount, sd->status.char_id); - pc_cart_delitem(sd, i, sd->status.cart[i].amount, 0, LOG_TYPE_OTHER); + ShowWarning("Removed invalid/disabled item (ID: %hu, amount: %d) from cart (char_id: %d).\n", nameid, sd->cart.u.items_cart[i].amount, sd->status.char_id); + pc_cart_delitem(sd, i, sd->cart.u.items_cart[i].amount, 0, LOG_TYPE_OTHER); continue; } - if (!sd->status.cart[i].unique_id && !itemdb_isstackable(nameid)) - sd->status.cart[i].unique_id = pc_generate_unique_id(sd); + if (!sd->cart.u.items_cart[i].unique_id && !itemdb_isstackable(nameid)) + sd->cart.u.items_cart[i].unique_id = pc_generate_unique_id(sd); } } - if (battle_config.item_check&0x4) { // Check for invalid(ated) items in storage. + if (battle_config.item_check&ITMCHK_STORAGE || type&ITMCHK_STORAGE) { // Check for invalid(ated) items in storage. for(i = 0; i < sd->storage_size; i++) { - nameid = sd->status.storage.items[i].nameid; + nameid = sd->storage.u.items_storage[i].nameid; if (!nameid) continue; if (!itemdb_available(nameid)) { sprintf(output, msg_txt(sd, 711), nameid); // Item %hu has been removed from your storage. clif_displaymessage(sd->fd, output); - ShowWarning("Removed invalid/disabled item id %hu from storage (amount=%d, char_id=%d).\n", nameid, sd->status.storage.items[i].amount, sd->status.char_id); - storage_delitem(sd, i, sd->status.storage.items[i].amount); + ShowWarning("Removed invalid/disabled item (ID: %hu, amount: %d) from storage (char_id: %d).\n", nameid, sd->storage.u.items_storage[i].amount, sd->status.char_id); + storage_delitem(sd, i, sd->storage.u.items_storage[i].amount); continue; } - if (!sd->status.storage.items[i].unique_id && !itemdb_isstackable(nameid)) - sd->status.storage.items[i].unique_id = pc_generate_unique_id(sd); + if (!sd->storage.u.items_storage[i].unique_id && !itemdb_isstackable(nameid)) + sd->storage.u.items_storage[i].unique_id = pc_generate_unique_id(sd); } } } @@ -10026,9 +10012,9 @@ bool pc_divorce(struct map_session_data *sd) p_sd->status.partner_id = 0; for( i = 0; i < MAX_INVENTORY; i++ ) { - if( sd->status.inventory[i].nameid == WEDDING_RING_M || sd->status.inventory[i].nameid == WEDDING_RING_F ) + if( sd->inventory.u.items_inventory[i].nameid == WEDDING_RING_M || sd->inventory.u.items_inventory[i].nameid == WEDDING_RING_F ) pc_delitem(sd, i, 1, 0, 0, LOG_TYPE_OTHER); - if( p_sd->status.inventory[i].nameid == WEDDING_RING_M || p_sd->status.inventory[i].nameid == WEDDING_RING_F ) + if( p_sd->inventory.u.items_inventory[i].nameid == WEDDING_RING_M || p_sd->inventory.u.items_inventory[i].nameid == WEDDING_RING_F ) pc_delitem(p_sd, i, 1, 0, 0, LOG_TYPE_OTHER); } diff --git a/src/map/pc.h b/src/map/pc.h index e0dc493732..49b1e77887 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -267,6 +267,11 @@ struct map_session_data { uint32 packet_ver; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 ... 18 struct mmo_charstatus status; + // Item Storages + struct s_storage storage; + struct s_storage inventory; + struct s_storage cart; + struct item_data* inventory_data[MAX_INVENTORY]; // direct pointers to itemdb entries (faster than doing item_id lookups) short equip_index[EQI_MAX]; unsigned int weight,max_weight; @@ -762,6 +767,14 @@ enum adopt_responses { ADOPT_MARRIED, }; +enum item_check { + ITMCHK_NONE = 0x0, + ITMCHK_INVENTORY = 0x1, + ITMCHK_CART = 0x2, + ITMCHK_STORAGE = 0x4, + ITMCHK_ALL = ITMCHK_INVENTORY|ITMCHK_CART|ITMCHK_STORAGE, +}; + struct { unsigned int base_hp[MAX_LEVEL], base_sp[MAX_LEVEL]; //Storage for the first calculation with hp/sp factor and multiplicator int hp_factor, hp_multiplicator, sp_factor; @@ -925,6 +938,7 @@ void pc_reg_received(struct map_session_data *sd); void pc_close_npc(struct map_session_data *sd,int flag); int pc_close_npc_timer(int tid, unsigned int tick, int id, intptr_t data); +void pc_setequipindex(struct map_session_data *sd); uint8 pc_isequip(struct map_session_data *sd,int n); int pc_equippoint(struct map_session_data *sd,int n); void pc_setinventorydata(struct map_session_data *sd); @@ -1041,7 +1055,7 @@ int pc_resethate(struct map_session_data*); bool pc_equipitem(struct map_session_data *sd, short n, int req_pos); bool pc_unequipitem(struct map_session_data*,int,int); void pc_checkitem(struct map_session_data*); -void pc_check_available_item(struct map_session_data *sd); +void pc_check_available_item(struct map_session_data *sd, uint8 type); int pc_useitem(struct map_session_data*,int); int pc_skillatk_bonus(struct map_session_data *sd, uint16 skill_id); diff --git a/src/map/pet.c b/src/map/pet.c index 9a45b8bfa4..1f372730fe 100644 --- a/src/map/pet.c +++ b/src/map/pet.c @@ -556,8 +556,8 @@ int pet_recv_petdata(uint32 account_id,struct s_pet *p,int flag) //Delete egg from inventory. [Skotlex] for (i = 0; i < MAX_INVENTORY; i++) { - if(sd->status.inventory[i].card[0] == CARD0_PET && - p->pet_id == MakeDWord(sd->status.inventory[i].card[1], sd->status.inventory[i].card[2])) + if(sd->inventory.u.items_inventory[i].card[0] == CARD0_PET && + p->pet_id == MakeDWord(sd->inventory.u.items_inventory[i].card[1], sd->inventory.u.items_inventory[i].card[2])) break; } @@ -601,8 +601,8 @@ int pet_select_egg(struct map_session_data *sd,short egg_index) if(egg_index < 0 || egg_index >= MAX_INVENTORY) return 0; //Forged packet! - if(sd->status.inventory[egg_index].card[0] == CARD0_PET) - intif_request_petdata(sd->status.account_id, sd->status.char_id, MakeDWord(sd->status.inventory[egg_index].card[1], sd->status.inventory[egg_index].card[2]) ); + if(sd->inventory.u.items_inventory[egg_index].card[0] == CARD0_PET) + intif_request_petdata(sd->status.account_id, sd->status.char_id, MakeDWord(sd->inventory.u.items_inventory[egg_index].card[1], sd->inventory.u.items_inventory[egg_index].card[2]) ); else ShowError("wrong egg item inventory %d\n",egg_index); @@ -861,10 +861,7 @@ int pet_equipitem(struct map_session_data *sd,int index) pd = sd->pd; - if (!pd) - return 1; - - nameid = sd->status.inventory[index].nameid; + nameid = sd->inventory.u.items_inventory[index].nameid; if(pd->petDB->AcceID == 0 || nameid != pd->petDB->AcceID || pd->pet.equip != 0) { clif_equipitemack(sd,0,0,ITEM_EQUIP_ACK_FAIL); diff --git a/src/map/script.c b/src/map/script.c index 9954498066..35af480020 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -45,13 +45,9 @@ #include "battleground.h" #include "party.h" #include "mail.h" -#include "script.h" #include "quest.h" #include "elemental.h" -#include -#include -#include #include #ifndef WIN32 #endif @@ -4223,7 +4219,7 @@ void script_run_autobonus(const char *autobonus, struct map_session_data *sd, un if( script ) { int j; - ARR_FIND( 0, EQI_MAX, j, sd->equip_index[j] >= 0 && sd->status.inventory[sd->equip_index[j]].equip == pos ); + ARR_FIND( 0, EQI_MAX, j, sd->equip_index[j] >= 0 && sd->inventory.u.items_inventory[sd->equip_index[j]].equip == pos ); if( j < EQI_MAX ) { //Single item autobonus current_equip_item_index = sd->equip_index[j]; @@ -6447,6 +6443,8 @@ BUILDIN_FUNC(viewpoint) /// cartcountitem2 ,,,,,,,{,}) /// storagecountitem {,}); /// storagecountitem2 ,,,,,,,{,}) +/// guildstoragecountitem {,}); +/// guildstoragecountitem2 ,,,,,,,{,}) BUILDIN_FUNC(countitem) { int i = 0, count = 0, aid = 3; @@ -6457,6 +6455,7 @@ BUILDIN_FUNC(countitem) uint16 size; struct item *items; TBL_PC *sd = NULL; + struct s_storage *gstor; if( command[strlen(command)-1] == '2' ) { i = 1; @@ -6478,17 +6477,28 @@ BUILDIN_FUNC(countitem) if( !strncmp(command, "cart", 4) ) { loc = 1; size = MAX_CART; - items = sd->status.cart; + items = sd->cart.u.items_cart; } else if( !strncmp(command, "storage", 7) ) { loc = 2; size = MAX_STORAGE; - items = sd->status.storage.items; + items = sd->storage.u.items_storage; + } + else if( !strncmp(command, "guildstorage", 12) ) { + gstor = guild2storage2(sd->status.guild_id); + + if (gstor && !sd->state.storage_flag) { + loc = 3; + size = MAX_GUILD_STORAGE; + items = gstor->u.items_guild; + } else { + script_pushint(st, -1); + return SCRIPT_CMD_SUCCESS; + } } - //TODO: 3 - Guild Storage else { size = MAX_INVENTORY; - items = sd->status.inventory; + items = sd->inventory.u.items_inventory; } if( loc == 1 && !pc_iscarton(sd) ) { @@ -6511,6 +6521,9 @@ BUILDIN_FUNC(countitem) return SCRIPT_CMD_FAILURE; } + if (loc == 3) + gstor->lock = true; + if( !i ) { // For count/cart/storagecountitem function unsigned short nameid = id->nameid; for( i = 0; i < size; i++ ) @@ -6541,6 +6554,11 @@ BUILDIN_FUNC(countitem) } } + if (loc == 3) { + storage_guild_storageclose(sd); + gstor->lock = false; + } + script_pushint(st, count); return SCRIPT_CMD_SUCCESS; } @@ -7312,16 +7330,24 @@ static void buildin_delitem_delete(struct map_session_data* sd, int idx, int* am { int delamount; struct item *itm = NULL; + struct s_storage *gstor; switch(loc) { case 1: // cart - itm = &sd->status.cart[idx]; + itm = &sd->cart.u.items_cart[idx]; break; case 2: // storage - itm = &sd->status.storage.items[idx]; + itm = &sd->storage.u.items_storage[idx]; + break; + case 3: // guild storage + { + gstor = guild2storage2(sd->status.guild_id); + + itm = &gstor->u.items_guild[idx]; + } break; default: //inventory - itm = &sd->status.inventory[idx]; + itm = &sd->inventory.u.items_inventory[idx]; break; } @@ -7341,6 +7367,13 @@ static void buildin_delitem_delete(struct map_session_data* sd, int idx, int* am storage_delitem(sd,idx,delamount); log_pick_pc(sd,LOG_TYPE_SCRIPT,-delamount,itm); break; + case 3: + gstor->lock = true; + storage_guild_delitem(sd, gstor, idx, delamount); + log_pick_pc(sd, LOG_TYPE_SCRIPT, -delamount, itm); + storage_guild_storageclose(sd); + gstor->lock = false; + break; default: pc_delitem(sd, idx, delamount, 0, 0, LOG_TYPE_SCRIPT); break; @@ -7377,15 +7410,23 @@ static bool buildin_delitem_search(struct map_session_data* sd, struct item* it, switch(loc) { case 1: // cart size = MAX_CART; - items = sd->status.cart; + items = sd->cart.u.items_cart; break; case 2: // storage size = MAX_STORAGE; - items = sd->status.storage.items; + items = sd->storage.u.items_storage; + break; + case 3: // guild storage + { + struct s_storage *gstor = guild2storage2(sd->status.guild_id); + + size = MAX_GUILD_STORAGE; + items = gstor->u.items_guild; + } break; default: //inventory size = MAX_INVENTORY; - items = sd->status.inventory; + items = sd->inventory.u.items_inventory; break; } @@ -7493,6 +7534,8 @@ static bool buildin_delitem_search(struct map_session_data* sd, struct item* it, /// cartdelitem "",{,} /// storagedelitem ,{,} /// storagedelitem "",{,} +/// guildstoragedelitem ,{,} +/// guildstoragedelitem "",{,} BUILDIN_FUNC(delitem) { TBL_PC *sd; @@ -7505,7 +7548,8 @@ BUILDIN_FUNC(delitem) loc = 1; else if(!strncmp(command, "storage", 7)) loc = 2; - //TODO: 3 - Guild Storage + else if(!strncmp(command, "guildstorage", 12)) + loc = 3; if( script_hasdata(st,4) ) { @@ -7527,8 +7571,17 @@ BUILDIN_FUNC(delitem) if (loc == 1 && !pc_iscarton(sd)) { ShowError("buildin_cartdelitem: player doesn't have cart (CID=%d).\n", sd->status.char_id); + script_pushint(st, -1); return SCRIPT_CMD_FAILURE; } + if (loc == 3) { + struct s_storage *gstor = guild2storage2(sd->status.guild_id); + + if (gstor == NULL || sd->state.storage_flag) { + script_pushint(st, -1); + return SCRIPT_CMD_FAILURE; + } + } data = script_getdata(st,2); get_val(st,data); @@ -7580,6 +7633,8 @@ BUILDIN_FUNC(delitem) /// cartdelitem2 "",,,,,,,,{,} /// storagedelitem2 ,,,,,,,,{,} /// storagedelitem2 "",,,,,,,,{,} +/// guildstoragedelitem2 ,,,,,,,,{,} +/// guildstoragedelitem2 "",,,,,,,,{,} BUILDIN_FUNC(delitem2) { TBL_PC *sd; @@ -7592,7 +7647,8 @@ BUILDIN_FUNC(delitem2) loc = 1; else if(!strncmp(command, "storage", 7)) loc = 2; - //TODO: 3 - Guild Storage + else if(!strncmp(command, "guildstorage", 12)) + loc = 3; if( script_hasdata(st,11) ) { @@ -7617,6 +7673,14 @@ BUILDIN_FUNC(delitem2) script_pushint(st,-1); return SCRIPT_CMD_FAILURE; } + if (loc == 3) { + struct s_storage *gstor = guild2storage2(sd->status.guild_id); + + if (gstor == NULL || sd->state.storage_flag) { + script_pushint(st, -1); + return SCRIPT_CMD_FAILURE; + } + } data = script_getdata(st,2); get_val(st,data); @@ -8158,7 +8222,7 @@ BUILDIN_FUNC(getequipuniqueid) return SCRIPT_CMD_FAILURE; } - item = &sd->status.inventory[i]; + item = &sd->inventory.u.items_inventory[i]; if (item != 0) { int maxlen = 256; char *buf = (char *)aMalloc(maxlen*sizeof(char)); @@ -8219,7 +8283,7 @@ BUILDIN_FUNC(getequipname) *------------------------------------------*/ BUILDIN_FUNC(getbrokenid) { - int i,num,id=0,brokencounter=0; + int i,num,id = 0,brokencounter = 0; TBL_PC *sd; if (!script_charid2sd(3, sd)) { @@ -8227,12 +8291,12 @@ BUILDIN_FUNC(getbrokenid) return SCRIPT_CMD_FAILURE; } - num=script_getnum(st,2); - for(i=0; istatus.inventory[i].attribute){ + num = script_getnum(st,2); + for(i = 0; i < MAX_INVENTORY; i++) { + if(sd->inventory.u.items_inventory[i].attribute) { brokencounter++; - if(num==brokencounter){ - id=sd->status.inventory[i].nameid; + if(num == brokencounter){ + id = sd->inventory.u.items_inventory[i].nameid; break; } } @@ -8250,20 +8314,20 @@ BUILDIN_FUNC(getbrokenid) BUILDIN_FUNC(repair) { int i,num; - int repaircounter=0; + int repaircounter = 0; TBL_PC *sd; if (!script_charid2sd(3,sd)) return SCRIPT_CMD_FAILURE; - num=script_getnum(st,2); - for(i=0; istatus.inventory[i].attribute){ + num = script_getnum(st,2); + for(i = 0; i < MAX_INVENTORY; i++) { + if(sd->inventory.u.items_inventory[i].attribute) { repaircounter++; - if(num==repaircounter){ - sd->status.inventory[i].attribute=0; + if(num == repaircounter) { + sd->inventory.u.items_inventory[i].attribute = 0; clif_equiplist(sd); - clif_produceeffect(sd, 0, sd->status.inventory[i].nameid); + clif_produceeffect(sd, 0, sd->inventory.u.items_inventory[i].nameid); clif_misceffect(&sd->bl, 3); break; } @@ -8286,10 +8350,10 @@ BUILDIN_FUNC(repairall) for(i = 0; i < MAX_INVENTORY; i++) { - if(sd->status.inventory[i].nameid && sd->status.inventory[i].attribute) + if(sd->inventory.u.items_inventory[i].nameid && sd->inventory.u.items_inventory[i].attribute) { - sd->status.inventory[i].attribute = 0; - clif_produceeffect(sd,0,sd->status.inventory[i].nameid); + sd->inventory.u.items_inventory[i].attribute = 0; + clif_produceeffect(sd,0,sd->inventory.u.items_inventory[i].nameid); repaircounter++; } } @@ -8349,7 +8413,7 @@ BUILDIN_FUNC(getequipisenableref) if( num > 0 && num <= ARRAYLENGTH(equip) ) i = pc_checkequip(sd,equip[num-1]); - if( i >= 0 && sd->inventory_data[i] && !sd->inventory_data[i]->flag.no_refine && !sd->status.inventory[i].expire_time ) + if( i >= 0 && sd->inventory_data[i] && !sd->inventory_data[i]->flag.no_refine && !sd->inventory.u.items_inventory[i].expire_time ) script_pushint(st,1); else script_pushint(st,0); @@ -8379,7 +8443,7 @@ BUILDIN_FUNC(getequiprefinerycnt) if (num > 0 && num <= ARRAYLENGTH(equip)) i=pc_checkequip(sd,equip[num-1]); if(i >= 0) - script_pushint(st,sd->status.inventory[i].refine); + script_pushint(st,sd->inventory.u.items_inventory[i].refine); else script_pushint(st,0); @@ -8437,8 +8501,8 @@ BUILDIN_FUNC(getequippercentrefinery) if (num > 0 && num <= ARRAYLENGTH(equip)) i = pc_checkequip(sd,equip[num-1]); - if(i >= 0 && sd->status.inventory[i].nameid && sd->status.inventory[i].refine < MAX_REFINE) - script_pushint(st,status_get_refine_chance((enum refine_type)itemdb_wlv(sd->status.inventory[i].nameid), (int)sd->status.inventory[i].refine)); + if(i >= 0 && sd->inventory.u.items_inventory[i].nameid && sd->inventory.u.items_inventory[i].refine < MAX_REFINE) + script_pushint(st,status_get_refine_chance((enum refine_type)itemdb_wlv(sd->inventory.u.items_inventory[i].nameid), (int)sd->inventory.u.items_inventory[i].refine)); else script_pushint(st,0); @@ -8467,32 +8531,32 @@ BUILDIN_FUNC(successrefitem) { if (pos > 0 && pos <= ARRAYLENGTH(equip)) i = pc_checkequip(sd,equip[pos-1]); if (i >= 0) { - unsigned int ep = sd->status.inventory[i].equip; + unsigned int ep = sd->inventory.u.items_inventory[i].equip; //Logs items, got from (N)PC scripts [Lupus] - log_pick_pc(sd, LOG_TYPE_SCRIPT, -1, &sd->status.inventory[i]); + log_pick_pc(sd, LOG_TYPE_SCRIPT, -1, &sd->inventory.u.items_inventory[i]); - if (sd->status.inventory[i].refine >= MAX_REFINE) { + if (sd->inventory.u.items_inventory[i].refine >= MAX_REFINE) { script_pushint(st, MAX_REFINE); return SCRIPT_CMD_SUCCESS; } - sd->status.inventory[i].refine += up; - sd->status.inventory[i].refine = cap_value( sd->status.inventory[i].refine, 0, MAX_REFINE); + sd->inventory.u.items_inventory[i].refine += up; + sd->inventory.u.items_inventory[i].refine = cap_value( sd->inventory.u.items_inventory[i].refine, 0, MAX_REFINE); pc_unequipitem(sd,i,2); // status calc will happen in pc_equipitem() below - clif_refine(sd->fd,0,i,sd->status.inventory[i].refine); + clif_refine(sd->fd,0,i,sd->inventory.u.items_inventory[i].refine); clif_delitem(sd,i,1,3); //Logs items, got from (N)PC scripts [Lupus] - log_pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->status.inventory[i]); + log_pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->inventory.u.items_inventory[i]); clif_additem(sd,i,1,0); pc_equipitem(sd,i,ep); clif_misceffect(&sd->bl,3); - if (sd->status.inventory[i].refine == MAX_REFINE && - sd->status.inventory[i].card[0] == CARD0_FORGE && - sd->status.char_id == (int)MakeDWord(sd->status.inventory[i].card[2],sd->status.inventory[i].card[3])) + if (sd->inventory.u.items_inventory[i].refine == MAX_REFINE && + sd->inventory.u.items_inventory[i].card[0] == CARD0_FORGE && + sd->status.char_id == (int)MakeDWord(sd->inventory.u.items_inventory[i].card[2],sd->inventory.u.items_inventory[i].card[3])) { // Fame point system [DracoRPG] switch (sd->inventory_data[i]->wlv){ case 1: @@ -8506,7 +8570,7 @@ BUILDIN_FUNC(successrefitem) { break; } } - script_pushint(st, sd->status.inventory[i].refine); + script_pushint(st, sd->inventory.u.items_inventory[i].refine); return SCRIPT_CMD_SUCCESS; } @@ -8534,9 +8598,9 @@ BUILDIN_FUNC(failedrefitem) { if (pos > 0 && pos <= ARRAYLENGTH(equip)) i = pc_checkequip(sd,equip[pos-1]); if (i >= 0) { - sd->status.inventory[i].refine = 0; + sd->inventory.u.items_inventory[i].refine = 0; pc_unequipitem(sd,i,3); //recalculate bonus - clif_refine(sd->fd,1,i,sd->status.inventory[i].refine); //notify client of failure + clif_refine(sd->fd,1,i,sd->inventory.u.items_inventory[i].refine); //notify client of failure pc_delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT); clif_misceffect(&sd->bl,2); // display failure effect script_pushint(st, 1); @@ -8569,25 +8633,25 @@ BUILDIN_FUNC(downrefitem) { if (pos > 0 && pos <= ARRAYLENGTH(equip)) i = pc_checkequip(sd,equip[pos-1]); if (i >= 0) { - unsigned int ep = sd->status.inventory[i].equip; + unsigned int ep = sd->inventory.u.items_inventory[i].equip; //Logs items, got from (N)PC scripts [Lupus] - log_pick_pc(sd, LOG_TYPE_SCRIPT, -1, &sd->status.inventory[i]); + log_pick_pc(sd, LOG_TYPE_SCRIPT, -1, &sd->inventory.u.items_inventory[i]); pc_unequipitem(sd,i,2); // status calc will happen in pc_equipitem() below - sd->status.inventory[i].refine -= down; - sd->status.inventory[i].refine = cap_value( sd->status.inventory[i].refine, 0, MAX_REFINE); + sd->inventory.u.items_inventory[i].refine -= down; + sd->inventory.u.items_inventory[i].refine = cap_value( sd->inventory.u.items_inventory[i].refine, 0, MAX_REFINE); - clif_refine(sd->fd,2,i,sd->status.inventory[i].refine); + clif_refine(sd->fd,2,i,sd->inventory.u.items_inventory[i].refine); clif_delitem(sd,i,1,3); //Logs items, got from (N)PC scripts [Lupus] - log_pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->status.inventory[i]); + log_pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->inventory.u.items_inventory[i]); clif_additem(sd,i,1,0); pc_equipitem(sd,i,ep); clif_misceffect(&sd->bl,2); - script_pushint(st, sd->status.inventory[i].refine); + script_pushint(st, sd->inventory.u.items_inventory[i].refine); return SCRIPT_CMD_SUCCESS; } @@ -8644,7 +8708,7 @@ BUILDIN_FUNC(breakequip) { if (pos > 0 && pos <= ARRAYLENGTH(equip)) i = pc_checkequip(sd,equip[pos-1]); if (i >= 0) { - sd->status.inventory[i].attribute = 1; + sd->inventory.u.items_inventory[i].attribute = 1; pc_unequipitem(sd,i,3); clif_equiplist(sd); script_pushint(st,1); @@ -8805,7 +8869,7 @@ BUILDIN_FUNC(autobonus) if (current_equip_combo_pos) pos = current_equip_combo_pos; else - pos = sd->status.inventory[current_equip_item_index].equip; + pos = sd->inventory.u.items_inventory[current_equip_item_index].equip; if((sd->state.autobonus&pos) == pos) return SCRIPT_CMD_SUCCESS; @@ -8847,7 +8911,7 @@ BUILDIN_FUNC(autobonus2) if (current_equip_combo_pos) pos = current_equip_combo_pos; else - pos = sd->status.inventory[current_equip_item_index].equip; + pos = sd->inventory.u.items_inventory[current_equip_item_index].equip; if((sd->state.autobonus&pos) == pos) return SCRIPT_CMD_SUCCESS; @@ -8889,7 +8953,7 @@ BUILDIN_FUNC(autobonus3) if (current_equip_combo_pos) pos = current_equip_combo_pos; else - pos = sd->status.inventory[current_equip_item_index].equip; + pos = sd->inventory.u.items_inventory[current_equip_item_index].equip; if((sd->state.autobonus&pos) == pos) return SCRIPT_CMD_SUCCESS; @@ -9526,7 +9590,7 @@ BUILDIN_FUNC(guildopenstorage) if( sd == NULL ) return SCRIPT_CMD_SUCCESS; - ret = gstorage_storageopen(sd); + ret = storage_guild_storageopen(sd); script_pushint(st,ret); return SCRIPT_CMD_SUCCESS; } @@ -9958,9 +10022,9 @@ BUILDIN_FUNC(killmonsterall) BUILDIN_FUNC(clone) { TBL_PC *sd, *msd=NULL; - uint32 char_id; - int master_id=0,x,y, flag = 0, m; + uint32 char_id, master_id = 0, x, y, flag = 0, m; enum e_mode mode = 0; + unsigned int duration = 0; const char *mapname,*event; @@ -12449,7 +12513,7 @@ BUILDIN_FUNC(getequipcardcnt) return SCRIPT_CMD_SUCCESS; } - if(itemdb_isspecial(sd->status.inventory[i].card[0])) + if(itemdb_isspecial(sd->inventory.u.items_inventory[i].card[0])) { script_pushint(st,0); return SCRIPT_CMD_SUCCESS; @@ -12457,7 +12521,7 @@ BUILDIN_FUNC(getequipcardcnt) count = 0; for( j = 0; j < sd->inventory_data[i]->slot; j++ ) - if( sd->status.inventory[i].card[j] && itemdb_type(sd->status.inventory[i].card[j]) == IT_CARD ) + if( sd->inventory.u.items_inventory[i].card[j] && itemdb_type(sd->inventory.u.items_inventory[i].card[j]) == IT_CARD ) count++; script_pushint(st,count); @@ -12480,16 +12544,16 @@ BUILDIN_FUNC(successremovecards) { return SCRIPT_CMD_SUCCESS; } - if(itemdb_isspecial(sd->status.inventory[i].card[0])) + if(itemdb_isspecial(sd->inventory.u.items_inventory[i].card[0])) return SCRIPT_CMD_SUCCESS; for( c = sd->inventory_data[i]->slot - 1; c >= 0; --c ) { - if( sd->status.inventory[i].card[c] && itemdb_type(sd->status.inventory[i].card[c]) == IT_CARD ) {// extract this card from the item + if( sd->inventory.u.items_inventory[i].card[c] && itemdb_type(sd->inventory.u.items_inventory[i].card[c]) == IT_CARD ) {// extract this card from the item unsigned char flag = 0; struct item item_tmp; memset(&item_tmp,0,sizeof(item_tmp)); cardflag = 1; - item_tmp.nameid = sd->status.inventory[i].card[c]; + item_tmp.nameid = sd->inventory.u.items_inventory[i].card[c]; item_tmp.identify = 1; if((flag=pc_additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))){ // get back the cart in inventory @@ -12504,15 +12568,15 @@ BUILDIN_FUNC(successremovecards) { struct item item_tmp; memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid = sd->status.inventory[i].nameid; + item_tmp.nameid = sd->inventory.u.items_inventory[i].nameid; item_tmp.identify = 1; - item_tmp.refine = sd->status.inventory[i].refine; - item_tmp.attribute = sd->status.inventory[i].attribute; - item_tmp.expire_time = sd->status.inventory[i].expire_time; - item_tmp.bound = sd->status.inventory[i].bound; + item_tmp.refine = sd->inventory.u.items_inventory[i].refine; + item_tmp.attribute = sd->inventory.u.items_inventory[i].attribute; + item_tmp.expire_time = sd->inventory.u.items_inventory[i].expire_time; + item_tmp.bound = sd->inventory.u.items_inventory[i].bound; for (j = sd->inventory_data[i]->slot; j < MAX_SLOTS; j++) - item_tmp.card[j]=sd->status.inventory[i].card[j]; + item_tmp.card[j]=sd->inventory.u.items_inventory[i].card[j]; pc_delitem(sd,i,1,0,3,LOG_TYPE_SCRIPT); if((flag=pc_additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))){ //chk if can be spawn in inventory otherwise put on floor @@ -12544,11 +12608,11 @@ BUILDIN_FUNC(failedremovecards) { if (i < 0 || !sd->inventory_data[i]) return SCRIPT_CMD_SUCCESS; - if(itemdb_isspecial(sd->status.inventory[i].card[0])) + if(itemdb_isspecial(sd->inventory.u.items_inventory[i].card[0])) return SCRIPT_CMD_SUCCESS; for( c = sd->inventory_data[i]->slot - 1; c >= 0; --c ) { - if( sd->status.inventory[i].card[c] && itemdb_type(sd->status.inventory[i].card[c]) == IT_CARD ) { + if( sd->inventory.u.items_inventory[i].card[c] && itemdb_type(sd->inventory.u.items_inventory[i].card[c]) == IT_CARD ) { cardflag = 1; if(typefail == 2) {// add cards to inventory, clear @@ -12557,7 +12621,7 @@ BUILDIN_FUNC(failedremovecards) { memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid = sd->status.inventory[i].card[c]; + item_tmp.nameid = sd->inventory.u.items_inventory[i].card[c]; item_tmp.identify = 1; if((flag=pc_additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))){ @@ -12578,15 +12642,15 @@ BUILDIN_FUNC(failedremovecards) { memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid = sd->status.inventory[i].nameid; + item_tmp.nameid = sd->inventory.u.items_inventory[i].nameid; item_tmp.identify = 1; - item_tmp.refine = sd->status.inventory[i].refine; - item_tmp.attribute = sd->status.inventory[i].attribute; - item_tmp.expire_time = sd->status.inventory[i].expire_time; - item_tmp.bound = sd->status.inventory[i].bound; + item_tmp.refine = sd->inventory.u.items_inventory[i].refine; + item_tmp.attribute = sd->inventory.u.items_inventory[i].attribute; + item_tmp.expire_time = sd->inventory.u.items_inventory[i].expire_time; + item_tmp.bound = sd->inventory.u.items_inventory[i].bound; for (j = sd->inventory_data[i]->slot; j < MAX_SLOTS; j++) - item_tmp.card[j]=sd->status.inventory[i].card[j]; + item_tmp.card[j]=sd->inventory.u.items_inventory[i].card[j]; pc_delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT); @@ -13161,7 +13225,7 @@ BUILDIN_FUNC(getequipcardid) if (num > 0 && num <= ARRAYLENGTH(equip)) i=pc_checkequip(sd,equip[num-1]); if(i >= 0 && slot>=0 && slot<4) - script_pushint(st,sd->status.inventory[i].card[slot]); + script_pushint(st,sd->inventory.u.items_inventory[i].card[slot]); else script_pushint(st,0); return SCRIPT_CMD_SUCCESS; @@ -13253,20 +13317,20 @@ BUILDIN_FUNC(getinventorylist) if (!script_charid2sd(2,sd)) return SCRIPT_CMD_FAILURE; for(i=0;istatus.inventory[i].nameid > 0 && sd->status.inventory[i].amount > 0){ - pc_setreg(sd,reference_uid(add_str("@inventorylist_id"), j),sd->status.inventory[i].nameid); - pc_setreg(sd,reference_uid(add_str("@inventorylist_amount"), j),sd->status.inventory[i].amount); - pc_setreg(sd,reference_uid(add_str("@inventorylist_equip"), j),sd->status.inventory[i].equip); - pc_setreg(sd,reference_uid(add_str("@inventorylist_refine"), j),sd->status.inventory[i].refine); - pc_setreg(sd,reference_uid(add_str("@inventorylist_identify"), j),sd->status.inventory[i].identify); - pc_setreg(sd,reference_uid(add_str("@inventorylist_attribute"), j),sd->status.inventory[i].attribute); + if(sd->inventory.u.items_inventory[i].nameid > 0 && sd->inventory.u.items_inventory[i].amount > 0){ + pc_setreg(sd,reference_uid(add_str("@inventorylist_id"), j),sd->inventory.u.items_inventory[i].nameid); + pc_setreg(sd,reference_uid(add_str("@inventorylist_amount"), j),sd->inventory.u.items_inventory[i].amount); + pc_setreg(sd,reference_uid(add_str("@inventorylist_equip"), j),sd->inventory.u.items_inventory[i].equip); + pc_setreg(sd,reference_uid(add_str("@inventorylist_refine"), j),sd->inventory.u.items_inventory[i].refine); + pc_setreg(sd,reference_uid(add_str("@inventorylist_identify"), j),sd->inventory.u.items_inventory[i].identify); + pc_setreg(sd,reference_uid(add_str("@inventorylist_attribute"), j),sd->inventory.u.items_inventory[i].attribute); for (k = 0; k < MAX_SLOTS; k++) { sprintf(card_var, "@inventorylist_card%d",k+1); - pc_setreg(sd,reference_uid(add_str(card_var), j),sd->status.inventory[i].card[k]); + pc_setreg(sd,reference_uid(add_str(card_var), j),sd->inventory.u.items_inventory[i].card[k]); } - pc_setreg(sd,reference_uid(add_str("@inventorylist_expire"), j),sd->status.inventory[i].expire_time); - pc_setreg(sd,reference_uid(add_str("@inventorylist_bound"), j),sd->status.inventory[i].bound); + pc_setreg(sd,reference_uid(add_str("@inventorylist_expire"), j),sd->inventory.u.items_inventory[i].expire_time); + pc_setreg(sd,reference_uid(add_str("@inventorylist_bound"), j),sd->inventory.u.items_inventory[i].bound); j++; } } @@ -13308,8 +13372,8 @@ BUILDIN_FUNC(clearitem) return SCRIPT_CMD_FAILURE; for (i=0; istatus.inventory[i].amount) { - pc_delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_SCRIPT); + if (sd->inventory.u.items_inventory[i].amount) { + pc_delitem(sd, i, sd->inventory.u.items_inventory[i].amount, 0, 0, LOG_TYPE_SCRIPT); } } return SCRIPT_CMD_SUCCESS; @@ -14127,7 +14191,7 @@ BUILDIN_FUNC(getmercinfo) if( script_hasdata(st,3) ) { - int char_id = script_getnum(st,3); + uint32 char_id = script_getnum(st,3); if( ( sd = map_charid2sd(char_id) ) == NULL ) { @@ -14186,11 +14250,11 @@ BUILDIN_FUNC(checkequipedcard) c=script_getnum(st,2); for(i=0;istatus.inventory[i].nameid > 0 && sd->status.inventory[i].amount && sd->inventory_data[i]){ - if (itemdb_isspecial(sd->status.inventory[i].card[0])) + if(sd->inventory.u.items_inventory[i].nameid > 0 && sd->inventory.u.items_inventory[i].amount && sd->inventory_data[i]){ + if (itemdb_isspecial(sd->inventory.u.items_inventory[i].card[0])) continue; for(n=0;ninventory_data[i]->slot;n++){ - if(sd->status.inventory[i].card[n]==c){ + if(sd->inventory.u.items_inventory[i].card[n] == c) { script_pushint(st,1); return SCRIPT_CMD_SUCCESS; } @@ -14687,13 +14751,13 @@ BUILDIN_FUNC(isequippedcnt) if (itemdb_type(id) != IT_CARD) { //No card. Count amount in inventory. if (sd->inventory_data[index]->nameid == id) - ret+= sd->status.inventory[index].amount; + ret+= sd->inventory.u.items_inventory[index].amount; } else { //Count cards. short k; - if (itemdb_isspecial(sd->status.inventory[index].card[0])) + if (itemdb_isspecial(sd->inventory.u.items_inventory[index].card[0])) continue; //No cards for(k=0; kinventory_data[index]->slot; k++) { - if (sd->status.inventory[index].card[k] == id) + if (sd->inventory.u.items_inventory[index].card[k] == id) ret++; //[Lupus] } } @@ -14751,13 +14815,13 @@ BUILDIN_FUNC(isequipped) } else { //Cards short k; if (sd->inventory_data[index]->slot == 0 || - itemdb_isspecial(sd->status.inventory[index].card[0])) + itemdb_isspecial(sd->inventory.u.items_inventory[index].card[0])) continue; for (k = 0; k < sd->inventory_data[index]->slot; k++) { //New hash system which should support up to 4 slots on any equipment. [Skotlex] unsigned int hash = 0; - if (sd->status.inventory[index].card[k] != id) + if (sd->inventory.u.items_inventory[index].card[k] != id) continue; hash = 1<<((j<5?j:j-5)*4 + k); @@ -14817,12 +14881,12 @@ BUILDIN_FUNC(cardscnt) if(itemdb_type(id) != IT_CARD) { if (sd->inventory_data[index]->nameid == id) - ret+= sd->status.inventory[index].amount; + ret+= sd->inventory.u.items_inventory[index].amount; } else { - if (itemdb_isspecial(sd->status.inventory[index].card[0])) + if (itemdb_isspecial(sd->inventory.u.items_inventory[index].card[0])) continue; for(k=0; kinventory_data[index]->slot; k++) { - if (sd->status.inventory[index].card[k] == id) + if (sd->inventory.u.items_inventory[index].card[k] == id) ret++; } } @@ -14840,7 +14904,7 @@ BUILDIN_FUNC(getrefine) { TBL_PC *sd; if ((sd = script_rid2sd(st))!= NULL) - script_pushint(st,sd->status.inventory[current_equip_item_index].refine); + script_pushint(st,sd->inventory.u.items_inventory[current_equip_item_index].refine); else script_pushint(st,0); return SCRIPT_CMD_SUCCESS; @@ -14900,7 +14964,7 @@ BUILDIN_FUNC(equip) { if ((item_data = itemdb_exists(nameid))) { int i; - ARR_FIND( 0, MAX_INVENTORY, i, sd->status.inventory[i].nameid == nameid ); + ARR_FIND( 0, MAX_INVENTORY, i, sd->inventory.u.items_inventory[i].nameid == nameid ); if (i < MAX_INVENTORY) { pc_equipitem(sd,i,item_data->equip); script_pushint(st,1); @@ -19998,13 +20062,13 @@ BUILDIN_FUNC(countbound) type = script_getnum(st,2); for( i = 0; i < MAX_INVENTORY; i ++ ) { - if( sd->status.inventory[i].nameid > 0 && ( - (!type && sd->status.inventory[i].bound) || (type && sd->status.inventory[i].bound == type) + if( sd->inventory.u.items_inventory[i].nameid > 0 && ( + (!type && sd->inventory.u.items_inventory[i].bound) || (type && sd->inventory.u.items_inventory[i].bound == type) )) { - pc_setreg(sd,reference_uid(add_str("@bound_items"), k),sd->status.inventory[i].nameid); + pc_setreg(sd,reference_uid(add_str("@bound_items"), k),sd->inventory.u.items_inventory[i].nameid); k++; - j += sd->status.inventory[i].amount; + j += sd->inventory.u.items_inventory[i].amount; } } @@ -20723,7 +20787,8 @@ BUILDIN_FUNC(mergeitem2) { } for (i = 0; i < MAX_INVENTORY; i++) { - struct item *it = &sd->status.inventory[i]; + struct item *it = &sd->inventory.u.items_inventory[i]; + if (!it || !it->unique_id || it->expire_time || !itemdb_isstackable(it->nameid)) continue; if ((!nameid || (nameid == it->nameid))) { @@ -21293,9 +21358,11 @@ struct script_function buildin_func[] = { BUILDIN_DEF(makeitem2,"visiiiiiiiii"), BUILDIN_DEF(delitem,"vi?"), BUILDIN_DEF2(delitem,"storagedelitem","vi?"), + BUILDIN_DEF2(delitem,"guildstoragedelitem","vi?"), BUILDIN_DEF2(delitem,"cartdelitem","vi?"), BUILDIN_DEF(delitem2,"viiiiiiii?"), BUILDIN_DEF2(delitem2,"storagedelitem2","viiiiiiii?"), + BUILDIN_DEF2(delitem2,"guildstoragedelitem2","viiiiiiii?"), BUILDIN_DEF2(delitem2,"cartdelitem2","viiiiiiii?"), BUILDIN_DEF2(enableitemuse,"enable_items",""), BUILDIN_DEF2(disableitemuse,"disable_items",""), @@ -21307,9 +21374,11 @@ struct script_function buildin_func[] = { BUILDIN_DEF(rand,"i?"), BUILDIN_DEF(countitem,"v?"), BUILDIN_DEF2(countitem,"storagecountitem","v?"), + BUILDIN_DEF2(countitem,"guildstoragecountitem","v?"), BUILDIN_DEF2(countitem,"cartcountitem","v?"), BUILDIN_DEF2(countitem,"countitem2","viiiiiii?"), BUILDIN_DEF2(countitem,"storagecountitem2","viiiiiii?"), + BUILDIN_DEF2(countitem,"guildstoragecountitem2","viiiiiii?"), BUILDIN_DEF2(countitem,"cartcountitem2","viiiiiii?"), BUILDIN_DEF(checkweight,"vi*"), BUILDIN_DEF(checkweight2,"rr"), diff --git a/src/map/skill.c b/src/map/skill.c index 03aa711b89..b26238b0c0 100755 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -2473,7 +2473,7 @@ int skill_break_equip(struct block_list *src, struct block_list *bl, unsigned sh if (sd) { for (i = 0; i < EQI_MAX; i++) { short j = sd->equip_index[i]; - if (j < 0 || sd->status.inventory[j].attribute == 1 || !sd->inventory_data[j]) + if (j < 0 || sd->inventory.u.items_inventory[j].attribute == 1 || !sd->inventory_data[j]) continue; switch(i) { @@ -2499,7 +2499,7 @@ int skill_break_equip(struct block_list *src, struct block_list *bl, unsigned sh continue; } if (flag) { - sd->status.inventory[j].attribute = 1; + sd->inventory.u.items_inventory[j].attribute = 1; pc_unequipitem(sd, j, 3); } } @@ -3809,7 +3809,7 @@ static int skill_check_condition_mercenary(struct block_list *bl, int skill, int index[i] = -1; if( itemid[i] < 1 ) continue; // No item index[i] = pc_search_inventory(sd, itemid[i]); - if( index[i] < 0 || sd->status.inventory[index[i]].amount < amount[i] ) + if( index[i] < 0 || sd->inventory.u.items_inventory[index[i]].amount < amount[i] ) { clif_skill_fail(sd, skill, USESKILL_FAIL_LEVEL, 0); return 0; @@ -7457,7 +7457,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui map_freeblock_unlock(); return 1; } - if (sd->inventory_data[j] == NULL || sd->status.inventory[j].amount < require.amount[x]) { + if (sd->inventory_data[j] == NULL || sd->inventory.u.items_inventory[j].amount < require.amount[x]) { clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); map_freeblock_unlock(); return 1; @@ -7597,7 +7597,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui int ebottle = pc_search_inventory(sd,ITEMID_EMPTY_BOTTLE); short alcohol_idx = -1, acid_idx = -1, fire_idx = -1; if( ebottle >= 0 ) - ebottle = sd->status.inventory[ebottle].amount; + ebottle = sd->inventory.u.items_inventory[ebottle].amount; //check if you can produce all three, if not, then fail: if (!(alcohol_idx = skill_can_produce_mix(sd,ITEMID_ALCOHOL,-1, 100)) //100 Alcohol || !(acid_idx = skill_can_produce_mix(sd,ITEMID_ACID_BOTTLE,-1, 50)) //50 Acid Bottle @@ -9607,7 +9607,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui else { shield_def = shield_data->def; shield_mdef = sd->bonus.shieldmdef; - shield_refine = sd->status.inventory[sd->equip_index[EQI_HAND_L]].refine; + shield_refine = sd->inventory.u.items_inventory[sd->equip_index[EQI_HAND_L]].refine; } if (flag&1) { sc_start(src,bl,SC_SILENCE,100,skill_lv,shield_mdef * 30000); @@ -11743,7 +11743,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui struct skill_condition require = skill_get_requirement(sd, skill_id, skill_lv); i_lv = skill_lv%11 - 1; j = pc_search_inventory(sd, require.itemid[i_lv]); - if (j < 0 || require.itemid[i_lv] <= 0 || sd->inventory_data[j] == NULL || sd->status.inventory[j].amount < require.amount[i_lv]) + if (j < 0 || require.itemid[i_lv] <= 0 || sd->inventory_data[j] == NULL || sd->inventory.u.items_inventory[j].amount < require.amount[i_lv]) { clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 1; @@ -14707,10 +14707,10 @@ bool skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_i else { // When a target was selected, consume items that were skipped in pc_use_item [Skotlex] if( (i = sd->itemindex) == -1 || - sd->status.inventory[i].nameid != sd->itemid || + sd->inventory.u.items_inventory[i].nameid != sd->itemid || sd->inventory_data[i] == NULL || !sd->inventory_data[i]->flag.delay_consume || - sd->status.inventory[i].amount < 1 + sd->inventory.u.items_inventory[i].amount < 1 ) { //Something went wrong, item exploit? sd->itemid = sd->itemindex = -1; @@ -14720,7 +14720,7 @@ bool skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_i sd->itemid = sd->itemindex = -1; if( skill_id == WZ_EARTHSPIKE && sc && sc->data[SC_EARTHSCROLL] && rnd()%100 > sc->data[SC_EARTHSCROLL]->val2 ) // [marquis007] ; //Do not consume item. - else if( sd->status.inventory[i].expire_time == 0 ) + else if( sd->inventory.u.items_inventory[i].expire_time == 0 ) pc_delitem(sd,i,1,0,0,LOG_TYPE_CONSUME); // Rental usable items are not consumed until expiration } return true; @@ -15101,8 +15101,8 @@ bool skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_i int count = 0; for( i = 0; i < MAX_INVENTORY; i++ ) - if( sd->status.inventory[i].nameid == ITEMID_ANCILLA ) - count += sd->status.inventory[i].amount; + if( sd->inventory.u.items_inventory[i].nameid == ITEMID_ANCILLA ) + count += sd->inventory.u.items_inventory[i].amount; if( count >= 3 ) { clif_skill_fail(sd, skill_id, USESKILL_FAIL_ANCILLA_NUMOVER, 0); return false; @@ -15126,7 +15126,7 @@ bool skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_i case WL_COMET: if( skill_check_pc_partner(sd,skill_id,&skill_lv,1,0) <= 0 && require.itemid[0] && sd->special_state.no_gemstone == 0 - && ((i = pc_search_inventory(sd,require.itemid[0])) < 0 || sd->status.inventory[i].amount < require.amount[0]) ) { + && ((i = pc_search_inventory(sd,require.itemid[0])) < 0 || sd->inventory.u.items_inventory[i].amount < require.amount[0]) ) { //clif_skill_fail(sd,skill_id,USESKILL_FAIL_NEED_ITEM,require.amount[0],require.itemid[0]); clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return false; @@ -15647,7 +15647,7 @@ bool skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, if((i=sd->equip_index[EQI_AMMO]) < 0 || !sd->inventory_data[i] ) { clif_arrow_fail(sd,0); return false; - } else if( sd->status.inventory[i].amount < require.ammo_qty ) { + } else if( sd->inventory.u.items_inventory[i].amount < require.ammo_qty ) { char e_msg[100]; if (require.ammo&(1<status.inventory[i].nameid)); + itemdb_jname(sd->inventory.u.items_inventory[i].nameid)); clif_colormes(sd->fd,color_table[COLOR_RED],e_msg); return false; } @@ -15676,7 +15676,7 @@ bool skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, if( !require.itemid[i] ) continue; index[i] = pc_search_inventory(sd,require.itemid[i]); - if( index[i] < 0 || sd->status.inventory[index[i]].amount < require.amount[i] ) { + if( index[i] < 0 || sd->inventory.u.items_inventory[index[i]].amount < require.amount[i] ) { if( require.itemid[i] == ITEMID_HOLY_WATER ) clif_skill_fail(sd,skill_id,USESKILL_FAIL_HOLYWATER,0); //Holy water is required. else if( require.itemid[i] == ITEMID_RED_GEMSTONE ) @@ -15968,7 +15968,7 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 if ((skill_id >= HT_SKIDTRAP && skill_id <= HT_TALKIEBOX && pc_checkskill(sd, RA_RESEARCHTRAP) > 0) || skill_id == SC_ESCAPE) { int16 itIndex; - if ((itIndex = pc_search_inventory(sd,req.itemid[i])) < 0 || ( itIndex >= 0 && sd->status.inventory[itIndex].amount < req.amount[i])) { + if ((itIndex = pc_search_inventory(sd,req.itemid[i])) < 0 || ( itIndex >= 0 && sd->inventory.u.items_inventory[itIndex].amount < req.amount[i])) { if (skill_id == SC_ESCAPE) // Alloy Trap has priority over normal Trap req.itemid[i] = ITEMID_TRAP; else @@ -16459,7 +16459,7 @@ void skill_repairweapon(struct map_session_data *sd, int idx) { if( idx < 0 || idx >= MAX_INVENTORY ) return; //Invalid index?? - item = &target_sd->status.inventory[idx]; + item = &target_sd->inventory.u.items_inventory[idx]; if( !item->nameid || !item->attribute ) return; //Again invalid item.... @@ -16501,9 +16501,9 @@ void skill_identify(struct map_session_data *sd, int idx) nullpo_retv(sd); if(idx >= 0 && idx < MAX_INVENTORY) { - if(sd->status.inventory[idx].nameid > 0 && sd->status.inventory[idx].identify == 0 ){ + if(sd->inventory.u.items_inventory[idx].nameid > 0 && sd->inventory.u.items_inventory[idx].identify == 0 ){ flag=0; - sd->status.inventory[idx].identify=1; + sd->inventory.u.items_inventory[idx].identify = 1; } } clif_item_identified(sd,idx,flag); @@ -16520,7 +16520,7 @@ void skill_weaponrefine(struct map_session_data *sd, int idx) { struct item *item; struct item_data *ditem = sd->inventory_data[idx]; - item = &sd->status.inventory[idx]; + item = &sd->inventory.u.items_inventory[idx]; if(item->nameid > 0 && ditem->type == IT_WEAPON) { int i = 0, per; @@ -18606,8 +18606,8 @@ short skill_can_produce_mix(struct map_session_data *sd, unsigned short nameid, unsigned short idx, amt; for (idx = 0, amt = 0; idx < MAX_INVENTORY; idx++) - if (sd->status.inventory[idx].nameid == nameid_produce) - amt += sd->status.inventory[idx].amount; + if (sd->inventory.u.items_inventory[idx].nameid == nameid_produce) + amt += sd->inventory.u.items_inventory[idx].amount; if (amt < qty * skill_produce_db[i].mat_amount[j]) return 0; } @@ -18692,14 +18692,14 @@ bool skill_produce_mix(struct map_session_data *sd, uint16 skill_id, unsigned sh if (data->stack.inventory) { for (i = 0; i < MAX_INVENTORY; i++) { - if (sd->status.inventory[i].nameid == nameid) { - if (sd->status.inventory[i].amount >= data->stack.amount) { + if (sd->inventory.u.items_inventory[i].nameid == nameid) { + if (sd->inventory.u.items_inventory[i].amount >= data->stack.amount) { clif_msg(sd,RUNE_CANT_CREATE); return 0; } else { // The amount fits, say we got temp_qty 4 and 19 runes, we trim temp_qty to 1. - if (temp_qty + sd->status.inventory[i].amount >= data->stack.amount) - temp_qty = data->stack.amount - sd->status.inventory[i].amount; + if (temp_qty + sd->inventory.u.items_inventory[i].amount >= data->stack.amount) + temp_qty = data->stack.amount - sd->inventory.u.items_inventory[i].amount; } break; } @@ -18721,7 +18721,7 @@ bool skill_produce_mix(struct map_session_data *sd, uint16 skill_id, unsigned sh j = pc_search_inventory(sd,id); if (j >= 0) { - y = sd->status.inventory[j].amount; + y = sd->inventory.u.items_inventory[j].amount; if (y > x) y = x; pc_delitem(sd,j,y,0,0,LOG_TYPE_PRODUCE); @@ -19508,7 +19508,7 @@ int skill_elementalanalysis(struct map_session_data* sd, int n, uint16 skill_lv, del_amount -= (del_amount % 10); add_amount = (skill_lv == 1) ? del_amount * (5 + rnd()%5) : del_amount / 10 ; - if( (nameid = sd->status.inventory[idx].nameid) <= 0 || del_amount > sd->status.inventory[idx].amount ) { + if( (nameid = sd->inventory.u.items_inventory[idx].nameid) <= 0 || del_amount > sd->inventory.u.items_inventory[idx].amount ) { clif_skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0); return 1; } @@ -19575,9 +19575,9 @@ int skill_changematerial(struct map_session_data *sd, int n, unsigned short *ite if( skill_produce_db[i].mat_id[j] > 0 ) { for( k = 0; k < n; k++ ) { int idx = item_list[k*2+0]-2; - nameid = sd->status.inventory[idx].nameid; + nameid = sd->inventory.u.items_inventory[idx].nameid; amount = item_list[k*2+1]; - if( nameid > 0 && sd->status.inventory[idx].identify == 0 ){ + if( nameid > 0 && sd->inventory.u.items_inventory[idx].identify == 0 ){ clif_msg_skill(sd,GN_CHANGEMATERIAL,ITEM_UNIDENTIFIED); return 0; } diff --git a/src/map/status.c b/src/map/status.c index f151b513d6..904aab60b7 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -3010,6 +3010,101 @@ static unsigned int status_calc_maxhpsp_pc(struct map_session_data* sd, unsigned return cap_value((unsigned int)dmax,1,UINT_MAX); } +/** + * Calculates player's weight + * @param sd: Player object + * @param flag: Calculation type + * 1 - Item weight + * 2 - Skill/Status/Configuration max weight bonus + * @return false - failed, true - success + */ +bool status_calc_weight(struct map_session_data *sd, uint8 flag) +{ + int b_weight, b_max_weight, skill, i; + struct status_change *sc; + + nullpo_retr(false, sd); + + sc = &sd->sc; + b_max_weight = sd->max_weight; // Store max weight for later comparison + b_weight = sd->weight; // Store current weight for later comparison + sd->max_weight = job_info[pc_class2idx(sd->status.class_)].max_weight_base + sd->status.str * 300; // Recalculate max weight + + if (flag&1) { + sd->weight = 0; // Reset current weight + + for(i = 0; i < MAX_INVENTORY; i++) { + if (!sd->inventory.u.items_inventory[i].nameid || sd->inventory_data[i] == NULL) + continue; + sd->weight += sd->inventory_data[i]->weight * sd->inventory.u.items_inventory[i].amount; + } + } + + if (flag&2) { + // Skill/Status bonus weight increases + if ((skill = pc_checkskill(sd, MC_INCCARRY)) > 0) + sd->max_weight += 2000 * skill; + if (pc_isriding(sd) && pc_checkskill(sd, KN_RIDING) > 0) + sd->max_weight += 10000; + else if (pc_isridingdragon(sd)) + sd->max_weight += 5000 + 2000 * pc_checkskill(sd, RK_DRAGONTRAINING); + if (sc->data[SC_KNOWLEDGE]) + sd->max_weight += sd->max_weight * sc->data[SC_KNOWLEDGE]->val1 / 10; + if ((skill = pc_checkskill(sd, ALL_INCCARRY)) > 0) + sd->max_weight += 2000 * skill; + } + + // Update the client if the new weight calculations don't match + if (b_weight != sd->weight) + clif_updatestatus(sd, SP_WEIGHT); + if (b_max_weight != sd->max_weight) { + clif_updatestatus(sd, SP_MAXWEIGHT); + pc_updateweightstatus(sd); + } + + return true; +} + +/** + * Calculates player's cart weight + * @param sd: Player object + * @return false - failed, true - success + */ +bool status_calc_cart_weight(struct map_session_data *sd, uint8 flag) +{ + int b_cart_weight_max, i; + + nullpo_retr(false, sd); + + if (!pc_iscarton(sd)) + return false; + + b_cart_weight_max = sd->cart_weight_max; // Store cart max weight for later comparison + sd->cart_weight_max = battle_config.max_cart_weight; // Recalculate max weight + + if (flag&1) { + sd->cart_weight = 0; // Reset current cart weight + sd->cart_num = 0; // Reset current cart item count + + for(i = 0; i < MAX_CART; i++) { + if (!sd->cart.u.items_cart[i].nameid) + continue; + sd->cart_weight += itemdb_weight(sd->cart.u.items_cart[i].nameid) * sd->cart.u.items_cart[i].amount; // Recalculate current cart weight + sd->cart_num++; // Recalculate current cart item count + } + } + + // Skill bonus max weight increases + if (flag&2) + sd->cart_weight_max += (pc_checkskill(sd, GN_REMODELING_CART) * 5000); + + // Update the client if the new weight calculations don't match + if (b_cart_weight_max != sd->cart_weight_max) + clif_updatestatus(sd, SP_CARTINFO); + + return true; +} + /** * Calculates player data from scratch without counting SC adjustments * Should be invoked whenever players raise stats, learn passive skills or change equipment @@ -3023,8 +3118,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) struct status_data *base_status; ///< Pointer to the player's base status const struct status_change *sc = &sd->sc; struct s_skill b_skill[MAX_SKILL]; ///< Previous skill tree - int b_weight, b_max_weight, b_cart_weight_max, ///< Previous weight - i, skill,refinedef=0; + int i, skill, refinedef = 0; short index = -1; if (++calculating > 10) // Too many recursive calls! @@ -3032,34 +3126,18 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) // Remember player-specific values that are currently being shown to the client (for refresh purposes) memcpy(b_skill, &sd->status.skill, sizeof(b_skill)); - b_weight = sd->weight; - b_max_weight = sd->max_weight; - b_cart_weight_max = sd->cart_weight_max; pc_calc_skilltree(sd); // SkillTree calculation - sd->max_weight = job_info[pc_class2idx(sd->status.class_)].max_weight_base+sd->status.str*300; - if (opt&SCO_FIRST) { // Load Hp/SP from char-received data. sd->battle_status.hp = sd->status.hp; sd->battle_status.sp = sd->status.sp; sd->regen.sregen = &sd->sregen; sd->regen.ssregen = &sd->ssregen; - sd->weight=0; - for(i=0;istatus.inventory[i].nameid==0 || sd->inventory_data[i] == NULL) - continue; - sd->weight += sd->inventory_data[i]->weight*sd->status.inventory[i].amount; - } - sd->cart_weight=0; - sd->cart_num=0; - for(i=0;istatus.cart[i].nameid==0) - continue; - sd->cart_weight+=itemdb_weight(sd->status.cart[i].nameid)*sd->status.cart[i].amount; - sd->cart_num++; - } + + status_calc_weight(sd, 1); + status_calc_cart_weight(sd, 1); } base_status = &sd->base_status; @@ -3221,17 +3299,17 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) } // Sanitize the refine level in case someone decreased the value inbetween - if (sd->status.inventory[index].refine > MAX_REFINE) - sd->status.inventory[index].refine = MAX_REFINE; + if (sd->inventory.u.items_inventory[index].refine > MAX_REFINE) + sd->inventory.u.items_inventory[index].refine = MAX_REFINE; if (sd->inventory_data[index]->type == IT_WEAPON) { - int r = sd->status.inventory[index].refine, wlv = sd->inventory_data[index]->wlv; + int r = sd->inventory.u.items_inventory[index].refine, wlv = sd->inventory_data[index]->wlv; struct weapon_data *wd; struct weapon_atk *wa; if(wlv >= REFINE_TYPE_MAX) wlv = REFINE_TYPE_MAX - 1; - if(i == EQI_HAND_L && sd->status.inventory[index].equip == EQP_HAND_L) { + if(i == EQI_HAND_L && sd->inventory.u.items_inventory[index].equip == EQP_HAND_L) { wd = &sd->left_weapon; // Left-hand weapon wa = &base_status->lhw; } else { @@ -3260,18 +3338,18 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) if (!calculating) // Abort, run_script retriggered this. [Skotlex] return 1; } - if(sd->status.inventory[index].card[0]==CARD0_FORGE) { // Forged weapon - wd->star += (sd->status.inventory[index].card[1]>>8); + if(sd->inventory.u.items_inventory[index].card[0] == CARD0_FORGE) { // Forged weapon + wd->star += (sd->inventory.u.items_inventory[index].card[1]>>8); if(wd->star >= 15) wd->star = 40; // 3 Star Crumbs now give +40 dmg - if(pc_famerank(MakeDWord(sd->status.inventory[index].card[2],sd->status.inventory[index].card[3]) ,MAPID_BLACKSMITH)) + if(pc_famerank(MakeDWord(sd->inventory.u.items_inventory[index].card[2],sd->inventory.u.items_inventory[index].card[3]) ,MAPID_BLACKSMITH)) wd->star += 10; if (!wa->ele) // Do not overwrite element from previous bonuses. - wa->ele = (sd->status.inventory[index].card[1]&0x0f); + wa->ele = (sd->inventory.u.items_inventory[index].card[1]&0x0f); } } else if(sd->inventory_data[index]->type == IT_ARMOR) { int r; - if ( (r = sd->status.inventory[index].refine) ) + if ( (r = sd->inventory.u.items_inventory[index].refine) ) refinedef += refine_info[REFINE_TYPE_ARMOR].bonus[r-1]; if(sd->inventory_data[index]->script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) || !itemdb_isNoEquip(sd->inventory_data[index],sd->bl.m))) { if( i == EQI_HAND_L ) // Shield @@ -3356,10 +3434,10 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) struct item_data *data; // Card script execution. - if (itemdb_isspecial(sd->status.inventory[index].card[0])) + if (itemdb_isspecial(sd->inventory.u.items_inventory[index].card[0])) continue; for (j = 0; j < MAX_SLOTS; j++) { // Uses MAX_SLOTS to support Soul Bound system [Inkfish] - int c = sd->status.inventory[index].card[j]; + int c = sd->inventory.u.items_inventory[index].card[j]; current_equip_card_id= c; if(!c) continue; @@ -3375,7 +3453,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) continue; if(!pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) && itemdb_isNoEquip(data,sd->bl.m)) // Card restriction checks. continue; - if(i == EQI_HAND_L && sd->status.inventory[index].equip == EQP_HAND_L) { // Left hand status. + if(i == EQI_HAND_L && sd->inventory.u.items_inventory[index].equip == EQP_HAND_L) { // Left hand status. sd->state.lr_flag = 1; run_script(data->script,0,sd->bl.id,0); sd->state.lr_flag = 0; @@ -3702,18 +3780,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) // ----- MISC CALCULATIONS ----- // Weight - if((skill=pc_checkskill(sd,MC_INCCARRY))>0) - sd->max_weight += 2000*skill; - if(pc_isriding(sd) && pc_checkskill(sd,KN_RIDING)>0) - sd->max_weight += 10000; - else if(pc_isridingdragon(sd)) - sd->max_weight += 5000+2000*pc_checkskill(sd,RK_DRAGONTRAINING); - if(sc->data[SC_KNOWLEDGE]) - sd->max_weight += sd->max_weight*sc->data[SC_KNOWLEDGE]->val1/10; - if((skill=pc_checkskill(sd,ALL_INCCARRY))>0) - sd->max_weight += 2000*skill; - - sd->cart_weight_max = battle_config.max_cart_weight + (pc_checkskill(sd, GN_REMODELING_CART)*5000); + status_calc_weight(sd, 2); + status_calc_cart_weight(sd, 2); if (pc_checkskill(sd,SM_MOVINGRECOVERY)>0) sd->regen.state.walk = 1; @@ -3847,15 +3915,6 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) } if(memcmp(b_skill,sd->status.skill,sizeof(sd->status.skill))) clif_skillinfoblock(sd); - if(b_weight != sd->weight) - clif_updatestatus(sd,SP_WEIGHT); - if(b_max_weight != sd->max_weight) { - clif_updatestatus(sd,SP_MAXWEIGHT); - pc_updateweightstatus(sd); - } - if( b_cart_weight_max != sd->cart_weight_max ) { - clif_updatestatus(sd,SP_CARTINFO); - } // If the skill is learned, the status is infinite. if( (skill = pc_checkskill(sd,SU_SPRITEMABLE)) > 0 ) diff --git a/src/map/status.h b/src/map/status.h index 0eab96e77a..795c187038 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -2208,6 +2208,8 @@ void status_change_clear_onChangeMap(struct block_list *bl, struct status_change #define status_calc_elemental(ed, opt) status_calc_bl_(&(ed)->bl, SCB_ALL, opt) #define status_calc_npc(nd, opt) status_calc_bl_(&(nd)->bl, SCB_ALL, opt) +bool status_calc_weight(struct map_session_data *sd, uint8 flag); +bool status_calc_cart_weight(struct map_session_data *sd, uint8 flag); void status_calc_bl_(struct block_list *bl, enum scb_flag flag, enum e_status_calc_opt opt); int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt); void status_calc_pet_(struct pet_data* pd, enum e_status_calc_opt opt); diff --git a/src/map/storage.c b/src/map/storage.c index 4de0303222..e8a588bf9c 100644 --- a/src/map/storage.c +++ b/src/map/storage.c @@ -84,10 +84,10 @@ void do_final_storage(void) */ static int storage_reconnect_sub(DBKey key, DBData *data, va_list ap) { - struct guild_storage *stor = (struct guild_storage *)db_data2ptr(data); + struct s_storage *stor = db_data2ptr(data); - if (stor->dirty && stor->opened == 0) //Save closed storages. - gstorage_storagesave(0, stor->guild_id,0); + if (stor->dirty && stor->status == 0) //Save closed storages. + storage_guild_storagesave(0, stor->id, 0); return 0; } @@ -119,9 +119,9 @@ int storage_storageopen(struct map_session_data *sd) } 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); + storage_sortitem(sd->storage.u.items_storage, ARRAYLENGTH(sd->storage.u.items_storage)); + clif_storagelist(sd, sd->storage.u.items_storage, ARRAYLENGTH(sd->storage.u.items_storage)); + clif_updatestorageamount(sd, sd->storage.amount, sd->storage_size); return 0; } @@ -162,7 +162,7 @@ int compare_item(struct item *a, struct item *b) */ static int storage_additem(struct map_session_data* sd, struct item* item_data, int amount) { - struct storage_data* stor = &sd->status.storage; + struct s_storage* stor = &sd->storage; struct item_data *data; int i; @@ -186,12 +186,12 @@ static int storage_additem(struct map_session_data* sd, struct item* item_data, 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 ) ) + if( compare_item(&stor->u.items_storage[i], item_data) ) { // existing items found, stack them + if( amount > MAX_AMOUNT - stor->u.items_storage[i].amount || ( data->stack.storage && amount > data->stack.amount - stor->u.items_storage[i].amount ) ) return 1; - stor->items[i].amount += amount; - clif_storageitemadded(sd,&stor->items[i],i,amount); + stor->u.items_storage[i].amount += amount; + clif_storageitemadded(sd,&stor->u.items_storage[i],i,amount); return 0; } @@ -199,16 +199,16 @@ static int storage_additem(struct map_session_data* sd, struct item* item_data, } // find free slot - ARR_FIND( 0, sd->storage_size, i, stor->items[i].nameid == 0 ); + ARR_FIND( 0, sd->storage_size, i, stor->u.items_storage[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); + memcpy(&stor->u.items_storage[i],item_data,sizeof(stor->u.items_storage[0])); + stor->amount++; + stor->u.items_storage[i].amount = amount; + clif_storageitemadded(sd,&stor->u.items_storage[i],i,amount); + clif_updatestorageamount(sd, stor->amount, sd->storage_size); return 0; } @@ -222,17 +222,16 @@ static int storage_additem(struct map_session_data* sd, struct item* item_data, */ 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 ) + if( sd->storage.u.items_storage[n].nameid == 0 || sd->storage.u.items_storage[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--; + sd->storage.u.items_storage[n].amount -= amount; + if( sd->storage.u.items_storage[n].amount == 0 ) { + memset(&sd->storage.u.items_storage[n],0,sizeof(sd->storage.u.items_storage[0])); + sd->storage.amount--; if( sd->state.storage_flag == 1 ) - clif_updatestorageamount(sd, sd->status.storage.storage_amount, sd->storage_size); + clif_updatestorageamount(sd, sd->storage.amount, sd->storage_size); } if( sd->state.storage_flag == 1 ) @@ -252,19 +251,19 @@ void storage_storageadd(struct map_session_data* sd, int index, int amount) { nullpo_retv(sd); - if( sd->status.storage.storage_amount > sd->storage_size ) + if( sd->storage.amount > sd->storage_size ) return; // storage full if( index < 0 || index >= MAX_INVENTORY ) return; - if( sd->status.inventory[index].nameid <= 0 ) + if( sd->inventory.u.items_inventory[index].nameid <= 0 ) return; // No item on that spot - if( amount < 1 || amount > sd->status.inventory[index].amount ) + if( amount < 1 || amount > sd->inventory.u.items_inventory[index].amount ) return; - if( storage_additem(sd,&sd->status.inventory[index],amount) == 0 ) + if( storage_additem(sd,&sd->inventory.u.items_inventory[index],amount) == 0 ) pc_delitem(sd,index,amount,0,4,LOG_TYPE_STORAGE); else { clif_storageitemremoved(sd,index,0); @@ -286,13 +285,13 @@ void storage_storageget(struct map_session_data* sd, int index, int amount) if( index < 0 || index >= sd->storage_size ) return; - if( sd->status.storage.items[index].nameid <= 0 ) + if( sd->storage.u.items_storage[index].nameid <= 0 ) return; //Nothing there - if( amount < 1 || amount > sd->status.storage.items[index].amount ) + if( amount < 1 || amount > sd->storage.u.items_storage[index].amount ) return; - if( (flag = pc_additem(sd,&sd->status.storage.items[index],amount,LOG_TYPE_STORAGE)) == 0 ) + if( (flag = pc_additem(sd,&sd->storage.u.items_storage[index],amount,LOG_TYPE_STORAGE)) == 0 ) storage_delitem(sd,index,amount); else { clif_storageitemremoved(sd,index,0); @@ -311,19 +310,19 @@ void storage_storageaddfromcart(struct map_session_data* sd, int index, int amou { nullpo_retv(sd); - if( sd->status.storage.storage_amount > sd->storage_size ) + if( sd->storage.amount > sd->storage_size ) return; // storage full / storage closed if( index < 0 || index >= MAX_CART ) return; - if( sd->status.cart[index].nameid <= 0 ) + if( sd->cart.u.items_cart[index].nameid <= 0 ) return; //No item there. - if( amount < 1 || amount > sd->status.cart[index].amount ) + if( amount < 1 || amount > sd->cart.u.items_cart[index].amount ) return; - if( storage_additem(sd,&sd->status.cart[index],amount) == 0 ) + if( storage_additem(sd,&sd->cart.u.items_cart[index],amount) == 0 ) pc_cart_delitem(sd,index,amount,0,LOG_TYPE_STORAGE); else { clif_storageitemremoved(sd,index,0); @@ -347,13 +346,13 @@ void storage_storagegettocart(struct map_session_data* sd, int index, int amount if( index < 0 || index >= sd->storage_size ) return; - if( sd->status.storage.items[index].nameid <= 0 ) + if( sd->storage.u.items_storage[index].nameid <= 0 ) return; //Nothing there. - if( amount < 1 || amount > sd->status.storage.items[index].amount ) + if( amount < 1 || amount > sd->storage.u.items_storage[index].amount ) return; - if( (flag = pc_cart_additem(sd,&sd->status.storage.items[index],amount,LOG_TYPE_STORAGE)) == 0 ) + if( (flag = pc_cart_additem(sd,&sd->storage.u.items_storage[index],amount,LOG_TYPE_STORAGE)) == 0 ) storage_delitem(sd,index,amount); else { clif_storageitemremoved(sd,index,0); @@ -373,15 +372,15 @@ void storage_storageclose(struct map_session_data* sd) clif_storageclose(sd); - if( save_settings&4 ) - chrif_save(sd,0); //Invokes the storage saving as well. + if (save_settings&CHARSAVE_STORAGE) + chrif_save(sd,0); sd->state.storage_flag = 0; } /** * Force closing the storage for player without displaying result - * (exemple when quitting the game) + * (example when quitting the game) * @param sd : player to close storage * @param flag : * 1: Character is quitting @@ -391,8 +390,8 @@ void storage_storage_quit(struct map_session_data* sd, int flag) { nullpo_retv(sd); - if (save_settings&4) - chrif_save(sd, flag); //Invokes the storage saving as well. + if (save_settings&CHARSAVE_STORAGE) + chrif_save(sd,0); sd->state.storage_flag = 0; } @@ -406,10 +405,11 @@ void storage_storage_quit(struct map_session_data* sd, int flag) */ static DBData create_guildstorage(DBKey key, va_list args) { - struct guild_storage *gs = NULL; + struct s_storage *gs = NULL; - gs = (struct guild_storage *) aCalloc(sizeof(struct guild_storage), 1); - gs->guild_id=key.i; + gs = (struct s_storage *) aCalloc(sizeof(struct s_storage), 1); + gs->type = TABLE_GUILD_STORAGE; + gs->id = key.i; return db_ptr2data(gs); } @@ -418,27 +418,27 @@ static DBData create_guildstorage(DBKey key, va_list args) * Retrieve the guild_storage of a guild * will create a new storage if none found for the guild * @param guild_id : id of the guild - * @return guild_storage + * @return s_storage */ -struct guild_storage *gstorage_guild2storage(int guild_id) +struct s_storage *guild2storage(int guild_id) { - struct guild_storage *gs = NULL; + struct s_storage *gs = NULL; if (guild_search(guild_id) != NULL) - gs = (struct guild_storage *)idb_ensure(guild_storage_db,guild_id,create_guildstorage); + gs = (struct s_storage *)idb_ensure(guild_storage_db,guild_id,create_guildstorage); return gs; } /** - * See if the guild_storage exist in db and fetch it if it,s the case + * See if the guild_storage exist in db and fetch it if it's the case * @author : [Skotlex] * @param guild_id : guild_id to search the storage - * @return guild_storage or NULL + * @return s_storage or NULL */ -struct guild_storage *gstorage_get_storage(int guild_id) +struct s_storage *guild2storage2(int guild_id) { - return (struct guild_storage*)idb_get(guild_storage_db,guild_id); + return (struct s_storage*)idb_get(guild_storage_db,guild_id); } /** @@ -446,7 +446,7 @@ struct guild_storage *gstorage_get_storage(int guild_id) * @param guild_id : guild to remove the storage from * @return 0 */ -void gstorage_delete(int guild_id) +void storage_guild_delete(int guild_id) { idb_remove(guild_storage_db,guild_id); } @@ -456,9 +456,9 @@ void gstorage_delete(int guild_id) * @param sd : player * @return 0 : success, 1 : fail, 2 : no guild found */ -char gstorage_storageopen(struct map_session_data* sd) +char storage_guild_storageopen(struct map_session_data* sd) { - struct guild_storage *gstor; + struct s_storage *gstor; nullpo_ret(sd); @@ -473,22 +473,22 @@ char gstorage_storageopen(struct map_session_data* sd) return 1; } - if((gstor = gstorage_get_storage(sd->status.guild_id)) == NULL) { + if((gstor = guild2storage2(sd->status.guild_id)) == NULL) { intif_request_guild_storage(sd->status.account_id,sd->status.guild_id); return 0; } - if(gstor->opened) + if(gstor->status) return 1; - if( gstor->locked ) + if( gstor->lock ) return 1; - gstor->opened = sd->status.char_id; + gstor->status = true; 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); + storage_sortitem(gstor->u.items_guild, ARRAYLENGTH(gstor->u.items_guild)); + clif_storagelist(sd, gstor->u.items_guild, ARRAYLENGTH(gstor->u.items_guild)); + clif_updatestorageamount(sd, gstor->amount, MAX_GUILD_STORAGE); return 0; } @@ -501,41 +501,41 @@ char gstorage_storageopen(struct map_session_data* sd) * @param amount : number of item to add * @return True : success, False : fail */ -bool gstorage_additem(struct map_session_data* sd, struct guild_storage* stor, struct item* item, int amount) +bool storage_guild_additem(struct map_session_data* sd, struct s_storage* stor, struct item* item_data, int amount) { struct item_data *id; int i; nullpo_ret(sd); nullpo_ret(stor); - nullpo_ret(item); + nullpo_ret(item_data); - if(item->nameid == 0 || amount <= 0) + if(item_data->nameid == 0 || amount <= 0) return false; - id = itemdb_search(item->nameid); + id = itemdb_search(item_data->nameid); if( id->stack.guildstorage && amount > id->stack.amount ) // item stack limitation return false; - if( !itemdb_canguildstore(item, pc_get_group_level(sd)) || item->expire_time ) { // Check if item is storable. [Skotlex] + 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 false; } - if( (item->bound == BOUND_ACCOUNT || item->bound > BOUND_GUILD) && !pc_can_give_bounded_items(sd) ) { + 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 false; } if(itemdb_isstackable2(id)) { //Stackable - for(i = 0; i < MAX_GUILD_STORAGE; i++){ - 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 ) ) + for(i = 0; i < MAX_GUILD_STORAGE; i++) { + if(compare_item(&stor->u.items_guild[i], item_data)) { + if( amount > MAX_AMOUNT - stor->u.items_guild[i].amount || ( id->stack.guildstorage && amount > id->stack.amount - stor->u.items_guild[i].amount ) ) return false; - - stor->items[i].amount+=amount; - clif_storageitemadded(sd,&stor->items[i],i,amount); + + stor->u.items_guild[i].amount += amount; + clif_storageitemadded(sd,&stor->u.items_guild[i],i,amount); stor->dirty = true; return true; } @@ -543,15 +543,15 @@ bool gstorage_additem(struct map_session_data* sd, struct guild_storage* stor, s } //Add item - for(i = 0; i < MAX_GUILD_STORAGE && stor->items[i].nameid; i++); + for(i = 0; i < MAX_GUILD_STORAGE && stor->u.items_guild[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++; - clif_storageitemadded(sd,&stor->items[i],i,amount); - clif_updatestorageamount(sd, stor->storage_amount, MAX_GUILD_STORAGE); + memcpy(&stor->u.items_guild[i],item_data,sizeof(stor->u.items_guild[0])); + stor->u.items_guild[i].amount = amount; + stor->amount++; + clif_storageitemadded(sd,&stor->u.items_guild[i],i,amount); + clif_updatestorageamount(sd, stor->amount, MAX_GUILD_STORAGE); stor->dirty = true; return true; } @@ -563,7 +563,7 @@ bool gstorage_additem(struct map_session_data* sd, struct guild_storage* stor, s * @param amount : number of item to add * @return True : success, False : fail */ -bool gstorage_additem2(struct guild_storage* stor, struct item* item, int amount) { +bool storage_guild_additem2(struct s_storage* stor, struct item* item, int amount) { struct item_data *id; int i; @@ -578,13 +578,12 @@ bool gstorage_additem2(struct guild_storage* stor, struct item* item, int amount if (itemdb_isstackable2(id)) { // Stackable for (i = 0; i < MAX_GUILD_STORAGE; i++) { - if (compare_item(&stor->items[i], item)) { + if (compare_item(&stor->u.items_guild[i], item)) { // Set the amount, make it fit with max amount - int da = ((id->stack.guildstorage) ? id->stack.amount : MAX_AMOUNT) - stor->items[i].amount; - amount = min(amount, da); + amount = min(amount, ((id->stack.guildstorage) ? id->stack.amount : MAX_AMOUNT) - stor->u.items_guild[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; + ShowWarning("storage_guild_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->u.items_guild[i].amount += amount; stor->dirty = true; return true; } @@ -592,13 +591,13 @@ bool gstorage_additem2(struct guild_storage* stor, struct item* item, int amount } // Add the item - for (i = 0; i < MAX_GUILD_STORAGE && stor->items[i].nameid; i++); + for (i = 0; i < MAX_GUILD_STORAGE && stor->u.items_guild[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++; + memcpy(&stor->u.items_guild[i], item, sizeof(stor->u.items_guild[0])); + stor->u.items_guild[i].amount = amount; + stor->amount++; stor->dirty = true; return true; } @@ -611,20 +610,20 @@ bool gstorage_additem2(struct guild_storage* stor, struct item* item, int amount * @param amount : number of item to delete * @return True : success, False : fail */ -bool gstorage_delitem(struct map_session_data* sd, struct guild_storage* stor, int n, int amount) +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->items[n].nameid == 0 || stor->items[n].amount < amount) + if(!stor->u.items_guild[n].nameid || stor->u.items_guild[n].amount < amount) return false; - stor->items[n].amount -= amount; + stor->u.items_guild[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); + 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); @@ -637,31 +636,31 @@ bool gstorage_delitem(struct map_session_data* sd, struct guild_storage* stor, i * @param sd : player * @param amount : number of item to delete */ -void gstorage_storageadd(struct map_session_data* sd, int index, int amount) +void storage_guild_storageadd(struct map_session_data* sd, int index, int amount) { - struct guild_storage *stor; + struct s_storage *stor; nullpo_retv(sd); - nullpo_retv(stor = gstorage_get_storage(sd->status.guild_id)); + nullpo_retv(stor = guild2storage2(sd->status.guild_id)); - if( !stor->opened || stor->opened != sd->status.char_id || stor->storage_amount > MAX_GUILD_STORAGE ) + if( !stor->status || stor->amount > MAX_GUILD_STORAGE ) return; if( index < 0 || index >= MAX_INVENTORY ) return; - if( sd->status.inventory[index].nameid == 0 ) + if( sd->inventory.u.items_inventory[index].nameid == 0 ) return; - if( amount < 1 || amount > sd->status.inventory[index].amount ) + if( amount < 1 || amount > sd->inventory.u.items_inventory[index].amount ) return; - if( stor->locked ) { - gstorage_storageclose(sd); + if( stor->lock ) { + storage_guild_storageclose(sd); return; } - if(gstorage_additem(sd,stor,&sd->status.inventory[index],amount)) + if(!storage_guild_additem(sd,stor,&sd->inventory.u.items_inventory[index],amount)) pc_delitem(sd,index,amount,0,4,LOG_TYPE_GSTORAGE); else { clif_storageitemremoved(sd,index,0); @@ -676,33 +675,33 @@ void gstorage_storageadd(struct map_session_data* sd, int index, int amount) * @param amount : number of item to get * @return 1:success, 0:fail */ -void gstorage_storageget(struct map_session_data* sd, int index, int amount) +void storage_guild_storageget(struct map_session_data* sd, int index, int amount) { - struct guild_storage *stor; + struct s_storage *stor; unsigned char flag = 0; nullpo_retv(sd); - nullpo_retv(stor = gstorage_get_storage(sd->status.guild_id)); + nullpo_retv(stor = guild2storage2(sd->status.guild_id)); - if(!stor->opened || stor->opened != sd->status.char_id) + if(!stor->status) return; if(index < 0 || index >= MAX_GUILD_STORAGE) return; - if(stor->items[index].nameid == 0) + if(stor->u.items_guild[index].nameid == 0) return; - if(amount < 1 || amount > stor->items[index].amount) + if(amount < 1 || amount > stor->u.items_guild[index].amount) return; - if( stor->locked ) { - gstorage_storageclose(sd); + if( stor->lock ) { + storage_guild_storageclose(sd); return; } - if((flag = pc_additem(sd,&stor->items[index],amount,LOG_TYPE_GSTORAGE)) == 0) - gstorage_delitem(sd,stor,index,amount); + if((flag = pc_additem(sd,&stor->u.items_guild[index],amount,LOG_TYPE_GSTORAGE)) == 0) + storage_guild_delitem(sd,stor,index,amount); else { // inform fail clif_storageitemremoved(sd,index,0); clif_additem(sd,0,0,flag); @@ -715,26 +714,26 @@ void gstorage_storageget(struct map_session_data* sd, int index, int amount) * @param index : index of item in cart * @param amount : number of item to transfer */ -void gstorage_storageaddfromcart(struct map_session_data* sd, int index, int amount) +void storage_guild_storageaddfromcart(struct map_session_data* sd, int index, int amount) { - struct guild_storage *stor; + struct s_storage *stor; nullpo_retv(sd); - nullpo_retv(stor = gstorage_get_storage(sd->status.guild_id)); + nullpo_retv(stor = guild2storage2(sd->status.guild_id)); - if( !stor->opened || stor->opened != sd->status.char_id || stor->storage_amount > MAX_GUILD_STORAGE ) + if( !stor->status || stor->amount > MAX_GUILD_STORAGE ) return; if( index < 0 || index >= MAX_CART ) return; - if( sd->status.cart[index].nameid == 0 ) + if( sd->cart.u.items_cart[index].nameid == 0 ) return; - if( amount < 1 || amount > sd->status.cart[index].amount ) + if( amount < 1 || amount > sd->cart.u.items_cart[index].amount ) return; - if(gstorage_additem(sd,stor,&sd->status.cart[index],amount)) + if(!storage_guild_additem(sd,stor,&sd->cart.u.items_cart[index],amount)) pc_cart_delitem(sd,index,amount,0,LOG_TYPE_GSTORAGE); else { clif_storageitemremoved(sd,index,0); @@ -749,28 +748,28 @@ void gstorage_storageaddfromcart(struct map_session_data* sd, int index, int amo * @param amount : number of item to transfer * @return 1:fail, 0:success */ -void gstorage_storagegettocart(struct map_session_data* sd, int index, int amount) +void storage_guild_storagegettocart(struct map_session_data* sd, int index, int amount) { short flag; - struct guild_storage *stor; + struct s_storage *stor; nullpo_retv(sd); - nullpo_retv(stor = gstorage_get_storage(sd->status.guild_id)); + nullpo_retv(stor = guild2storage2(sd->status.guild_id)); - if(!stor->opened || stor->opened != sd->status.char_id) + if(!stor->status) return; if(index < 0 || index >= MAX_GUILD_STORAGE) return; - if(stor->items[index].nameid == 0) + if(stor->u.items_guild[index].nameid == 0) return; - if(amount < 1 || amount > stor->items[index].amount) + if(amount < 1 || amount > stor->u.items_guild[index].amount) return; - if((flag = pc_cart_additem(sd,&stor->items[index],amount,LOG_TYPE_GSTORAGE)) == 0) - gstorage_delitem(sd,stor,index,amount); + if((flag = pc_cart_additem(sd,&stor->u.items_guild[index],amount,LOG_TYPE_GSTORAGE)) == 0) + storage_guild_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); @@ -784,13 +783,13 @@ void gstorage_storagegettocart(struct map_session_data* sd, int index, int amoun * @param flag : 1=char quitting, close the storage * @return False : fail (no storage), True : success (requested) */ -bool gstorage_storagesave(uint32 account_id, int guild_id, int flag) +bool storage_guild_storagesave(uint32 account_id, int guild_id, int flag) { - struct guild_storage *stor = gstorage_get_storage(guild_id); + struct s_storage *stor = guild2storage2(guild_id); if (stor) { if (flag) //Char quitting, close it. - stor->opened = 0; + stor->status = false; if (stor->dirty) intif_send_guild_storage(account_id,stor); @@ -805,12 +804,12 @@ bool gstorage_storagesave(uint32 account_id, int guild_id, int flag) * ACK save of guild storage * @param guild_id : guild to use the storage */ -void gstorage_storagesaved(int guild_id) +void storage_guild_storagesaved(int guild_id) { - struct guild_storage *stor; + struct s_storage *stor; - if ((stor = gstorage_get_storage(guild_id)) != NULL) { - if (stor->dirty && stor->opened == 0) // Storage has been correctly saved. + if ((stor = guild2storage2(guild_id)) != NULL) { + if (stor->dirty && !stor->status) // Storage has been correctly saved. stor->dirty = false; } } @@ -819,21 +818,21 @@ void gstorage_storagesaved(int guild_id) * Close storage for player then save it * @param sd : player */ -void gstorage_storageclose(struct map_session_data* sd) +void storage_guild_storageclose(struct map_session_data* sd) { - struct guild_storage *stor; + struct s_storage *stor; nullpo_retv(sd); - nullpo_retv(stor = gstorage_get_storage(sd->status.guild_id)); + nullpo_retv(stor = guild2storage2(sd->status.guild_id)); clif_storageclose(sd); - if (stor->opened) { + if (stor->status) { if (save_settings&CHARSAVE_STORAGE) chrif_save(sd, 0); //This one also saves the storage. [Skotlex] else - gstorage_storagesave(sd->status.account_id, sd->status.guild_id,0); + storage_guild_storagesave(sd->status.account_id, sd->status.guild_id,0); - stor->opened = 0; + stor->status = false; } sd->state.storage_flag = 0; @@ -844,31 +843,31 @@ void gstorage_storageclose(struct map_session_data* sd) * @param sd * @param flag */ -void gstorage_storage_quit(struct map_session_data* sd, int flag) +void storage_guild_storage_quit(struct map_session_data* sd, int flag) { - struct guild_storage *stor; + struct s_storage *stor; nullpo_retv(sd); - nullpo_retv(stor = gstorage_get_storage(sd->status.guild_id)); + nullpo_retv(stor = guild2storage2(sd->status.guild_id)); - if (flag) { // Only during a guild break flag is 1 (don't save storage) - sd->state.storage_flag = 0; - stor->opened = 0; + if (flag) { //Only during a guild break flag is 1 (don't save storage) clif_storageclose(sd); if (save_settings&CHARSAVE_STORAGE) chrif_save(sd,0); + sd->state.storage_flag = 0; + stor->status = false; return; } - if (stor->opened) { + if (stor->status) { if (save_settings&CHARSAVE_STORAGE) chrif_save(sd,0); else - gstorage_storagesave(sd->status.account_id,sd->status.guild_id,1); + storage_guild_storagesave(sd->status.account_id,sd->status.guild_id,1); } sd->state.storage_flag = 0; - stor->opened = 0; + stor->status = false; } diff --git a/src/map/storage.h b/src/map/storage.h index 112618d528..6ef94f5259 100644 --- a/src/map/storage.h +++ b/src/map/storage.h @@ -5,8 +5,7 @@ #define _STORAGE_H_ //#include "../common/mmo.h" -struct storage_data; -struct guild_storage; +struct s_storage; struct item; //#include "map.h" struct map_session_data; @@ -24,21 +23,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* 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); +struct s_storage* guild2storage(int guild_id); +struct s_storage* guild2storage2(int guild_id); +void storage_guild_delete(int guild_id); +char storage_guild_storageopen(struct map_session_data *sd); +bool storage_guild_additem(struct map_session_data *sd,struct s_storage *stor,struct item *item_data,int amount); +bool storage_guild_additem2(struct s_storage* stor, struct item* item, int amount); +bool storage_guild_delitem(struct map_session_data *sd,struct s_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); +void storage_guild_storageclose(struct map_session_data *sd); +void storage_guild_storage_quit(struct map_session_data *sd,int flag); +bool storage_guild_storagesave(uint32 account_id, int guild_id, int flag); +void storage_guild_storagesaved(int guild_id); //Ack from char server that guild store was saved. int compare_item(struct item *a, struct item *b); diff --git a/src/map/trade.c b/src/map/trade.c index 4a4f80fe9e..1b4d8e37e6 100644 --- a/src/map/trade.c +++ b/src/map/trade.c @@ -182,7 +182,7 @@ int impossible_trade_check(struct map_session_data *sd) } // get inventory of player - memcpy(&inventory, &sd->status.inventory, sizeof(struct item) * MAX_INVENTORY); + memcpy(&inventory, &sd->inventory.u.items_inventory, sizeof(struct item) * MAX_INVENTORY); // remove this part: arrows can be trade and equipped // re-added! [celest] @@ -248,8 +248,8 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd) 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); + memcpy(&inventory, &sd->inventory.u.items_inventory, sizeof(struct item) * MAX_INVENTORY); + memcpy(&inventory2, &tsd->inventory.u.items_inventory, sizeof(struct item) * MAX_INVENTORY); // check free slot in both inventory for(trade_i = 0; trade_i < 10; trade_i++) { @@ -365,10 +365,10 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount) // Item checks... if( index < 0 || index >= MAX_INVENTORY ) return; - if( amount < 0 || amount > sd->status.inventory[index].amount ) + if( amount < 0 || amount > sd->inventory.u.items_inventory[index].amount ) return; - item = &sd->status.inventory[index]; + item = &sd->inventory.u.items_inventory[index]; src_lv = pc_get_group_level(sd); dst_lv = pc_get_group_level(target_sd); @@ -408,8 +408,8 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount) } if( sd->deal.item[trade_i].index == index ) { // The same item as before is being readjusted. - if( sd->deal.item[trade_i].amount + amount > sd->status.inventory[index].amount ) { // packet deal exploit check - amount = sd->status.inventory[index].amount - sd->deal.item[trade_i].amount; + if( sd->deal.item[trade_i].amount + amount > sd->inventory.u.items_inventory[index].amount ) { // packet deal exploit check + amount = sd->inventory.u.items_inventory[index].amount - sd->deal.item[trade_i].amount; trade_weight = sd->inventory_data[index]->weight * amount; } @@ -594,7 +594,7 @@ void trade_tradecommit(struct map_session_data *sd) if (sd->deal.item[trade_i].amount) { n = sd->deal.item[trade_i].index; - flag = pc_additem(tsd, &sd->status.inventory[n], sd->deal.item[trade_i].amount,LOG_TYPE_TRADE); + flag = pc_additem(tsd, &sd->inventory.u.items_inventory[n], sd->deal.item[trade_i].amount,LOG_TYPE_TRADE); if (flag == 0) pc_delitem(sd, n, sd->deal.item[trade_i].amount, 1, 6, LOG_TYPE_TRADE); else @@ -606,7 +606,7 @@ void trade_tradecommit(struct map_session_data *sd) if (tsd->deal.item[trade_i].amount) { n = tsd->deal.item[trade_i].index; - flag = pc_additem(sd, &tsd->status.inventory[n], tsd->deal.item[trade_i].amount,LOG_TYPE_TRADE); + flag = pc_additem(sd, &tsd->inventory.u.items_inventory[n], tsd->deal.item[trade_i].amount,LOG_TYPE_TRADE); if (flag == 0) pc_delitem(tsd, n, tsd->deal.item[trade_i].amount, 1, 6, LOG_TYPE_TRADE); else diff --git a/src/map/unit.c b/src/map/unit.c index 0383bc7baa..0a8ad538ab 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -2913,7 +2913,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) - gstorage_storage_quit(sd,0); + storage_guild_storage_quit(sd, 0); sd->state.storage_flag = 0; //Force close it when being warped. } diff --git a/src/map/vending.c b/src/map/vending.c index e297a87aad..529ef7cb0e 100755 --- a/src/map/vending.c +++ b/src/map/vending.c @@ -157,15 +157,15 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui return; } - w += itemdb_weight(vsd->status.cart[idx].nameid) * amount; + w += itemdb_weight(vsd->cart.u.items_cart[idx].nameid) * amount; if( w + sd->weight > sd->max_weight ) { clif_buyvending(sd, idx, amount, 2); // you can not buy, because overweight return; } //Check to see if cart/vend info is in sync. - if( vending[j].amount > vsd->status.cart[idx].amount ) - vending[j].amount = vsd->status.cart[idx].amount; + if( vending[j].amount > vsd->cart.u.items_cart[idx].amount ) + vending[j].amount = vsd->cart.u.items_cart[idx].amount; // if they try to add packets (example: get twice or more 2 apples if marchand has only 3 apples). // here, we check cumulative amounts @@ -177,7 +177,7 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui vending[j].amount -= amount; - switch( pc_checkadditem(sd, vsd->status.cart[idx].nameid, amount) ) { + switch( pc_checkadditem(sd, vsd->cart.u.items_cart[idx].nameid, amount) ) { case CHKADDITEM_EXIST: break; //We'd add this item to the existing one (in buyers inventory) case CHKADDITEM_NEW: @@ -202,16 +202,16 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui z = 0.; // zeny counter // vending item - pc_additem(sd, &vsd->status.cart[idx], amount, LOG_TYPE_VENDING); + pc_additem(sd, &vsd->cart.u.items_cart[idx], amount, LOG_TYPE_VENDING); vsd->vending[vend_list[i]].amount -= amount; z += ((double)vsd->vending[i].value * (double)amount); if( vsd->vending[vend_list[i]].amount ) { - if( Sql_Query( mmysql_handle, "UPDATE `%s` SET `amount` = %d WHERE `vending_id` = %d and `cartinventory_id` = %d", vending_items_db, vsd->vending[vend_list[i]].amount, vsd->vender_id, vsd->status.cart[idx].id ) != SQL_SUCCESS ) { + if( Sql_Query( mmysql_handle, "UPDATE `%s` SET `amount` = %d WHERE `vending_id` = %d and `cartinventory_id` = %d", vending_items_db, vsd->vending[vend_list[i]].amount, vsd->vender_id, vsd->cart.u.items_cart[idx].id ) != SQL_SUCCESS ) { Sql_ShowDebug( mmysql_handle ); } } else { - if( Sql_Query( mmysql_handle, "DELETE FROM `%s` WHERE `vending_id` = %d and `cartinventory_id` = %d", vending_items_db, vsd->vender_id, vsd->status.cart[idx].id ) != SQL_SUCCESS ) { + if( Sql_Query( mmysql_handle, "DELETE FROM `%s` WHERE `vending_id` = %d and `cartinventory_id` = %d", vending_items_db, vsd->vender_id, vsd->cart.u.items_cart[idx].id ) != SQL_SUCCESS ) { Sql_ShowDebug( mmysql_handle ); } } @@ -315,28 +315,16 @@ int8 vending_openvending(struct map_session_data* sd, const char* message, const if( index < 0 || index >= MAX_CART // invalid position || pc_cartitem_amount(sd, index, amount) < 0 // invalid item or insufficient quantity //NOTE: official server does not do any of the following checks! - || !sd->status.cart[index].identify // unidentified item - || sd->status.cart[index].attribute == 1 // broken item - || sd->status.cart[index].expire_time // It should not be in the cart but just in case - || (sd->status.cart[index].bound && !pc_can_give_bounded_items(sd)) // can't trade account bound items and has no permission - || !itemdb_cantrade(&sd->status.cart[index], pc_get_group_level(sd), pc_get_group_level(sd)) ) // untradeable item + || !sd->cart.u.items_cart[index].identify // unidentified item + || sd->cart.u.items_cart[index].attribute == 1 // broken item + || sd->cart.u.items_cart[index].expire_time // It should not be in the cart but just in case + || (sd->cart.u.items_cart[index].bound && !pc_can_give_bounded_items(sd)) // can't trade account bound items and has no permission + || !itemdb_cantrade(&sd->cart.u.items_cart[index], pc_get_group_level(sd), pc_get_group_level(sd)) ) // untradeable item continue; sd->vending[i].index = index; sd->vending[i].amount = amount; sd->vending[i].value = min(value, (unsigned int)battle_config.vending_max_value); - - // Player just moved item to cart and we don't have the correct cart ID yet. - if (sd->status.cart[sd->vending[i].index].id == 0) { - struct item_data *idb = itemdb_search(sd->status.cart[index].nameid); - char msg[256]; - - sprintf(msg, msg_txt(sd, 733), idb->jname); - clif_displaymessage(sd->fd, msg); - clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); - return 4; - } - i++; // item successfully added } @@ -365,7 +353,7 @@ int8 vending_openvending(struct map_session_data* sd, const char* message, const StringBuf_Init(&buf); StringBuf_Printf(&buf, "INSERT INTO `%s`(`vending_id`,`index`,`cartinventory_id`,`amount`,`price`) VALUES", vending_items_db); for (i = 0; i < count; i++) { - StringBuf_Printf(&buf, "(%d,%d,%d,%d,%d)", sd->vender_id, i, sd->status.cart[sd->vending[i].index].id, sd->vending[i].amount, sd->vending[i].value); + StringBuf_Printf(&buf, "(%d,%d,%d,%d,%d)", sd->vender_id, i, sd->cart.u.items_cart[sd->vending[i].index].id, sd->vending[i].amount, sd->vending[i].value); if (i < count-1) StringBuf_AppendStr(&buf, ","); } @@ -395,7 +383,7 @@ bool vending_search(struct map_session_data* sd, unsigned short nameid) return false; } - ARR_FIND( 0, sd->vend_num, i, sd->status.cart[sd->vending[i].index].nameid == (short)nameid ); + ARR_FIND( 0, sd->vend_num, i, sd->cart.u.items_cart[sd->vending[i].index].nameid == (short)nameid ); if( i == sd->vend_num ) { // not found return false; } @@ -419,11 +407,11 @@ bool vending_searchall(struct map_session_data* sd, const struct s_search_store_ return true; for( idx = 0; idx < s->item_count; idx++ ) { - ARR_FIND( 0, sd->vend_num, i, sd->status.cart[sd->vending[i].index].nameid == (short)s->itemlist[idx] ); + ARR_FIND( 0, sd->vend_num, i, sd->cart.u.items_cart[sd->vending[i].index].nameid == (short)s->itemlist[idx] ); if( i == sd->vend_num ) { // not found continue; } - it = &sd->status.cart[sd->vending[i].index]; + it = &sd->cart.u.items_cart[sd->vending[i].index]; if( s->min_price && s->min_price > sd->vending[i].value ) { // too low price continue; @@ -485,7 +473,7 @@ void vending_reopen( struct map_session_data* sd ) uint32 *value = (uint32*)(p + 4); // Find item position in cart - ARR_FIND(0, MAX_CART, entry->index, sd->status.cart[entry->index].id == entry->cartinventory_id); + ARR_FIND(0, MAX_CART, entry->index, sd->cart.u.items_cart[entry->index].id == entry->cartinventory_id); if (entry->index == MAX_CART) { count--; @@ -493,7 +481,7 @@ void vending_reopen( struct map_session_data* sd ) } *index = entry->index + 2; - *amount = itemdb_isstackable(sd->status.cart[entry->index].nameid) ? entry->amount : 1; + *amount = itemdb_isstackable(sd->cart.u.items_cart[entry->index].nameid) ? entry->amount : 1; *value = entry->price; p += 8; From cedc56f74a9c83eb3f43cb5d321c1f49e725576a Mon Sep 17 00:00:00 2001 From: aleos89 Date: Thu, 7 Apr 2016 10:01:13 -0400 Subject: [PATCH 02/22] Resolved compile errors for 2015 clients * Refactored some missing inventory checks from recent updates. --- src/map/clif.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/map/clif.c b/src/map/clif.c index d7064904b1..43bbf1fc31 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -2508,7 +2508,7 @@ void clif_additem(struct map_session_data *sd, int n, int amount, unsigned char #if PACKETVER >= 20071002 WFIFOW(fd,offs+27) = 0; // HireExpireDate #if PACKETVER >= 20150226 - clif_add_random_options(WFIFOP(fd,offs+31), &sd->status.inventory[n]); + clif_add_random_options(WFIFOP(fd,offs+31), &sd->inventory.u.items_inventory[n]); #endif #endif } @@ -2544,7 +2544,7 @@ void clif_additem(struct map_session_data *sd, int n, int amount, unsigned char WFIFOW(fd,offs+27)=(sd->inventory.u.items_inventory[n].bound && !itemdb_isstackable(sd->inventory.u.items_inventory[n].nameid)) ? BOUND_DISPYELLOW : sd->inventory_data[n]->flag.bindOnEquip ? BOUND_ONEQUIP : 0; #endif #if PACKETVER >= 20150226 - clif_add_random_options(WFIFOP(fd,31), &sd->status.inventory[n]); + clif_add_random_options(WFIFOP(fd,31), &sd->inventory.u.items_inventory[n]); #endif } @@ -4266,7 +4266,7 @@ void clif_tradeadditem(struct map_session_data* sd, struct map_session_data* tsd WBUFW(buf,15)= 0; //card (4w) WBUFW(buf,17)= 0; //card (4w) #if PACKETVER >= 20150226 - clif_add_random_options(WBUFP(buf, 19), &sd->status.inventory[index]); + clif_add_random_options(WBUFP(buf, 19), &sd->inventory.u.items_inventory[index]); #endif } else @@ -4292,7 +4292,7 @@ void clif_tradeadditem(struct map_session_data* sd, struct map_session_data* tsd WBUFB(buf,10)= sd->inventory.u.items_inventory[index].refine; //refine clif_addcards(WBUFP(buf, 11), &sd->inventory.u.items_inventory[index]); #if PACKETVER >= 20150226 - clif_add_random_options(WBUFP(buf, 19), &sd->status.inventory[index]); + clif_add_random_options(WBUFP(buf, 19), &sd->inventory.u.items_inventory[index]); #endif } WFIFOSET(fd,packet_len(cmd)); @@ -18690,8 +18690,8 @@ void clif_parse_Oneclick_Itemidentify(int fd, struct map_session_data *sd) { // - Invalid item ID or item doesn't exist // - Item is already identified if (idx < 0 || idx >= MAX_INVENTORY || - sd->status.inventory[idx].nameid <= 0 || sd->inventory_data[idx] == NULL || - sd->status.inventory[idx].identify) + sd->inventory.u.items_inventory[idx].nameid <= 0 || sd->inventory_data[idx] == NULL || + sd->inventory.u.items_inventory[idx].identify) return; // Ignore the request - No magnifiers in inventory From 09dd7bd77fc8fccb7160173c2a3026f111809f96 Mon Sep 17 00:00:00 2001 From: aleos89 Date: Thu, 7 Apr 2016 11:04:22 -0400 Subject: [PATCH 03/22] Fixed players getting stuck in storage * Resolves an issue when the server saves character data and the character is in their storage resulting in the storage_flag being removed too early. Thanks to @stealth62! --- src/map/intif.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/map/intif.c b/src/map/intif.c index af1c2b361e..21efa8278a 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -3236,8 +3236,6 @@ static void intif_parse_StorageSaved(int fd) //ShowInfo("Inventory has been saved (AID: %d).\n", RFIFOL(fd, 2)); break; case TABLE_STORAGE: //storage - if (sd && sd->state.storage_flag == 1) - sd->state.storage_flag = 0; //ShowInfo("Storage has been saved (AID: %d).\n", RFIFOL(fd, 2)); break; case TABLE_CART: // cart From ab7324c84ca5a03e216bb3a44e658955bb9bc598 Mon Sep 17 00:00:00 2001 From: aleos89 Date: Tue, 30 Aug 2016 20:58:40 -0400 Subject: [PATCH 04/22] Resolved some compile warnings * Removed an unused variable. * Resolved an uninitialized variable issue. --- src/map/intif.c | 2 -- src/map/script.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/map/intif.c b/src/map/intif.c index 329c74629c..efd9ca5e1c 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -3228,8 +3228,6 @@ static bool intif_parse_StorageReceived(int fd) */ static void intif_parse_StorageSaved(int fd) { - TBL_PC *sd = map_id2sd(RFIFOL(fd,2)); - if (RFIFOB(fd, 6)) { switch (RFIFOB(fd, 7)) { case TABLE_INVENTORY: //inventory diff --git a/src/map/script.c b/src/map/script.c index fe414dd2db..d835dc2966 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -7377,7 +7377,7 @@ static void buildin_delitem_delete(struct map_session_data* sd, int idx, int* am { int delamount; struct item *itm = NULL; - struct s_storage *gstor; + struct s_storage *gstor = NULL; switch(loc) { case 1: // cart From 7ffb94334348e576ad9b4052742bbee5b693ee9e Mon Sep 17 00:00:00 2001 From: aleos89 Date: Wed, 31 Aug 2016 19:55:19 -0400 Subject: [PATCH 05/22] Storage optimization clean ups * Cleaned up some of the script command documentation. * Adjusted some checks to use constants. --- doc/script_commands.txt | 8 +++--- src/map/script.c | 56 ++++++++++++++++++++--------------------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 55546f10d0..681ffd4603 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -4608,7 +4608,7 @@ database. If the name is not found, nothing will be deleted. *guildstoragedelitem "",{,}; This command behaves identically to 'delitem', but deletes items from the player's -cart or storage. +cart, storage, or guild storage. If no cart is mounted, 'cartdelitem' will return -1. If player is not in a guild or storage is open, 'guildstoragedelitem' will return -1. @@ -4631,7 +4631,7 @@ See 'getitem2' for an explanation of the expanded parameters. *guildstoragedelitem2 "",,,,,,,,{,}; This command behaves identically to 'delitem2', but deletes items from the player's -cart or storage. +cart, storage, or guild storage. If no cart is mounted, 'cartdelitem2' will return -1. If player is not in a guild or storage is open, 'guildstoragedelitem2' will return -1. @@ -4668,7 +4668,7 @@ adding up strings: *guildstoragecountitem(""{,}) This command behaves identically to 'countitem', but counts items from the player's -cart, storage or guild storage. +cart, storage, or guild storage. If no cart is mounted, 'cartcountitem' will return -1. If player is not in a guild or storage is open, 'guildstoragecountitem' will return -1. @@ -4694,7 +4694,7 @@ See 'getitem2' for an explanation of the expanded parameters. *guildstoragecountitem2("",,,,,,,{,}) This command behaves identically to 'countitem2', but counts items from the player's -cart, storage or guild storage. +cart, storage, or guild storage. If no cart is mounted, 'cartcountitem2' will return -1. If player is not in a guild or storage is open, 'guildstoragecountitem2' will return -1. diff --git a/src/map/script.c b/src/map/script.c index d835dc2966..a2806c4af9 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -6522,12 +6522,12 @@ BUILDIN_FUNC(countitem) } if( !strncmp(command, "cart", 4) ) { - loc = 1; + loc = TABLE_CART; size = MAX_CART; items = sd->cart.u.items_cart; } else if( !strncmp(command, "storage", 7) ) { - loc = 2; + loc = TABLE_STORAGE; size = MAX_STORAGE; items = sd->storage.u.items_storage; } @@ -6535,7 +6535,7 @@ BUILDIN_FUNC(countitem) gstor = guild2storage2(sd->status.guild_id); if (gstor && !sd->state.storage_flag) { - loc = 3; + loc = TABLE_GUILD_STORAGE; size = MAX_GUILD_STORAGE; items = gstor->u.items_guild; } else { @@ -6548,7 +6548,7 @@ BUILDIN_FUNC(countitem) items = sd->inventory.u.items_inventory; } - if( loc == 1 && !pc_iscarton(sd) ) { + if( loc == TABLE_CART && !pc_iscarton(sd) ) { ShowError("buildin_%s: Player doesn't have cart (CID:%d).\n", command, sd->status.char_id); script_pushint(st,-1); return SCRIPT_CMD_SUCCESS; @@ -6568,7 +6568,7 @@ BUILDIN_FUNC(countitem) return SCRIPT_CMD_FAILURE; } - if (loc == 3) + if (loc == TABLE_GUILD_STORAGE) gstor->lock = true; if( !i ) { // For count/cart/storagecountitem function @@ -6601,7 +6601,7 @@ BUILDIN_FUNC(countitem) } } - if (loc == 3) { + if (loc == TABLE_GUILD_STORAGE) { storage_guild_storageclose(sd); gstor->lock = false; } @@ -7380,20 +7380,20 @@ static void buildin_delitem_delete(struct map_session_data* sd, int idx, int* am struct s_storage *gstor = NULL; switch(loc) { - case 1: // cart + case TABLE_CART: itm = &sd->cart.u.items_cart[idx]; break; - case 2: // storage + case TABLE_STORAGE: itm = &sd->storage.u.items_storage[idx]; break; - case 3: // guild storage + case TABLE_GUILD_STORAGE: { gstor = guild2storage2(sd->status.guild_id); itm = &gstor->u.items_guild[idx]; } break; - default: //inventory + default: // TABLE_INVENTORY itm = &sd->inventory.u.items_inventory[idx]; break; } @@ -7407,21 +7407,21 @@ static void buildin_delitem_delete(struct map_session_data* sd, int idx, int* am intif_delete_petdata(MakeDWord(itm->card[1], itm->card[2])); } switch(loc) { - case 1: + case TABLE_CART: pc_cart_delitem(sd,idx,delamount,0,LOG_TYPE_SCRIPT); break; - case 2: + case TABLE_STORAGE: storage_delitem(sd,idx,delamount); log_pick_pc(sd,LOG_TYPE_SCRIPT,-delamount,itm); break; - case 3: + case TABLE_GUILD_STORAGE: gstor->lock = true; storage_guild_delitem(sd, gstor, idx, delamount); log_pick_pc(sd, LOG_TYPE_SCRIPT, -delamount, itm); storage_guild_storageclose(sd); gstor->lock = false; break; - default: + default: // TABLE_INVENTORY pc_delitem(sd, idx, delamount, 0, 0, LOG_TYPE_SCRIPT); break; } @@ -7455,15 +7455,15 @@ static bool buildin_delitem_search(struct map_session_data* sd, struct item* it, } switch(loc) { - case 1: // cart + case TABLE_CART: size = MAX_CART; items = sd->cart.u.items_cart; break; - case 2: // storage + case TABLE_STORAGE: size = MAX_STORAGE; items = sd->storage.u.items_storage; break; - case 3: // guild storage + case TABLE_GUILD_STORAGE: { struct s_storage *gstor = guild2storage2(sd->status.guild_id); @@ -7471,7 +7471,7 @@ static bool buildin_delitem_search(struct map_session_data* sd, struct item* it, items = gstor->u.items_guild; } break; - default: //inventory + default: // TABLE_INVENTORY size = MAX_INVENTORY; items = sd->inventory.u.items_inventory; break; @@ -7592,11 +7592,11 @@ BUILDIN_FUNC(delitem) char* command = (char*)script_getfuncname(st); if(!strncmp(command, "cart", 4)) - loc = 1; + loc = TABLE_CART; else if(!strncmp(command, "storage", 7)) - loc = 2; + loc = TABLE_STORAGE; else if(!strncmp(command, "guildstorage", 12)) - loc = 3; + loc = TABLE_GUILD_STORAGE; if( script_hasdata(st,4) ) { @@ -7616,12 +7616,12 @@ BUILDIN_FUNC(delitem) return SCRIPT_CMD_SUCCESS; } - if (loc == 1 && !pc_iscarton(sd)) { + if (loc == TABLE_CART && !pc_iscarton(sd)) { ShowError("buildin_cartdelitem: player doesn't have cart (CID=%d).\n", sd->status.char_id); script_pushint(st, -1); return SCRIPT_CMD_FAILURE; } - if (loc == 3) { + if (loc == TABLE_GUILD_STORAGE) { struct s_storage *gstor = guild2storage2(sd->status.guild_id); if (gstor == NULL || sd->state.storage_flag) { @@ -7691,11 +7691,11 @@ BUILDIN_FUNC(delitem2) char* command = (char*)script_getfuncname(st); if(!strncmp(command, "cart", 4)) - loc = 1; + loc = TABLE_CART; else if(!strncmp(command, "storage", 7)) - loc = 2; + loc = TABLE_STORAGE; else if(!strncmp(command, "guildstorage", 12)) - loc = 3; + loc = TABLE_GUILD_STORAGE; if( script_hasdata(st,11) ) { @@ -7715,12 +7715,12 @@ BUILDIN_FUNC(delitem2) return SCRIPT_CMD_SUCCESS; } - if (loc == 1 && !pc_iscarton(sd)) { + if (loc == TABLE_CART && !pc_iscarton(sd)) { ShowError("buildin_cartdelitem: player doesn't have cart (CID=%d).\n", sd->status.char_id); script_pushint(st,-1); return SCRIPT_CMD_FAILURE; } - if (loc == 3) { + if (loc == TABLE_GUILD_STORAGE) { struct s_storage *gstor = guild2storage2(sd->status.guild_id); if (gstor == NULL || sd->state.storage_flag) { From adbabeeef5e6fcc5cef3e2242833ddbf908cca23 Mon Sep 17 00:00:00 2001 From: aleos89 Date: Tue, 6 Sep 2016 11:18:33 -0400 Subject: [PATCH 06/22] Fixed guild storage item transfers * Fixed items not getting removed from inventory/cart when transferring to guild storage. Thanks to @Jeybla! --- src/map/storage.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/map/storage.c b/src/map/storage.c index e8a588bf9c..92cadc8777 100644 --- a/src/map/storage.c +++ b/src/map/storage.c @@ -660,7 +660,7 @@ void storage_guild_storageadd(struct map_session_data* sd, int index, int amount return; } - if(!storage_guild_additem(sd,stor,&sd->inventory.u.items_inventory[index],amount)) + if(storage_guild_additem(sd,stor,&sd->inventory.u.items_inventory[index],amount)) pc_delitem(sd,index,amount,0,4,LOG_TYPE_GSTORAGE); else { clif_storageitemremoved(sd,index,0); @@ -733,7 +733,7 @@ void storage_guild_storageaddfromcart(struct map_session_data* sd, int index, in if( amount < 1 || amount > sd->cart.u.items_cart[index].amount ) return; - if(!storage_guild_additem(sd,stor,&sd->cart.u.items_cart[index],amount)) + if(storage_guild_additem(sd,stor,&sd->cart.u.items_cart[index],amount)) pc_cart_delitem(sd,index,amount,0,LOG_TYPE_GSTORAGE); else { clif_storageitemremoved(sd,index,0); From c3a308ffdb85f933af3596e4b0dc723be249c76b Mon Sep 17 00:00:00 2001 From: aleos89 Date: Tue, 6 Sep 2016 13:16:14 -0400 Subject: [PATCH 07/22] Storage types optimization fixes * Fixed guild storage getting reset on server restart. * Adjusted a guild bound item acknowledgment attempting to create guild storage data if not found. * Added expire_time to guild storage data. * Added some missing random option item checks. Thanks to @Jeybla! --- src/char/int_storage.c | 58 ++++++++++++++++++++++++++++++++++-------- src/map/intif.c | 2 +- 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/char/int_storage.c b/src/char/int_storage.c index 44d6232649..0217ff3cce 100644 --- a/src/char/int_storage.c +++ b/src/char/int_storage.c @@ -61,7 +61,8 @@ static bool inventory_fromsql(uint32 char_id, struct s_storage* p) struct item tmp_item; memset(p, 0, sizeof(struct s_storage)); //clean up memory - p->amount = 0; + p->id = char_id; + p->type = TABLE_INVENTORY; stmt = SqlStmt_Malloc(sql_handle); if (stmt == NULL) { @@ -69,11 +70,16 @@ static bool inventory_fromsql(uint32 char_id, struct s_storage* p) return false; } - // storage {`account_id`/`id`/`nameid`/`amount`/`equip`/`identify`/`refine`/`attribute`/`card0`/`card1`/`card2`/`card3`/`option_id0`/`option_val0`/`option_parm0`/`option_id1`/`option_val1`/`option_parm1`/`option_id2`/`option_val2`/`option_parm2`/`option_id3`/`option_val3`/`option_parm3`/`option_id4`/`option_val4`/`option_parm4`} + // storage {`account_id`/`id`/`nameid`/`amount`/`equip`/`identify`/`refine`/`attribute`/`expire_time`/`favorite`/`bound`/`unique_id`/`card0`/`card1`/`card2`/`card3`/`option_id0`/`option_val0`/`option_parm0`/`option_id1`/`option_val1`/`option_parm1`/`option_id2`/`option_val2`/`option_parm2`/`option_id3`/`option_val3`/`option_parm3`/`option_id4`/`option_val4`/`option_parm4`} StringBuf_Init(&buf); StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `bound`, `unique_id`"); for( i = 0; i < MAX_SLOTS; ++i ) StringBuf_Printf(&buf, ", `card%d`", i); + for( i = 0; i < MAX_ITEM_RDM_OPT; ++i ) { + StringBuf_Printf(&buf, ", `option_id%d`", i); + StringBuf_Printf(&buf, ", `option_val%d`", i); + StringBuf_Printf(&buf, ", `option_parm%d`", i); + } StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", schema_config.inventory_db, MAX_INVENTORY); if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) @@ -99,6 +105,11 @@ static bool inventory_fromsql(uint32 char_id, struct s_storage* p) SqlStmt_BindColumn(stmt,10, SQLDT_ULONGLONG, &tmp_item.unique_id, 0, NULL, NULL); for( i = 0; i < MAX_SLOTS; ++i ) SqlStmt_BindColumn(stmt, 11+i, SQLDT_USHORT, &tmp_item.card[i], 0, NULL, NULL); + for( i = 0; i < MAX_ITEM_RDM_OPT; ++i ) { + SqlStmt_BindColumn(stmt, 11+MAX_SLOTS+i*3, SQLDT_SHORT, &tmp_item.option[i].id, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 12+MAX_SLOTS+i*3, SQLDT_SHORT, &tmp_item.option[i].value, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 13+MAX_SLOTS+i*3, SQLDT_CHAR, &tmp_item.option[i].param, 0, NULL, NULL); + } for( i = 0; i < MAX_INVENTORY && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) memcpy(&p->u.items_inventory[i], &tmp_item, sizeof(tmp_item)); @@ -126,7 +137,8 @@ static bool cart_fromsql(uint32 char_id, struct s_storage* p) struct item tmp_item; memset(p, 0, sizeof(struct s_storage)); //clean up memory - p->amount = 0; + p->id = char_id; + p->type = TABLE_CART; stmt = SqlStmt_Malloc(sql_handle); if (stmt == NULL) { @@ -134,6 +146,7 @@ static bool cart_fromsql(uint32 char_id, struct s_storage* p) return false; } + // storage {`char_id`/`id`/`nameid`/`amount`/`equip`/`identify`/`refine`/`attribute`/`expire_time`/`bound`/`unique_id`/`card0`/`card1`/`card2`/`card3`/`option_id0`/`option_val0`/`option_parm0`/`option_id1`/`option_val1`/`option_parm1`/`option_id2`/`option_val2`/`option_parm2`/`option_id3`/`option_val3`/`option_parm3`/`option_id4`/`option_val4`/`option_parm4`} StringBuf_Init(&buf); StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`"); for( j = 0; j < MAX_SLOTS; ++j ) @@ -167,6 +180,11 @@ static bool cart_fromsql(uint32 char_id, struct s_storage* p) SqlStmt_BindColumn(stmt, 9, SQLDT_ULONGLONG, &tmp_item.unique_id, 0, NULL, NULL); for( i = 0; i < MAX_SLOTS; ++i ) SqlStmt_BindColumn(stmt, 10+i, SQLDT_USHORT, &tmp_item.card[i], 0, NULL, NULL); + for( i = 0; i < MAX_ITEM_RDM_OPT; ++i ) { + SqlStmt_BindColumn(stmt, 10+MAX_SLOTS+i*3, SQLDT_SHORT, &tmp_item.option[i].id, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 11+MAX_SLOTS+i*3, SQLDT_SHORT, &tmp_item.option[i].value, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 12+MAX_SLOTS+i*3, SQLDT_CHAR, &tmp_item.option[i].param, 0, NULL, NULL); + } for( i = 0; i < MAX_CART && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) memcpy(&p->u.items_cart[i], &tmp_item, sizeof(tmp_item)); @@ -194,7 +212,8 @@ static bool storage_fromsql(uint32 account_id, struct s_storage* p) struct item tmp_item; memset(p, 0, sizeof(struct s_storage)); //clean up memory - p->amount = 0; + p->id = account_id; + p->type = TABLE_STORAGE; stmt = SqlStmt_Malloc(sql_handle); if (stmt == NULL) { @@ -202,10 +221,16 @@ static bool storage_fromsql(uint32 account_id, struct s_storage* p) return false; } + // storage {`account_id`/`id`/`nameid`/`amount`/`equip`/`identify`/`refine`/`attribute`/`card0`/`card1`/`card2`/`card3`/`option_id0`/`option_val0`/`option_parm0`/`option_id1`/`option_val1`/`option_parm1`/`option_id2`/`option_val2`/`option_parm2`/`option_id3`/`option_val3`/`option_parm3`/`option_id4`/`option_val4`/`option_parm4`} StringBuf_Init(&buf); StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`"); for( j = 0; j < MAX_SLOTS; ++j ) StringBuf_Printf(&buf, ", `card%d`", j); + for( i = 0; i < MAX_ITEM_RDM_OPT; ++i ) { + StringBuf_Printf(&buf, ", `option_id%d`", i); + StringBuf_Printf(&buf, ", `option_val%d`", i); + StringBuf_Printf(&buf, ", `option_parm%d`", i); + } StringBuf_Printf(&buf, " FROM `%s` WHERE `account_id`=? ORDER BY `nameid` LIMIT %d", schema_config.storage_db, account_id, MAX_STORAGE); if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) @@ -230,6 +255,11 @@ static bool storage_fromsql(uint32 account_id, struct s_storage* p) SqlStmt_BindColumn(stmt, 9, SQLDT_ULONGLONG, &tmp_item.unique_id, 0, NULL, NULL); for( i = 0; i < MAX_SLOTS; ++i ) SqlStmt_BindColumn(stmt, 10+i, SQLDT_USHORT, &tmp_item.card[i], 0, NULL, NULL); + for( i = 0; i < MAX_ITEM_RDM_OPT; ++i ) { + SqlStmt_BindColumn(stmt, 10+MAX_SLOTS+i*3, SQLDT_SHORT, &tmp_item.option[i].id, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 11+MAX_SLOTS+i*3, SQLDT_SHORT, &tmp_item.option[i].value, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 12+MAX_SLOTS+i*3, SQLDT_CHAR, &tmp_item.option[i].param, 0, NULL, NULL); + } for( i = 0; i < MAX_STORAGE && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) memcpy(&p->u.items_storage[i], &tmp_item, sizeof(tmp_item)); @@ -269,7 +299,8 @@ bool guild_storage_fromsql(int guild_id, struct s_storage* p) struct item tmp_item; memset(p, 0, sizeof(struct s_storage)); //clean up memory - p->amount = 0; + p->id = guild_id; + p->type = TABLE_GUILD_STORAGE; stmt = SqlStmt_Malloc(sql_handle); if (stmt == NULL) { @@ -277,9 +308,9 @@ bool guild_storage_fromsql(int guild_id, struct s_storage* p) return false; } - // storage {`guild_id`/`id`/`nameid`/`amount`/`equip`/`identify`/`refine`/`attribute`/`card0`/`card1`/`card2`/`card3`/`option_id0`/`option_val0`/`option_parm0`/`option_id1`/`option_val1`/`option_parm1`/`option_id2`/`option_val2`/`option_parm2`/`option_id3`/`option_val3`/`option_parm3`/`option_id4`/`option_val4`/`option_parm4`} + // storage {`guild_id`/`id`/`nameid`/`amount`/`equip`/`identify`/`refine`/`attribute`/`expire_time`/`bound`/`unique_id`/`card0`/`card1`/`card2`/`card3`/`option_id0`/`option_val0`/`option_parm0`/`option_id1`/`option_val1`/`option_parm1`/`option_id2`/`option_val2`/`option_parm2`/`option_id3`/`option_val3`/`option_parm3`/`option_id4`/`option_val4`/`option_parm4`} StringBuf_Init(&buf); - StringBuf_AppendStr(&buf, "SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`bound`,`unique_id`"); + StringBuf_AppendStr(&buf, "SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`expire_time`,`bound`,`unique_id`"); for( j = 0; j < MAX_SLOTS; ++j ) StringBuf_Printf(&buf, ",`card%d`", j); for( j = 0; j < MAX_ITEM_RDM_OPT; ++j ) { @@ -306,11 +337,16 @@ bool guild_storage_fromsql(int guild_id, struct s_storage* p) SqlStmt_BindColumn(stmt, 4, SQLDT_CHAR, &tmp_item.identify, 0, NULL, NULL); SqlStmt_BindColumn(stmt, 5, SQLDT_CHAR, &tmp_item.refine, 0, NULL, NULL); SqlStmt_BindColumn(stmt, 6, SQLDT_CHAR, &tmp_item.attribute, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 7, SQLDT_CHAR, &tmp_item.bound, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 8, SQLDT_ULONGLONG, &tmp_item.unique_id, 0, NULL, NULL); - tmp_item.expire_time = 0; + SqlStmt_BindColumn(stmt, 7, SQLDT_UINT, &tmp_item.expire_time, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 8, SQLDT_CHAR, &tmp_item.bound, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 9, SQLDT_ULONGLONG, &tmp_item.unique_id, 0, NULL, NULL); for( i = 0; i < MAX_SLOTS; ++i ) - SqlStmt_BindColumn(stmt, 9+i, SQLDT_USHORT, &tmp_item.card[i], 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 10+i, SQLDT_USHORT, &tmp_item.card[i], 0, NULL, NULL); + for( i = 0; i < MAX_ITEM_RDM_OPT; ++i ) { + SqlStmt_BindColumn(stmt, 10+MAX_SLOTS+i*3, SQLDT_SHORT, &tmp_item.option[i].id, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 11+MAX_SLOTS+i*3, SQLDT_SHORT, &tmp_item.option[i].value, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 12+MAX_SLOTS+i*3, SQLDT_CHAR, &tmp_item.option[i].param, 0, NULL, NULL); + } for( i = 0; i < MAX_GUILD_STORAGE && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) memcpy(&p->u.items_guild[i], &tmp_item, sizeof(tmp_item)); diff --git a/src/map/intif.c b/src/map/intif.c index efd9ca5e1c..7db816a701 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -3099,7 +3099,7 @@ void intif_itembound_guild_retrieve(uint32 char_id,uint32 account_id,int guild_i */ void intif_parse_itembound_ack(int fd) { int guild_id = RFIFOW(fd,6); - struct s_storage *gstor = guild2storage(guild_id); + struct s_storage *gstor = guild2storage2(guild_id); if (gstor) gstor->lock = false; //Unlock now that operation is completed } From cb252ded85483264926456ed6a62336e37ba1b9c Mon Sep 17 00:00:00 2001 From: aleos89 Date: Tue, 6 Sep 2016 14:43:52 -0400 Subject: [PATCH 08/22] Storage types optimization clean ups * Removed char_inventory_to_sql and merged differences with char_memitemdata_to_sql. Thanks to @Jeybla's suggestion! --- src/char/char.c | 222 +++++++---------------------------------- src/char/char.h | 1 - src/char/int_storage.c | 2 +- 3 files changed, 38 insertions(+), 187 deletions(-) diff --git a/src/char/char.c b/src/char/char.c index 989136ab17..5781d2ce21 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -261,8 +261,6 @@ static DBData char_create_charstatus(DBKey key, va_list args) { return db_ptr2data(cp); } -int char_inventory_to_sql(const struct item items[], int max, int id); - int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p){ int i = 0; int count = 0; @@ -520,24 +518,35 @@ int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p){ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tableswitch) { StringBuf buf; SqlStmt* stmt; - int i,j; - const char* tablename; - const char* selectoption; + int i, j, offset = 0; + const char* tablename, *selectoption; struct item item; // temp storage variable bool* flag; // bit array for inventory matching bool found; int errors = 0; switch (tableswitch) { - case TABLE_CART: tablename = schema_config.cart_db; selectoption = "char_id"; break; - case TABLE_STORAGE: tablename = schema_config.storage_db; selectoption = "account_id"; break; - case TABLE_GUILD_STORAGE: tablename = schema_config.guild_storage_db; selectoption = "guild_id"; break; + case TABLE_INVENTORY: + tablename = schema_config.inventory_db; + selectoption = "char_id"; + break; + case TABLE_CART: + tablename = schema_config.cart_db; + selectoption = "char_id"; + break; + case TABLE_STORAGE: + tablename = schema_config.storage_db; + selectoption = "account_id"; + break; + case TABLE_GUILD_STORAGE: + tablename = schema_config.guild_storage_db; + selectoption = "guild_id"; + break; default: ShowError("Invalid table name!\n"); return 1; } - // The following code compares inventory with current database values // and performs modification/deletion/insertion only on relevant rows. // This approach is more complicated than a trivial delete&insert, but @@ -545,6 +554,10 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl StringBuf_Init(&buf); StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`"); + if (tableswitch == TABLE_INVENTORY) { + StringBuf_Printf(&buf, ", `favorite`"); + offset = 1; + } for( i = 0; i < MAX_SLOTS; ++i ) StringBuf_Printf(&buf, ", `card%d`", i); @@ -575,12 +588,14 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl SqlStmt_BindColumn(stmt, 7, SQLDT_UINT, &item.expire_time, 0, NULL, NULL); SqlStmt_BindColumn(stmt, 8, SQLDT_UINT, &item.bound, 0, NULL, NULL); SqlStmt_BindColumn(stmt, 9, SQLDT_UINT64, &item.unique_id, 0, NULL, NULL); + if (tableswitch == TABLE_INVENTORY) + SqlStmt_BindColumn(stmt, 10, SQLDT_CHAR, &item.favorite, 0, NULL, NULL); for( i = 0; i < MAX_SLOTS; ++i ) - SqlStmt_BindColumn(stmt, 10+i, SQLDT_USHORT, &item.card[i], 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 10+offset+i, SQLDT_USHORT, &item.card[i], 0, NULL, NULL); for( i = 0; i < MAX_ITEM_RDM_OPT; ++i ) { - SqlStmt_BindColumn(stmt, 10+MAX_SLOTS+i*3, SQLDT_SHORT, &item.option[i].id, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 11+MAX_SLOTS+i*3, SQLDT_SHORT, &item.option[i].value, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 12+MAX_SLOTS+i*3, SQLDT_CHAR, &item.option[i].param, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 10+offset+MAX_SLOTS+i*3, SQLDT_SHORT, &item.option[i].id, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 11+offset+MAX_SLOTS+i*3, SQLDT_SHORT, &item.option[i].value, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 12+offset+MAX_SLOTS+i*3, SQLDT_CHAR, &item.option[i].param, 0, NULL, NULL); } // bit array indicating which inventory items have already been matched flag = (bool*) aCalloc(max, sizeof(bool)); @@ -614,7 +629,8 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl items[i].attribute == item.attribute && items[i].expire_time == item.expire_time && items[i].bound == item.bound && - items[i].unique_id == item.unique_id ) + items[i].unique_id == item.unique_id && + (tableswitch != TABLE_INVENTORY || items[i].favorite == item.favorite) ) ; //Do nothing. else { @@ -622,6 +638,8 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl StringBuf_Clear(&buf); StringBuf_Printf(&buf, "UPDATE `%s` SET `amount`='%d', `equip`='%d', `identify`='%d', `refine`='%d',`attribute`='%d', `expire_time`='%u', `bound`='%d', `unique_id`='%"PRIu64"'", tablename, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time, items[i].bound, items[i].unique_id); + if (tableswitch == TABLE_INVENTORY) + StringBuf_Printf(&buf, ", `favorite`='%d'", items[i].favorite); for( j = 0; j < MAX_SLOTS; ++j ) StringBuf_Printf(&buf, ", `card%d`=%hu", j, items[i].card[j]); for( j = 0; j < MAX_ITEM_RDM_OPT; ++j ) { @@ -655,6 +673,8 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl StringBuf_Clear(&buf); StringBuf_Printf(&buf, "INSERT INTO `%s`(`%s`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`", tablename, selectoption); + if (tableswitch == TABLE_INVENTORY) + StringBuf_Printf(&buf, ", `favorite`"); for( j = 0; j < MAX_SLOTS; ++j ) StringBuf_Printf(&buf, ", `card%d`", j); for( j = 0; j < MAX_ITEM_RDM_OPT; ++j ) { @@ -679,6 +699,8 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl StringBuf_Printf(&buf, "('%d', '%hu', '%d', '%d', '%d', '%d', '%d', '%u', '%d', '%"PRIu64"'", id, items[i].nameid, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time, items[i].bound, items[i].unique_id); + if (tableswitch == TABLE_INVENTORY) + StringBuf_Printf(&buf, ", '%d'", items[i].favorite); for( j = 0; j < MAX_SLOTS; ++j ) StringBuf_Printf(&buf, ", '%hu'", items[i].card[j]); for( j = 0; j < MAX_ITEM_RDM_OPT; ++j ) { @@ -695,177 +717,7 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl errors++; } - ShowInfo("Saved %s data for %s: %d\n", (tableswitch == TABLE_CART ? "Cart" : (tableswitch == TABLE_STORAGE ? "Storage" : "Guild Storage") ), selectoption, id); - - StringBuf_Destroy(&buf); - aFree(flag); - - return errors; -} -/* pretty much a copy of memitemdata_to_sql except it handles inventory_db exclusively, - * - this is required because inventory db is the only one with the 'favorite' column. */ -int char_inventory_to_sql(const struct item items[], int max, int char_id) { - StringBuf buf; - SqlStmt* stmt; - int i, j; - struct item item; // temp storage variable - bool* flag; // bit array for inventory matching - bool found; - int errors = 0; - - - // The following code compares inventory with current database values - // and performs modification/deletion/insertion only on relevant rows. - // This approach is more complicated than a trivial delete&insert, but - // it significantly reduces cpu load on the database server. - - StringBuf_Init(&buf); - StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `bound`, `unique_id`"); - for( i = 0; i < MAX_SLOTS; ++i ) - StringBuf_Printf(&buf, ", `card%d`", i); - for( i = 0; i < MAX_ITEM_RDM_OPT; ++i ) { - StringBuf_Printf(&buf, ", `option_id%d`", i); - StringBuf_Printf(&buf, ", `option_val%d`", i); - StringBuf_Printf(&buf, ", `option_parm%d`", i); - } - StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`='%d'", schema_config.inventory_db, char_id); - - stmt = SqlStmt_Malloc(sql_handle); - if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) || - SQL_ERROR == SqlStmt_Execute(stmt) ) - { - SqlStmt_ShowDebug(stmt); - SqlStmt_Free(stmt); - StringBuf_Destroy(&buf); - return 1; - } - - SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &item.id, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 1, SQLDT_USHORT, &item.nameid, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 2, SQLDT_SHORT, &item.amount, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 3, SQLDT_UINT, &item.equip, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 4, SQLDT_CHAR, &item.identify, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 5, SQLDT_CHAR, &item.refine, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 6, SQLDT_CHAR, &item.attribute, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 7, SQLDT_UINT, &item.expire_time, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 8, SQLDT_CHAR, &item.favorite, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 9, SQLDT_CHAR, &item.bound, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 10,SQLDT_UINT64, &item.unique_id, 0, NULL, NULL); - for( i = 0; i < MAX_SLOTS; ++i ) - SqlStmt_BindColumn(stmt, 11+i, SQLDT_USHORT, &item.card[i], 0, NULL, NULL); - for( i = 0; i < MAX_ITEM_RDM_OPT; ++i ) { - SqlStmt_BindColumn(stmt, 11+MAX_SLOTS+i*3, SQLDT_SHORT, &item.option[i].id, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 12+MAX_SLOTS+i*3, SQLDT_SHORT, &item.option[i].value, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 13+MAX_SLOTS+i*3, SQLDT_CHAR, &item.option[i].param, 0, NULL, NULL); - } - - // bit array indicating which inventory items have already been matched - flag = (bool*) aCalloc(max, sizeof(bool)); - - while( SQL_SUCCESS == SqlStmt_NextRow(stmt) ) { - found = false; - // search for the presence of the item in the char's inventory - for( i = 0; i < max; ++i ) { - // skip empty and already matched entries - if( items[i].nameid == 0 || flag[i] ) - continue; - - if( items[i].nameid == item.nameid - && items[i].card[0] == item.card[0] - && items[i].card[2] == item.card[2] - && items[i].card[3] == item.card[3] - ) { //They are the same item. - int k; - - ARR_FIND( 0, MAX_SLOTS, j, items[i].card[j] != item.card[j] ); - ARR_FIND( 0, MAX_ITEM_RDM_OPT, k, items[i].option[k].id != item.option[k].id || items[i].option[k].value != item.option[k].value || items[i].option[k].param != item.option[k].param ); - - if( j == MAX_SLOTS && - k == MAX_ITEM_RDM_OPT && - items[i].amount == item.amount && - items[i].equip == item.equip && - items[i].identify == item.identify && - items[i].refine == item.refine && - items[i].attribute == item.attribute && - items[i].expire_time == item.expire_time && - items[i].favorite == item.favorite && - items[i].bound == item.bound && - items[i].unique_id == item.unique_id ) - ; //Do nothing. - else { - // update all fields. - StringBuf_Clear(&buf); - StringBuf_Printf(&buf, "UPDATE `%s` SET `amount`='%d', `equip`='%d', `identify`='%d', `refine`='%d',`attribute`='%d', `expire_time`='%u', `favorite`='%d', `bound`='%d', `unique_id`='%"PRIu64"'", - schema_config.inventory_db, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time, items[i].favorite, items[i].bound, items[i].unique_id); - for( j = 0; j < MAX_SLOTS; ++j ) - StringBuf_Printf(&buf, ", `card%d`=%hu", j, items[i].card[j]); - for( j = 0; j < MAX_ITEM_RDM_OPT; ++j ) { - StringBuf_Printf(&buf, ", `option_id%d`=%d", j, items[i].option[j].id); - StringBuf_Printf(&buf, ", `option_val%d`=%d", j, items[i].option[j].value); - StringBuf_Printf(&buf, ", `option_parm%d`=%d", j, items[i].option[j].param); - } - StringBuf_Printf(&buf, " WHERE `id`='%d' LIMIT 1", item.id); - - if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) { - Sql_ShowDebug(sql_handle); - errors++; - } - } - - found = flag[i] = true; //Item dealt with, - break; //skip to next item in the db. - } - } - if( !found ) {// Item not present in inventory, remove it. - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE from `%s` where `id`='%d' LIMIT 1", schema_config.inventory_db, item.id) ) { - Sql_ShowDebug(sql_handle); - errors++; - } - } - } - SqlStmt_Free(stmt); - - StringBuf_Clear(&buf); - StringBuf_Printf(&buf, "INSERT INTO `%s` (`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `bound`, `unique_id`", schema_config.inventory_db); - for( i = 0; i < MAX_SLOTS; ++i ) - StringBuf_Printf(&buf, ", `card%d`", i); - for( i = 0; i < MAX_ITEM_RDM_OPT; ++i ) { - StringBuf_Printf(&buf, ", `option_id%d`", i); - StringBuf_Printf(&buf, ", `option_val%d`", i); - StringBuf_Printf(&buf, ", `option_parm%d`", i); - } - StringBuf_AppendStr(&buf, ") VALUES "); - - found = false; - // insert non-matched items into the db as new items - for( i = 0; i < max; ++i ) { - // skip empty and already matched entries - if( items[i].nameid == 0 || flag[i] ) - continue; - - if( found ) - StringBuf_AppendStr(&buf, ","); - else - found = true; - - StringBuf_Printf(&buf, "('%d', '%hu', '%d', '%d', '%d', '%d', '%d', '%u', '%d', '%d', '%"PRIu64"'", - char_id, items[i].nameid, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time, items[i].favorite, items[i].bound, items[i].unique_id); - for( j = 0; j < MAX_SLOTS; ++j ) - StringBuf_Printf(&buf, ", '%hu'", items[i].card[j]); - for( j = 0; j < MAX_ITEM_RDM_OPT; ++j ) { - StringBuf_Printf(&buf, ", '%d'", items[i].option[j].id); - StringBuf_Printf(&buf, ", '%d'", items[i].option[j].value); - StringBuf_Printf(&buf, ", '%d'", items[i].option[j].param); - } - StringBuf_AppendStr(&buf, ")"); - } - - if( found && SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) { - Sql_ShowDebug(sql_handle); - errors++; - } - - ShowInfo("Saved Inventory data for char_id: %d.\n", char_id); + ShowInfo("Saved %s data for %s: %d\n", (tableswitch == TABLE_INVENTORY ? "Inventory" : (tableswitch == TABLE_CART ? "Cart" : (tableswitch == TABLE_STORAGE ? "Storage" : "Guild Storage"))), selectoption, id); StringBuf_Destroy(&buf); aFree(flag); diff --git a/src/char/char.h b/src/char/char.h index a0be0a60a2..4993fb0e30 100644 --- a/src/char/char.h +++ b/src/char/char.h @@ -257,7 +257,6 @@ int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf); int char_delete_char_sql(uint32 char_id); int char_rename_char_sql(struct char_session_data *sd, uint32 char_id); int char_divorce_char_sql(int partner_id1, int partner_id2); -int char_inventory_to_sql(const struct item items[], int max, int char_id); int char_memitemdata_to_sql(const struct item items[], int max, int id, int tableswitch); void disconnect_player(uint32 account_id); diff --git a/src/char/int_storage.c b/src/char/int_storage.c index 0217ff3cce..efb88517b3 100644 --- a/src/char/int_storage.c +++ b/src/char/int_storage.c @@ -22,7 +22,7 @@ */ static int inventory_tosql(uint32 char_id, struct s_storage* p) { - return char_inventory_to_sql(p->u.items_inventory, MAX_INVENTORY, char_id); + return char_memitemdata_to_sql(p->u.items_inventory, MAX_INVENTORY, char_id, TABLE_INVENTORY); } /** From 17946ea28665709465a3855c59d310bee9c4b7a1 Mon Sep 17 00:00:00 2001 From: Cydh Ramdh Date: Sun, 11 Sep 2016 06:40:03 +0700 Subject: [PATCH 09/22] Fixed Cart save issue for vending (#1551) * Added check if cart need to be saved first or not before vending * Removed `id` from item struct when new item added to cart. * The `id` value from inventory is never be used, on relog, `id`s for cart are always use 'real' value from table. * 0-ing the value also prevent wrong `id` number while inserting records to `vending_items`. * Ordered by `id` whiel loading cart items from table. * Initialize `sd->inventory`, `sd->inventory`, and `sd->storage` to 0 on `pc_authok` Signed-off-by: Cydh Ramdh --- src/char/char.c | 3 ++- src/char/int_storage.c | 18 ++++++++++++++---- src/common/mmo.h | 3 ++- src/map/clif.c | 3 --- src/map/intif.c | 11 ++++++++++- src/map/pc.c | 6 +++++- src/map/pc.h | 1 + src/map/skill.c | 7 ++++++- 8 files changed, 40 insertions(+), 12 deletions(-) diff --git a/src/char/char.c b/src/char/char.c index 5781d2ce21..7b9c8f987c 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -531,6 +531,7 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl selectoption = "char_id"; break; case TABLE_CART: + case TABLE_CART_: tablename = schema_config.cart_db; selectoption = "char_id"; break; @@ -717,7 +718,7 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl errors++; } - ShowInfo("Saved %s data for %s: %d\n", (tableswitch == TABLE_INVENTORY ? "Inventory" : (tableswitch == TABLE_CART ? "Cart" : (tableswitch == TABLE_STORAGE ? "Storage" : "Guild Storage"))), selectoption, id); + ShowInfo("Saved %s data for %s: %d\n", (tableswitch == TABLE_INVENTORY ? "Inventory" : (tableswitch == TABLE_GUILD_STORAGE ? "Guild Storage" : (tableswitch == TABLE_STORAGE ? "Storage" : "Cart"))), selectoption, id); StringBuf_Destroy(&buf); aFree(flag); diff --git a/src/char/int_storage.c b/src/char/int_storage.c index efb88517b3..216638e96c 100644 --- a/src/char/int_storage.c +++ b/src/char/int_storage.c @@ -156,7 +156,7 @@ static bool cart_fromsql(uint32 char_id, struct s_storage* p) StringBuf_Printf(&buf, ", `option_val%d`", i); StringBuf_Printf(&buf, ", `option_parm%d`", i); } - StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", schema_config.cart_db, MAX_CART); + StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? ORDER BY `id` LIMIT %d", schema_config.cart_db, MAX_CART); if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) @@ -677,15 +677,22 @@ static void mapif_storage_data_loaded(int fd, uint32 account_id, char type, stru * IZ 0x388b .L .B .B * @param fd * @param account_id + * @param char_id * @param type */ -void mapif_storage_saved(int fd, uint32 account_id, bool sucess, char type) { +void mapif_storage_saved(int fd, uint32 account_id, uint32 char_id, bool sucess, char type) { WFIFOHEAD(fd,8); WFIFOW(fd, 0) = 0x388b; WFIFOL(fd, 2) = account_id; WFIFOB(fd, 6) = sucess; WFIFOB(fd, 7) = type; WFIFOSET(fd,8); + + if (type == TABLE_CART_) { + struct s_storage stor; + memset(&stor, 0, sizeof(struct s_storage)); + mapif_storage_data_loaded(fd, account_id, type, stor, cart_fromsql(char_id, &stor)); + } } /** @@ -738,10 +745,13 @@ bool mapif_parse_StorageSave(int fd) { switch(type){ case TABLE_INVENTORY: inventory_tosql(cid, &stor); break; case TABLE_STORAGE: storage_tosql(aid, &stor); break; - case TABLE_CART: cart_tosql(cid, &stor); break; + case TABLE_CART: + case TABLE_CART_: + cart_tosql(cid, &stor); + break; default: return false; } - mapif_storage_saved(fd, aid, true, type); + mapif_storage_saved(fd, aid, cid, true, type); return false; } diff --git a/src/common/mmo.h b/src/common/mmo.h index b6e1066b1a..62fac65009 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -297,8 +297,9 @@ struct skill_cooldown_data { }; enum storage_type { - TABLE_INVENTORY, + TABLE_INVENTORY = 1, TABLE_CART, + TABLE_CART_, TABLE_STORAGE, TABLE_GUILD_STORAGE, }; diff --git a/src/map/clif.c b/src/map/clif.c index 020bcc3bc4..86f66f3aed 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -6912,9 +6912,6 @@ void clif_openvendingreq(struct map_session_data* sd, int num) nullpo_retv(sd); - intif_storage_save(sd, TABLE_CART); // Save cart item data - intif_storage_request(sd, TABLE_CART); // Update cart item ID information - fd = sd->fd; WFIFOHEAD(fd,packet_len(0x12d)); WFIFOW(fd,0) = 0x12d; diff --git a/src/map/intif.c b/src/map/intif.c index 7db816a701..b4fd1ffc2f 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -3160,7 +3160,10 @@ static bool intif_parse_StorageReceived(int fd) switch (type) { case TABLE_INVENTORY: stor = &sd->inventory; break; case TABLE_STORAGE: stor = &sd->storage; break; - case TABLE_CART: stor = &sd->cart; break; + case TABLE_CART: + case TABLE_CART_: + stor = &sd->cart; + break; default: return false; } @@ -3214,6 +3217,10 @@ static bool intif_parse_StorageReceived(int fd) } break; + case TABLE_CART_: + clif_openvendingreq(sd, sd->vend_skill_lv+2); + break; + case TABLE_STORAGE: pc_check_available_item(sd, ITMCHK_STORAGE); break; @@ -3237,6 +3244,7 @@ static void intif_parse_StorageSaved(int fd) //ShowInfo("Storage has been saved (AID: %d).\n", RFIFOL(fd, 2)); break; case TABLE_CART: // cart + case TABLE_CART_: //ShowInfo("Cart has been saved (AID: %d).\n", RFIFOL(fd, 2)); break; default: @@ -3292,6 +3300,7 @@ bool intif_storage_save(struct map_session_data *sd, enum storage_type type) stor = &sd->storage; break; case TABLE_CART: + case TABLE_CART_: stor = &sd->cart; break; default: diff --git a/src/map/pc.c b/src/map/pc.c index f4d837d2f0..84e99d4e36 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1148,7 +1148,10 @@ bool pc_authok(struct map_session_data *sd, uint32 login_id2, time_t expiration_ if (!(battle_config.display_skill_fail&2)) sd->state.showdelay = 1; - pc_setequipindex(sd); // required at the moment, to complete auth_ok [lighta] + memset(&sd->inventory, 0, sizeof(struct s_storage)); + memset(&sd->cart, 0, sizeof(struct s_storage)); + memset(&sd->storage, 0, sizeof(struct s_storage)); + memset(&sd->equip_index, -1, sizeof(sd->equip_index)); if( sd->status.option&OPTION_INVISIBLE && !pc_can_use_command( sd, "hide", COMMAND_ATCOMMAND ) ){ sd->status.option &= ~OPTION_INVISIBLE; @@ -5045,6 +5048,7 @@ unsigned char pc_cart_additem(struct map_session_data *sd,struct item *item,int return 2; // no slot memcpy(&sd->cart.u.items_cart[i],item,sizeof(sd->cart.u.items_cart[0])); + sd->cart.u.items_cart[i].id = 0; sd->cart.u.items_cart[i].amount = amount; sd->cart_num++; clif_cart_additem(sd,i,amount,0); diff --git a/src/map/pc.h b/src/map/pc.h index 805e206241..5d5e78e19f 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -519,6 +519,7 @@ struct map_session_data { int vended_id; int vender_id; int vend_num; + uint16 vend_skill_lv; char message[MESSAGE_SIZE]; struct s_vending vending[MAX_VENDING]; diff --git a/src/map/skill.c b/src/map/skill.c index 0cedfbf917..a6ef4f7702 100755 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -7300,7 +7300,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui else { sd->state.prevend = 1; sd->state.workinprogress = WIP_DISABLE_ALL; - clif_openvendingreq(sd,2+skill_lv); + sd->vend_skill_lv = skill_lv; + ARR_FIND(0, MAX_CART, i, sd->cart.u.items_cart[i].nameid && sd->cart.u.items_cart[i].id == 0); + if (i < MAX_CART) + intif_storage_save(sd, TABLE_CART_); + else + clif_openvendingreq(sd,2+skill_lv); } } break; From 103ee947ff26aa850420f28271d0c931d83293f7 Mon Sep 17 00:00:00 2001 From: Lemongrass3110 Date: Mon, 10 Oct 2016 13:13:23 +0200 Subject: [PATCH 10/22] Follow up to f0dd764 Fixed compile/merge errors from 5a56210 --- src/map/script.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/map/script.c b/src/map/script.c index eba38fa00e..a249239035 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -12711,9 +12711,9 @@ BUILDIN_FUNC(successremovecards) { item_tmp.card[j]=sd->inventory.u.items_inventory[i].card[j]; for (j = 0; j < MAX_ITEM_RDM_OPT; j++){ - item_tmp.option[j].id=sd->status.inventory[i].option[j].id; - item_tmp.option[j].value=sd->status.inventory[i].option[j].value; - item_tmp.option[j].param=sd->status.inventory[i].option[j].param; + item_tmp.option[j].id=sd->inventory.u.items_inventory[i].option[j].id; + item_tmp.option[j].value=sd->inventory.u.items_inventory[i].option[j].value; + item_tmp.option[j].param=sd->inventory.u.items_inventory[i].option[j].param; } pc_delitem(sd,i,1,0,3,LOG_TYPE_SCRIPT); @@ -12790,9 +12790,9 @@ BUILDIN_FUNC(failedremovecards) { item_tmp.card[j]=sd->inventory.u.items_inventory[i].card[j]; for (j = 0; j < MAX_ITEM_RDM_OPT; j++){ - item_tmp.option[j].id=sd->status.inventory[i].option[j].id; - item_tmp.option[j].value=sd->status.inventory[i].option[j].value; - item_tmp.option[j].param=sd->status.inventory[i].option[j].param; + item_tmp.option[j].id=sd->inventory.u.items_inventory[i].option[j].id; + item_tmp.option[j].value=sd->inventory.u.items_inventory[i].option[j].value; + item_tmp.option[j].param=sd->inventory.u.items_inventory[i].option[j].param; } pc_delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT); From 800714abfe7b6e665d6997c314fc26a0ae519a7f Mon Sep 17 00:00:00 2001 From: Lemongrass3110 Date: Thu, 13 Oct 2016 23:53:34 +0200 Subject: [PATCH 11/22] Reverted a lot of e8f4500 Wasted 11 bytes of network traffic to keep the code clean. Process: 1) A player tries to open a vending store and is now in the pre-vend state. 2) If all items in the cart are saved then he can proceed to opening the store. 3) If not a request to save the cart data is sent to the inter server. 4) If the acknowledgment packet from the inter server is received then check if the player is still online and in pre-vend state and open the vending dialog --- src/char/char.c | 1 - src/char/int_storage.c | 15 +++------------ src/map/intif.c | 18 ++++++++++-------- src/map/skill.c | 2 +- 4 files changed, 14 insertions(+), 22 deletions(-) diff --git a/src/char/char.c b/src/char/char.c index 923a8b3f34..f0354d07eb 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -531,7 +531,6 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl selectoption = "char_id"; break; case TABLE_CART: - case TABLE_CART_: tablename = schema_config.cart_db; selectoption = "char_id"; break; diff --git a/src/char/int_storage.c b/src/char/int_storage.c index 216638e96c..e33d5c1676 100644 --- a/src/char/int_storage.c +++ b/src/char/int_storage.c @@ -687,12 +687,6 @@ void mapif_storage_saved(int fd, uint32 account_id, uint32 char_id, bool sucess, WFIFOB(fd, 6) = sucess; WFIFOB(fd, 7) = type; WFIFOSET(fd,8); - - if (type == TABLE_CART_) { - struct s_storage stor; - memset(&stor, 0, sizeof(struct s_storage)); - mapif_storage_data_loaded(fd, account_id, type, stor, cart_fromsql(char_id, &stor)); - } } /** @@ -743,12 +737,9 @@ bool mapif_parse_StorageSave(int fd) { //ShowInfo("Saving storage data for AID=%d.\n", aid); switch(type){ - case TABLE_INVENTORY: inventory_tosql(cid, &stor); break; - case TABLE_STORAGE: storage_tosql(aid, &stor); break; - case TABLE_CART: - case TABLE_CART_: - cart_tosql(cid, &stor); - break; + case TABLE_INVENTORY: inventory_tosql(cid, &stor); break; + case TABLE_STORAGE: storage_tosql(aid, &stor); break; + case TABLE_CART: cart_tosql(cid, &stor); break; default: return false; } mapif_storage_saved(fd, aid, cid, true, type); diff --git a/src/map/intif.c b/src/map/intif.c index 92f69aea93..81ee6f9164 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -3163,7 +3163,6 @@ static bool intif_parse_StorageReceived(int fd) case TABLE_INVENTORY: stor = &sd->inventory; break; case TABLE_STORAGE: stor = &sd->storage; break; case TABLE_CART: - case TABLE_CART_: stor = &sd->cart; break; default: return false; @@ -3216,13 +3215,11 @@ static bool intif_parse_StorageReceived(int fd) if (sd->state.autotrade) { clif_parse_LoadEndAck(sd->fd, sd); sd->autotrade_tid = add_timer(gettick() + battle_config.feature_autotrade_open_delay, pc_autotrade_timer, sd->bl.id, 0); + }else if( sd->state.prevend ){ + clif_openvendingreq(sd, sd->vend_skill_lv+2); } break; - case TABLE_CART_: - clif_openvendingreq(sd, sd->vend_skill_lv+2); - break; - case TABLE_STORAGE: pc_check_available_item(sd, ITMCHK_STORAGE); break; @@ -3246,8 +3243,14 @@ static void intif_parse_StorageSaved(int fd) //ShowInfo("Storage has been saved (AID: %d).\n", RFIFOL(fd, 2)); break; case TABLE_CART: // cart - case TABLE_CART_: //ShowInfo("Cart has been saved (AID: %d).\n", RFIFOL(fd, 2)); + { + struct map_session_data *sd = map_id2sd(RFIFOL(fd, 2)); + + if( sd && sd->state.prevend ){ + intif_storage_request(sd,TABLE_CART); + } + } break; default: break; @@ -3301,8 +3304,7 @@ bool intif_storage_save(struct map_session_data *sd, enum storage_type type) case TABLE_STORAGE: stor = &sd->storage; break; - case TABLE_CART: - case TABLE_CART_: + case TABLE_CART: stor = &sd->cart; break; default: diff --git a/src/map/skill.c b/src/map/skill.c index 3cdf771088..2cc66b5f4f 100755 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -7319,7 +7319,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui sd->vend_skill_lv = skill_lv; ARR_FIND(0, MAX_CART, i, sd->cart.u.items_cart[i].nameid && sd->cart.u.items_cart[i].id == 0); if (i < MAX_CART) - intif_storage_save(sd, TABLE_CART_); + intif_storage_save(sd, TABLE_CART); else clif_openvendingreq(sd,2+skill_lv); } From a8c8cbd498c059c87af7e230b5d5434f39576bb4 Mon Sep 17 00:00:00 2001 From: aleos89 Date: Thu, 13 Oct 2016 18:06:58 -0400 Subject: [PATCH 12/22] Small cleanups * Corrected the spacing to tabs in a few locations. * Corrected a variable typo. --- src/char/char.c | 2 +- src/char/int_storage.c | 5 +++-- src/map/chrif.c | 6 +++--- src/map/pc.c | 4 ++-- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/char/char.c b/src/char/char.c index f0354d07eb..7e01c8c818 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -1095,7 +1095,7 @@ int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_ev if (charserv_config.save_log) - ShowInfo("Loaded char (%d - %s): %s\n", char_id, p->name, StringBuf_Value(&msg_buf)); //ok. all data load successfully! + ShowInfo("Loaded char (%d - %s): %s\n", char_id, p->name, StringBuf_Value(&msg_buf)); //ok. all data load successfully! SqlStmt_Free(stmt); cp = (struct mmo_charstatus *)idb_ensure(char_db_, char_id, char_create_charstatus); diff --git a/src/char/int_storage.c b/src/char/int_storage.c index e33d5c1676..72f70af8e2 100644 --- a/src/char/int_storage.c +++ b/src/char/int_storage.c @@ -678,13 +678,14 @@ static void mapif_storage_data_loaded(int fd, uint32 account_id, char type, stru * @param fd * @param account_id * @param char_id + * @param success * @param type */ -void mapif_storage_saved(int fd, uint32 account_id, uint32 char_id, bool sucess, char type) { +void mapif_storage_saved(int fd, uint32 account_id, uint32 char_id, bool success, char type) { WFIFOHEAD(fd,8); WFIFOW(fd, 0) = 0x388b; WFIFOL(fd, 2) = account_id; - WFIFOB(fd, 6) = sucess; + WFIFOB(fd, 6) = success; WFIFOB(fd, 7) = type; WFIFOSET(fd,8); } diff --git a/src/map/chrif.c b/src/map/chrif.c index ad5b211315..4088779f0a 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -299,9 +299,9 @@ int chrif_save(struct map_session_data *sd, int flag) { chrif_bsdata_save(sd, (flag && (flag != 3))); if (sd->state.storage_flag == 1) - intif_storage_save(sd,TABLE_STORAGE); - intif_storage_save(sd,TABLE_INVENTORY); - intif_storage_save(sd,TABLE_CART); + intif_storage_save(sd,TABLE_STORAGE); + intif_storage_save(sd,TABLE_INVENTORY); + intif_storage_save(sd,TABLE_CART); //For data sync if (sd->state.storage_flag == 2) diff --git a/src/map/pc.c b/src/map/pc.c index bfc21cb279..31626a8474 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -4486,7 +4486,7 @@ char pc_additem(struct map_session_data *sd,struct item *item,int amount,e_log_p sd->inventory.u.items_inventory[i].bound == item->bound && sd->inventory.u.items_inventory[i].expire_time == 0 && sd->inventory.u.items_inventory[i].unique_id == item->unique_id && - memcmp(&sd->inventory.u.items_inventory[i].card, &item->card, sizeof(item->card)) == 0 ) { + memcmp(&sd->inventory.u.items_inventory[i].card, &item->card, sizeof(item->card)) == 0 ) { if( amount > MAX_AMOUNT - sd->inventory.u.items_inventory[i].amount || ( id->stack.inventory && amount > id->stack.amount - sd->inventory.u.items_inventory[i].amount ) ) return ADDITEM_OVERAMOUNT; sd->inventory.u.items_inventory[i].amount += amount; @@ -5070,7 +5070,7 @@ void pc_cart_delitem(struct map_session_data *sd,int n,int amount,int type,e_log nullpo_retv(sd); if(sd->cart.u.items_cart[n].nameid == 0 || - sd->cart.u.items_cart[n].amount < amount) + sd->cart.u.items_cart[n].amount < amount) return; log_pick_pc(sd, log_type, -amount, &sd->cart.u.items_cart[n]); From 768d801f3d0fd63c888af7bb3ebef72f964b2256 Mon Sep 17 00:00:00 2001 From: Lemongrass3110 Date: Fri, 14 Oct 2016 00:40:37 +0200 Subject: [PATCH 13/22] Merged storage loading into a single function Follow up to 800714a forgot to eliminate TABLE_CART_ completely. --- src/char/char.c | 118 +++++++++++++++++- src/char/char.h | 3 +- src/char/int_storage.c | 265 +---------------------------------------- src/common/mmo.h | 1 - 4 files changed, 119 insertions(+), 268 deletions(-) diff --git a/src/char/char.c b/src/char/char.c index 7e01c8c818..8f09330a00 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -515,30 +515,33 @@ int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p){ } /// Saves an array of 'item' entries into the specified table. -int char_memitemdata_to_sql(const struct item items[], int max, int id, int tableswitch) { +int char_memitemdata_to_sql(const struct item items[], int max, int id, enum storage_type tableswitch) { StringBuf buf; SqlStmt* stmt; - int i, j, offset = 0; - const char* tablename, *selectoption; + int i, j, offset = 0, errors = 0; + const char *tablename, *selectoption, *printname; struct item item; // temp storage variable bool* flag; // bit array for inventory matching bool found; - int errors = 0; switch (tableswitch) { case TABLE_INVENTORY: + printname = "Inventory"; tablename = schema_config.inventory_db; selectoption = "char_id"; break; case TABLE_CART: + printname = "Cart"; tablename = schema_config.cart_db; selectoption = "char_id"; break; case TABLE_STORAGE: + printname = "Storage"; tablename = schema_config.storage_db; selectoption = "account_id"; break; case TABLE_GUILD_STORAGE: + printname = "Guild Storage"; tablename = schema_config.guild_storage_db; selectoption = "guild_id"; break; @@ -717,7 +720,7 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl errors++; } - ShowInfo("Saved %s data for %s: %d\n", (tableswitch == TABLE_INVENTORY ? "Inventory" : (tableswitch == TABLE_GUILD_STORAGE ? "Guild Storage" : (tableswitch == TABLE_STORAGE ? "Storage" : "Cart"))), selectoption, id); + ShowInfo("Saved %s data for %s: %d\n", printname, selectoption, id); StringBuf_Destroy(&buf); aFree(flag); @@ -725,6 +728,111 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl return errors; } +bool char_memitemdata_from_sql( struct s_storage* p, int max, int id, enum storage_type tableswitch ){ + StringBuf buf; + SqlStmt* stmt; + int i,j, offset = 0; + struct item item, *storage; + const char *tablename, *selectoption, *printname; + + switch (tableswitch) { + case TABLE_INVENTORY: + printname = "Inventory"; + tablename = schema_config.inventory_db; + selectoption = "char_id"; + storage = p->u.items_inventory; + break; + case TABLE_CART: + printname = "Cart"; + tablename = schema_config.cart_db; + selectoption = "char_id"; + storage = p->u.items_cart; + break; + case TABLE_STORAGE: + printname = "Storage"; + tablename = schema_config.storage_db; + selectoption = "account_id"; + storage = p->u.items_storage; + break; + case TABLE_GUILD_STORAGE: + printname = "Guild Storage"; + tablename = schema_config.guild_storage_db; + selectoption = "guild_id"; + storage = p->u.items_guild; + break; + default: + ShowError("Invalid table name!\n"); + return false; + } + + memset(p, 0, sizeof(struct s_storage)); //clean up memory + p->id = id; + p->type = tableswitch; + + stmt = SqlStmt_Malloc(sql_handle); + if (stmt == NULL) { + SqlStmt_ShowDebug(stmt); + return false; + } + + StringBuf_Init(&buf); + StringBuf_AppendStr(&buf, "SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`expire_time`,`bound`,`unique_id`"); + if (tableswitch == TABLE_INVENTORY) { + StringBuf_Printf(&buf, ", `favorite`"); + offset = 1; + } + for( j = 0; j < MAX_SLOTS; ++j ) + StringBuf_Printf(&buf, ",`card%d`", j); + for( j = 0; j < MAX_ITEM_RDM_OPT; ++j ) { + StringBuf_Printf(&buf, ", `option_id%d`", j); + StringBuf_Printf(&buf, ", `option_val%d`", j); + StringBuf_Printf(&buf, ", `option_parm%d`", j); + } + StringBuf_Printf(&buf, " FROM `%s` WHERE `%s`=? ORDER BY `nameid`", tablename, selectoption ); + + if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) + || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &id, 0) + || SQL_ERROR == SqlStmt_Execute(stmt) ) + { + SqlStmt_ShowDebug(stmt); + SqlStmt_Free(stmt); + StringBuf_Destroy(&buf); + return false; + } + + SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &item.id, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 1, SQLDT_USHORT, &item.nameid, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 2, SQLDT_SHORT, &item.amount, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 3, SQLDT_UINT, &item.equip, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 4, SQLDT_CHAR, &item.identify, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 5, SQLDT_CHAR, &item.refine, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 6, SQLDT_CHAR, &item.attribute, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 7, SQLDT_UINT, &item.expire_time, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 8, SQLDT_CHAR, &item.bound, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 9, SQLDT_ULONGLONG, &item.unique_id, 0, NULL, NULL); + if (tableswitch == TABLE_INVENTORY) + SqlStmt_BindColumn(stmt, 10, SQLDT_CHAR, &item.favorite, 0, NULL, NULL); + for( i = 0; i < MAX_SLOTS; ++i ) + SqlStmt_BindColumn(stmt, 10+offset+i, SQLDT_USHORT, &item.card[i], 0, NULL, NULL); + for( i = 0; i < MAX_ITEM_RDM_OPT; ++i ) { + SqlStmt_BindColumn(stmt, 10+offset+MAX_SLOTS+i*3, SQLDT_SHORT, &item.option[i].id, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 11+offset+MAX_SLOTS+i*3, SQLDT_SHORT, &item.option[i].value, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 12+offset+MAX_SLOTS+i*3, SQLDT_CHAR, &item.option[i].param, 0, NULL, NULL); + } + + for( i = 0; i < max && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) + memcpy(&storage[i], &item, sizeof(item)); + + p->amount = i; + ShowInfo("Loaded %s data from DB for %s: %d (total: %d)\n", printname, selectoption, id, p->amount); + + SqlStmt_FreeResult(stmt); + SqlStmt_Free(stmt); + StringBuf_Destroy(&buf); + + return true; +} + /** * Returns the correct gender ID for the given character and enum value. * diff --git a/src/char/char.h b/src/char/char.h index 4993fb0e30..9596dd86eb 100644 --- a/src/char/char.h +++ b/src/char/char.h @@ -257,7 +257,8 @@ int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf); int char_delete_char_sql(uint32 char_id); int char_rename_char_sql(struct char_session_data *sd, uint32 char_id); int char_divorce_char_sql(int partner_id1, int partner_id2); -int char_memitemdata_to_sql(const struct item items[], int max, int id, int tableswitch); +int char_memitemdata_to_sql(const struct item items[], int max, int id, enum storage_type tableswitch); +bool char_memitemdata_from_sql( struct s_storage* p, int max, int id, enum storage_type tableswitch ); void disconnect_player(uint32 account_id); diff --git a/src/char/int_storage.c b/src/char/int_storage.c index 72f70af8e2..55f6b3b3fe 100644 --- a/src/char/int_storage.c +++ b/src/char/int_storage.c @@ -55,72 +55,7 @@ static int cart_tosql(uint32 char_id, struct s_storage* p) */ static bool inventory_fromsql(uint32 char_id, struct s_storage* p) { - int i; - StringBuf buf; - SqlStmt* stmt; - struct item tmp_item; - - memset(p, 0, sizeof(struct s_storage)); //clean up memory - p->id = char_id; - p->type = TABLE_INVENTORY; - - stmt = SqlStmt_Malloc(sql_handle); - if (stmt == NULL) { - SqlStmt_ShowDebug(stmt); - return false; - } - - // storage {`account_id`/`id`/`nameid`/`amount`/`equip`/`identify`/`refine`/`attribute`/`expire_time`/`favorite`/`bound`/`unique_id`/`card0`/`card1`/`card2`/`card3`/`option_id0`/`option_val0`/`option_parm0`/`option_id1`/`option_val1`/`option_parm1`/`option_id2`/`option_val2`/`option_parm2`/`option_id3`/`option_val3`/`option_parm3`/`option_id4`/`option_val4`/`option_parm4`} - StringBuf_Init(&buf); - StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `bound`, `unique_id`"); - for( i = 0; i < MAX_SLOTS; ++i ) - StringBuf_Printf(&buf, ", `card%d`", i); - for( i = 0; i < MAX_ITEM_RDM_OPT; ++i ) { - StringBuf_Printf(&buf, ", `option_id%d`", i); - StringBuf_Printf(&buf, ", `option_val%d`", i); - StringBuf_Printf(&buf, ", `option_parm%d`", i); - } - StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", schema_config.inventory_db, MAX_INVENTORY); - - if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) - || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) - || SQL_ERROR == SqlStmt_Execute(stmt) ) - { - SqlStmt_ShowDebug(stmt); - SqlStmt_Free(stmt); - StringBuf_Destroy(&buf); - return false; - } - - SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &tmp_item.id, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 1, SQLDT_USHORT, &tmp_item.nameid, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 2, SQLDT_SHORT, &tmp_item.amount, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 3, SQLDT_UINT, &tmp_item.equip, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 4, SQLDT_CHAR, &tmp_item.identify, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 5, SQLDT_CHAR, &tmp_item.refine, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 6, SQLDT_CHAR, &tmp_item.attribute, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 7, SQLDT_UINT, &tmp_item.expire_time, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 8, SQLDT_CHAR, &tmp_item.favorite, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 9, SQLDT_CHAR, &tmp_item.bound, 0, NULL, NULL); - SqlStmt_BindColumn(stmt,10, SQLDT_ULONGLONG, &tmp_item.unique_id, 0, NULL, NULL); - for( i = 0; i < MAX_SLOTS; ++i ) - SqlStmt_BindColumn(stmt, 11+i, SQLDT_USHORT, &tmp_item.card[i], 0, NULL, NULL); - for( i = 0; i < MAX_ITEM_RDM_OPT; ++i ) { - SqlStmt_BindColumn(stmt, 11+MAX_SLOTS+i*3, SQLDT_SHORT, &tmp_item.option[i].id, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 12+MAX_SLOTS+i*3, SQLDT_SHORT, &tmp_item.option[i].value, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 13+MAX_SLOTS+i*3, SQLDT_CHAR, &tmp_item.option[i].param, 0, NULL, NULL); - } - - for( i = 0; i < MAX_INVENTORY && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) - memcpy(&p->u.items_inventory[i], &tmp_item, sizeof(tmp_item)); - - p->amount = i; - ShowInfo("Loaded inventory data from DB - CID: %d (total: %d)\n", char_id, p->amount); - - SqlStmt_FreeResult(stmt); - SqlStmt_Free(stmt); - StringBuf_Destroy(&buf); - return true; + return char_memitemdata_from_sql( p, MAX_INVENTORY, char_id, TABLE_INVENTORY ); } /** @@ -131,71 +66,7 @@ static bool inventory_fromsql(uint32 char_id, struct s_storage* p) */ static bool cart_fromsql(uint32 char_id, struct s_storage* p) { - int i,j; - StringBuf buf; - SqlStmt* stmt; - struct item tmp_item; - - memset(p, 0, sizeof(struct s_storage)); //clean up memory - p->id = char_id; - p->type = TABLE_CART; - - stmt = SqlStmt_Malloc(sql_handle); - if (stmt == NULL) { - SqlStmt_ShowDebug(stmt); - return false; - } - - // storage {`char_id`/`id`/`nameid`/`amount`/`equip`/`identify`/`refine`/`attribute`/`expire_time`/`bound`/`unique_id`/`card0`/`card1`/`card2`/`card3`/`option_id0`/`option_val0`/`option_parm0`/`option_id1`/`option_val1`/`option_parm1`/`option_id2`/`option_val2`/`option_parm2`/`option_id3`/`option_val3`/`option_parm3`/`option_id4`/`option_val4`/`option_parm4`} - StringBuf_Init(&buf); - StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`"); - for( j = 0; j < MAX_SLOTS; ++j ) - StringBuf_Printf(&buf, ",`card%d`", j); - for( i = 0; i < MAX_ITEM_RDM_OPT; ++i ) { - StringBuf_Printf(&buf, ", `option_id%d`", i); - StringBuf_Printf(&buf, ", `option_val%d`", i); - StringBuf_Printf(&buf, ", `option_parm%d`", i); - } - StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? ORDER BY `id` LIMIT %d", schema_config.cart_db, MAX_CART); - - if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) - || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) - || SQL_ERROR == SqlStmt_Execute(stmt) ) - { - SqlStmt_ShowDebug(stmt); - SqlStmt_Free(stmt); - StringBuf_Destroy(&buf); - return false; - } - - SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &tmp_item.id, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 1, SQLDT_USHORT, &tmp_item.nameid, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 2, SQLDT_SHORT, &tmp_item.amount, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 3, SQLDT_UINT, &tmp_item.equip, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 4, SQLDT_CHAR, &tmp_item.identify, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 5, SQLDT_CHAR, &tmp_item.refine, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 6, SQLDT_CHAR, &tmp_item.attribute, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 7, SQLDT_UINT, &tmp_item.expire_time, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 8, SQLDT_CHAR, &tmp_item.bound, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 9, SQLDT_ULONGLONG, &tmp_item.unique_id, 0, NULL, NULL); - for( i = 0; i < MAX_SLOTS; ++i ) - SqlStmt_BindColumn(stmt, 10+i, SQLDT_USHORT, &tmp_item.card[i], 0, NULL, NULL); - for( i = 0; i < MAX_ITEM_RDM_OPT; ++i ) { - SqlStmt_BindColumn(stmt, 10+MAX_SLOTS+i*3, SQLDT_SHORT, &tmp_item.option[i].id, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 11+MAX_SLOTS+i*3, SQLDT_SHORT, &tmp_item.option[i].value, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 12+MAX_SLOTS+i*3, SQLDT_CHAR, &tmp_item.option[i].param, 0, NULL, NULL); - } - - for( i = 0; i < MAX_CART && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) - memcpy(&p->u.items_cart[i], &tmp_item, sizeof(tmp_item)); - - p->amount = i; - ShowInfo("Loaded Cart data from DB - CID: %d (total: %d)\n", char_id, p->amount); - - SqlStmt_FreeResult(stmt); - SqlStmt_Free(stmt); - StringBuf_Destroy(&buf); - return true; + return char_memitemdata_from_sql( p, MAX_CART, char_id, TABLE_CART ); } /** @@ -206,71 +77,7 @@ static bool cart_fromsql(uint32 char_id, struct s_storage* p) */ static bool storage_fromsql(uint32 account_id, struct s_storage* p) { - int i, j; - StringBuf buf; - SqlStmt* stmt; - struct item tmp_item; - - memset(p, 0, sizeof(struct s_storage)); //clean up memory - p->id = account_id; - p->type = TABLE_STORAGE; - - stmt = SqlStmt_Malloc(sql_handle); - if (stmt == NULL) { - SqlStmt_ShowDebug(stmt); - return false; - } - - // storage {`account_id`/`id`/`nameid`/`amount`/`equip`/`identify`/`refine`/`attribute`/`card0`/`card1`/`card2`/`card3`/`option_id0`/`option_val0`/`option_parm0`/`option_id1`/`option_val1`/`option_parm1`/`option_id2`/`option_val2`/`option_parm2`/`option_id3`/`option_val3`/`option_parm3`/`option_id4`/`option_val4`/`option_parm4`} - StringBuf_Init(&buf); - StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`"); - for( j = 0; j < MAX_SLOTS; ++j ) - StringBuf_Printf(&buf, ", `card%d`", j); - for( i = 0; i < MAX_ITEM_RDM_OPT; ++i ) { - StringBuf_Printf(&buf, ", `option_id%d`", i); - StringBuf_Printf(&buf, ", `option_val%d`", i); - StringBuf_Printf(&buf, ", `option_parm%d`", i); - } - StringBuf_Printf(&buf, " FROM `%s` WHERE `account_id`=? ORDER BY `nameid` LIMIT %d", schema_config.storage_db, account_id, MAX_STORAGE); - - if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) - || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &account_id, 0) - || SQL_ERROR == SqlStmt_Execute(stmt) ) - { - SqlStmt_ShowDebug(stmt); - SqlStmt_Free(stmt); - StringBuf_Destroy(&buf); - return false; - } - - SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &tmp_item.id, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 1, SQLDT_USHORT, &tmp_item.nameid, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 2, SQLDT_SHORT, &tmp_item.amount, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 3, SQLDT_UINT, &tmp_item.equip, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 4, SQLDT_CHAR, &tmp_item.identify, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 5, SQLDT_CHAR, &tmp_item.refine, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 6, SQLDT_CHAR, &tmp_item.attribute, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 7, SQLDT_UINT, &tmp_item.expire_time, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 8, SQLDT_CHAR, &tmp_item.bound, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 9, SQLDT_ULONGLONG, &tmp_item.unique_id, 0, NULL, NULL); - for( i = 0; i < MAX_SLOTS; ++i ) - SqlStmt_BindColumn(stmt, 10+i, SQLDT_USHORT, &tmp_item.card[i], 0, NULL, NULL); - for( i = 0; i < MAX_ITEM_RDM_OPT; ++i ) { - SqlStmt_BindColumn(stmt, 10+MAX_SLOTS+i*3, SQLDT_SHORT, &tmp_item.option[i].id, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 11+MAX_SLOTS+i*3, SQLDT_SHORT, &tmp_item.option[i].value, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 12+MAX_SLOTS+i*3, SQLDT_CHAR, &tmp_item.option[i].param, 0, NULL, NULL); - } - - for( i = 0; i < MAX_STORAGE && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) - memcpy(&p->u.items_storage[i], &tmp_item, sizeof(tmp_item)); - - p->amount = i; - ShowInfo("Loaded Storage data from DB - AID: %d (total: %d)\n", account_id, p->amount); - - SqlStmt_FreeResult(stmt); - SqlStmt_Free(stmt); - StringBuf_Destroy(&buf); - return true; + return char_memitemdata_from_sql( p, MAX_STORAGE, account_id, TABLE_STORAGE ); } /** @@ -293,71 +100,7 @@ bool guild_storage_tosql(int guild_id, struct s_storage* p) */ bool guild_storage_fromsql(int guild_id, struct s_storage* p) { - int i,j; - StringBuf buf; - SqlStmt* stmt; - struct item tmp_item; - - memset(p, 0, sizeof(struct s_storage)); //clean up memory - p->id = guild_id; - p->type = TABLE_GUILD_STORAGE; - - stmt = SqlStmt_Malloc(sql_handle); - if (stmt == NULL) { - SqlStmt_ShowDebug(stmt); - return false; - } - - // storage {`guild_id`/`id`/`nameid`/`amount`/`equip`/`identify`/`refine`/`attribute`/`expire_time`/`bound`/`unique_id`/`card0`/`card1`/`card2`/`card3`/`option_id0`/`option_val0`/`option_parm0`/`option_id1`/`option_val1`/`option_parm1`/`option_id2`/`option_val2`/`option_parm2`/`option_id3`/`option_val3`/`option_parm3`/`option_id4`/`option_val4`/`option_parm4`} - StringBuf_Init(&buf); - StringBuf_AppendStr(&buf, "SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`expire_time`,`bound`,`unique_id`"); - for( j = 0; j < MAX_SLOTS; ++j ) - StringBuf_Printf(&buf, ",`card%d`", j); - for( j = 0; j < MAX_ITEM_RDM_OPT; ++j ) { - StringBuf_Printf(&buf, ", `option_id%d`", j); - StringBuf_Printf(&buf, ", `option_val%d`", j); - StringBuf_Printf(&buf, ", `option_parm%d`", j); - } - StringBuf_Printf(&buf, " FROM `%s` WHERE `guild_id`='%d' ORDER BY `nameid`", schema_config.guild_storage_db, guild_id); - - if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) - || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &guild_id, 0) - || SQL_ERROR == SqlStmt_Execute(stmt) ) - { - SqlStmt_ShowDebug(stmt); - SqlStmt_Free(stmt); - StringBuf_Destroy(&buf); - return false; - } - - SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &tmp_item.id, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 1, SQLDT_USHORT, &tmp_item.nameid, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 2, SQLDT_SHORT, &tmp_item.amount, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 3, SQLDT_UINT, &tmp_item.equip, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 4, SQLDT_CHAR, &tmp_item.identify, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 5, SQLDT_CHAR, &tmp_item.refine, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 6, SQLDT_CHAR, &tmp_item.attribute, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 7, SQLDT_UINT, &tmp_item.expire_time, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 8, SQLDT_CHAR, &tmp_item.bound, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 9, SQLDT_ULONGLONG, &tmp_item.unique_id, 0, NULL, NULL); - for( i = 0; i < MAX_SLOTS; ++i ) - SqlStmt_BindColumn(stmt, 10+i, SQLDT_USHORT, &tmp_item.card[i], 0, NULL, NULL); - for( i = 0; i < MAX_ITEM_RDM_OPT; ++i ) { - SqlStmt_BindColumn(stmt, 10+MAX_SLOTS+i*3, SQLDT_SHORT, &tmp_item.option[i].id, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 11+MAX_SLOTS+i*3, SQLDT_SHORT, &tmp_item.option[i].value, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 12+MAX_SLOTS+i*3, SQLDT_CHAR, &tmp_item.option[i].param, 0, NULL, NULL); - } - - for( i = 0; i < MAX_GUILD_STORAGE && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) - memcpy(&p->u.items_guild[i], &tmp_item, sizeof(tmp_item)); - - p->amount = i; - ShowInfo("Loaded Guild Storage data from DB - GID: %d (total: %d)\n", guild_id, p->amount); - - SqlStmt_FreeResult(stmt); - SqlStmt_Free(stmt); - StringBuf_Destroy(&buf); - return true; + return char_memitemdata_from_sql( p, MAX_GUILD_STORAGE, guild_id, TABLE_GUILD_STORAGE ); } //--------------------------------------------------------- diff --git a/src/common/mmo.h b/src/common/mmo.h index 476d548fce..c5dd6f82f7 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -299,7 +299,6 @@ struct skill_cooldown_data { enum storage_type { TABLE_INVENTORY = 1, TABLE_CART, - TABLE_CART_, TABLE_STORAGE, TABLE_GUILD_STORAGE, }; From 7e2efec61b9c9e0767e01454c74fb6d80b31bf36 Mon Sep 17 00:00:00 2001 From: aleos89 Date: Fri, 14 Oct 2016 12:50:06 -0400 Subject: [PATCH 14/22] Moved some inventory checks * Resolved item bonuses not properly being given that get applied before the player's inventory is received. * Resolved rental items that have Status Changes attached to them not getting removed if the timer expired when the player logs in. * Removed an extra call for player's with item sets. Thanks to @Tokeiburu! --- src/map/intif.c | 2 ++ src/map/pc.c | 4 ---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/map/intif.c b/src/map/intif.c index 81ee6f9164..6b46348f29 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -3205,7 +3205,9 @@ static bool intif_parse_StorageReceived(int fd) //Set here because we need the inventory data for weapon sprite parsing. status_set_viewdata(&sd->bl, sd->status.class_); pc_load_combo(sd); + status_calc_pc(sd, (enum e_status_calc_opt)(SCO_FIRST|SCO_FORCE)); status_calc_weight(sd, 1|2); // Refresh item weight data + chrif_scdata_request(sd->status.account_id, sd->status.char_id); break; } diff --git a/src/map/pc.c b/src/map/pc.c index 7cca10388e..4ae205c403 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1421,10 +1421,6 @@ void pc_reg_received(struct map_session_data *sd) if (!chrif_auth_finished(sd)) ShowError("pc_reg_received: Failed to properly remove player %d:%d from logging db!\n", sd->status.account_id, sd->status.char_id); - pc_load_combo(sd); - - status_calc_pc(sd, (enum e_status_calc_opt)(SCO_FIRST|SCO_FORCE)); - chrif_scdata_request(sd->status.account_id, sd->status.char_id); chrif_skillcooldown_request(sd->status.account_id, sd->status.char_id); chrif_bsdata_request(sd->status.char_id); sd->storage_size = MIN_STORAGE; //default to min From c0bd422af2c704816abe249ff7380802c037f241 Mon Sep 17 00:00:00 2001 From: aleos89 Date: Thu, 27 Oct 2016 20:28:31 -0400 Subject: [PATCH 15/22] Resolved some more inventory issues * Moved storage type loading further up the chain to ensure data is loaded sooner. * Resolved cart weight and cart count to update properly. * Resolved item display index not displaying in the correct order when opening a Vending Shop. Thanks to @Tokeiburu! --- src/map/intif.c | 3 ++- src/map/pc.c | 11 ++++++----- src/map/status.c | 16 ++++++++++++---- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/map/intif.c b/src/map/intif.c index 6b46348f29..446e7b150a 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -3213,11 +3213,12 @@ static bool intif_parse_StorageReceived(int fd) case TABLE_CART: pc_check_available_item(sd, ITMCHK_CART); - status_calc_cart_weight(sd, 1|2); if (sd->state.autotrade) { clif_parse_LoadEndAck(sd->fd, sd); sd->autotrade_tid = add_timer(gettick() + battle_config.feature_autotrade_open_delay, pc_autotrade_timer, sd->bl.id, 0); }else if( sd->state.prevend ){ + clif_clearcart(sd->fd); + clif_cartlist(sd); clif_openvendingreq(sd, sd->vend_skill_lv+2); } break; diff --git a/src/map/pc.c b/src/map/pc.c index 4ae205c403..3a9f313106 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1399,6 +1399,12 @@ void pc_reg_received(struct map_session_data *sd) return; sd->state.active = 1; + intif_storage_request(sd,TABLE_INVENTORY); // Request inventory data + intif_storage_request(sd,TABLE_CART); // Request cart data + intif_storage_request(sd,TABLE_STORAGE); // Request storage data + + sd->storage_size = MIN_STORAGE; //default to min + if (sd->status.party_id) party_member_joined(sd); if (sd->status.guild_id) @@ -1423,7 +1429,6 @@ void pc_reg_received(struct map_session_data *sd) chrif_skillcooldown_request(sd->status.account_id, sd->status.char_id); chrif_bsdata_request(sd->status.char_id); - sd->storage_size = MIN_STORAGE; //default to min #ifdef VIP_ENABLE sd->vip.time = 0; sd->vip.enabled = 0; @@ -1451,10 +1456,6 @@ void pc_reg_received(struct map_session_data *sd) clif_changeoption( &sd->bl ); } - - intif_storage_request(sd,TABLE_STORAGE); // Request storage data - intif_storage_request(sd,TABLE_CART); // Request cart data - intif_storage_request(sd,TABLE_INVENTORY); // Request inventory data } static int pc_calc_skillpoint(struct map_session_data* sd) diff --git a/src/map/status.c b/src/map/status.c index 49ef653e0a..d6d32a9ff6 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -3134,6 +3134,10 @@ bool status_calc_weight(struct map_session_data *sd, uint8 flag) /** * Calculates player's cart weight * @param sd: Player object + * @param flag: Calculation type + * 1 - Cart item weight + * 2 - Skill/Status/Configuration max weight bonus + * 4 - Whether to check for cart status * @return false - failed, true - success */ bool status_calc_cart_weight(struct map_session_data *sd, uint8 flag) @@ -3142,7 +3146,7 @@ bool status_calc_cart_weight(struct map_session_data *sd, uint8 flag) nullpo_retr(false, sd); - if (!pc_iscarton(sd)) + if (!pc_iscarton(sd) && !(flag&4)) return false; b_cart_weight_max = sd->cart_weight_max; // Store cart max weight for later comparison @@ -3201,9 +3205,6 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) sd->battle_status.sp = sd->status.sp; sd->regen.sregen = &sd->sregen; sd->regen.ssregen = &sd->ssregen; - - status_calc_weight(sd, 1); - status_calc_cart_weight(sd, 1); } base_status = &sd->base_status; @@ -8479,6 +8480,13 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty return 0; break; + case SC_PUSH_CART: + if (sd) { + sd->cart_weight_max = 0; // Force a client refesh + status_calc_cart_weight(sd, 1|2|4); + } + break; + case SC_WEDDING: case SC_XMAS: case SC_SUMMER: From a0caaa1036a21681d38a8daa21616da5c9be253f Mon Sep 17 00:00:00 2001 From: aleos89 Date: Fri, 28 Oct 2016 17:51:58 -0400 Subject: [PATCH 16/22] Fixed cart data for older cart types * Follow up to c0bd422. * Resolves older carts that don't use the SC_PUSH_CART status to update their weight and item data properly. * Moved to pc_scdata_received so that it will hit both versions just fine. Thanks to @Lemongrass3110! --- src/map/pc.c | 5 +++++ src/map/status.c | 7 ------- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/map/pc.c b/src/map/pc.c index 3a9f313106..56a64cb300 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -11453,6 +11453,11 @@ void pc_damage_log_clear(struct map_session_data *sd, int id) */ void pc_scdata_received(struct map_session_data *sd) { pc_inventory_rentals(sd); // Needed here to remove rentals that have Status Changes after chrif_load_scdata has finished + + if (pc_iscarton(sd)) { + sd->cart_weight_max = 0; // Force a client refesh + status_calc_cart_weight(sd, 1|2|4); + } } /** diff --git a/src/map/status.c b/src/map/status.c index d6d32a9ff6..47cdeccdc6 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -8480,13 +8480,6 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty return 0; break; - case SC_PUSH_CART: - if (sd) { - sd->cart_weight_max = 0; // Force a client refesh - status_calc_cart_weight(sd, 1|2|4); - } - break; - case SC_WEDDING: case SC_XMAS: case SC_SUMMER: From 46b1de7d5074dc1dc80e17214e23acae656161a9 Mon Sep 17 00:00:00 2001 From: Cydh Ramdh Date: Fri, 14 Oct 2016 08:49:32 +0700 Subject: [PATCH 17/22] Initial release 'premium' storage * Adapting official multiple storages. * Added config to defines storages. See conf/import-tmpl/inter_server.conf. * Added packet IZ `0x388c` for sending storage definitions. * Added script command `openstorage2` to open premium storages. * Removed `sd->storage_size`, replaced by `sd->storage.max_amount`. The value is defined in inter_server.conf in storage entries. Signed-off-by: Cydh Ramdh --- conf/import-tmpl/inter_server.conf | 0 conf/inter_athena.conf | 3 +- conf/inter_server.conf | 25 ++ doc/packet_interserv.txt | 12 + doc/script_commands.txt | 27 ++ sql-files/upgrades/premium_storage.sql | 38 +++ src/char/char.c | 27 +- src/char/char.h | 6 +- src/char/int_storage.c | 123 +++++++-- src/char/int_storage.h | 4 + src/char/inter.c | 103 ++++++- src/char/inter.h | 11 + src/common/mmo.h | 23 +- src/map/atcommand.c | 20 +- src/map/chrif.c | 22 +- src/map/clif.c | 39 ++- src/map/clif.h | 2 +- src/map/intif.c | 108 +++++--- src/map/intif.h | 4 +- src/map/pc.c | 13 +- src/map/pc.h | 5 +- src/map/script.c | 24 +- src/map/script_constants.h | 4 + src/map/skill.c | 2 +- src/map/storage.c | 357 +++++++++++++++++++------ src/map/storage.h | 31 ++- src/map/unit.c | 2 + vcproj-10/map-server.vcxproj | 1 + vcproj-12/map-server.vcxproj | 1 + vcproj-13/map-server.vcxproj | 1 + vcproj-14/map-server.vcxproj | 1 + 31 files changed, 843 insertions(+), 196 deletions(-) create mode 100644 conf/import-tmpl/inter_server.conf create mode 100644 conf/inter_server.conf create mode 100644 sql-files/upgrades/premium_storage.sql diff --git a/conf/import-tmpl/inter_server.conf b/conf/import-tmpl/inter_server.conf new file mode 100644 index 0000000000..e69de29bb2 diff --git a/conf/inter_athena.conf b/conf/inter_athena.conf index 2a8d642a17..9fc1c1e1f4 100644 --- a/conf/inter_athena.conf +++ b/conf/inter_athena.conf @@ -93,7 +93,6 @@ scdata_db: sc_data cart_db: cart_inventory inventory_db: inventory charlog_db: charlog -storage_db: storage skill_db: skill interlog_db: interlog memo_db: memo @@ -150,4 +149,6 @@ db_roulette_table: db_roulette // Use SQL item_db, mob_db and mob_skill_db for the map server? (yes/no) use_sql_db: no +inter_server_conf: conf/inter_server.conf + import: conf/import/inter_conf.txt diff --git a/conf/inter_server.conf b/conf/inter_server.conf new file mode 100644 index 0000000000..448b14d05f --- /dev/null +++ b/conf/inter_server.conf @@ -0,0 +1,25 @@ +/** + * Config for storages + * + * To access premium storage, use 'openstorage2' script command (except for the default storage). + * If premium storages are added, just copy the structure of storage table then match the table name in this config. + * The 'max' of premium storages are not adjusted by 'vip_storage_increase' config nor MIN_STORAGE. + * + * Structure: +{ + id: // (int) Storage ID will be used for 'openstorage2' script command. + name: "" // (string) Storage name will be sent to the client when player open the storage. + table: "" // (string) Name of table where storage is saved, the table stucture is same like default storage name + max: // (int) *optional* Maximum number of storage, MAX_STORAGE will be used if no value defined +}, // Use comma to add more storages + **/ +storages: ( +{ + // Default storage + // DO NOT CHANGE THIS EXCEPT YOU KNOW WHAT YOU ARE DOING + id: 0 + name: "Storage" + table: "storage" + //max: 600 +} +) diff --git a/doc/packet_interserv.txt b/doc/packet_interserv.txt index 5ad05e2b3e..286a6d769c 100644 --- a/doc/packet_interserv.txt +++ b/doc/packet_interserv.txt @@ -2194,6 +2194,18 @@ Currently the max packet size is 0xFFFF (see 'WFIFOSET()' in 'src/common/socket. desc: - Info about inventory/cart/storage data is saved +0x388c + Type: IZ + Structure: .W .W { .? }*? + index: 0,2,6,... + len: 6+variable + parameter: + - cmd : packet identification (0x388c) + - len : Pakcet length + - storage_table : Storage table information + desc: + - Receive storage information + 0x3890 Type: IZ Structure: .W .W .L .B .?B diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 90ff56effd..b75e802804 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -5053,6 +5053,33 @@ window, to avoid any disruption when both windows overlap. --------------------------------------- +*openstorage2 ,{,}; + +Just like 'openstorage' command, except this command can open additional storage +by specified 'storage_id'. For storage_id, please read the conf/inter_server.conf +for storages groups. + +Values for 'mode' are: + STOR_MODE_NONE : Player only can read the storage entries. + STOR_MODE_GET : Player can get items from the storage. + STOR_MODE_PUT : Player can put items to the storage. + +Example: + if (vip_status(1)) { + mes "I will open your Premium storage."; + mes "Thank you for using our service."; + close2; + openstorage2 1,STOR_MODE_GET|STOR_MODE_PUT; + } else { + mes "Sorry, your Premium status is expired."; + mes "Storage will be opened but you can't put any item into it."; + close2; + openstorage2 1,STOR_MODE_GET; + } + end; + +--------------------------------------- + *openmail({}); This will open a character's Mail window on the client connected to the diff --git a/sql-files/upgrades/premium_storage.sql b/sql-files/upgrades/premium_storage.sql new file mode 100644 index 0000000000..1718374c4a --- /dev/null +++ b/sql-files/upgrades/premium_storage.sql @@ -0,0 +1,38 @@ +-- +-- Table structure for table `storage_1` +-- + +CREATE TABLE IF NOT EXISTS `storage_1` ( + `id` int(11) unsigned NOT NULL auto_increment, + `account_id` int(11) unsigned NOT NULL default '0', + `nameid` smallint(5) unsigned NOT NULL default '0', + `amount` smallint(11) unsigned NOT NULL default '0', + `equip` int(11) unsigned NOT NULL default '0', + `identify` smallint(6) unsigned NOT NULL default '0', + `refine` tinyint(3) unsigned NOT NULL default '0', + `attribute` tinyint(4) unsigned NOT NULL default '0', + `card0` smallint(5) unsigned NOT NULL default '0', + `card1` smallint(5) unsigned NOT NULL default '0', + `card2` smallint(5) unsigned NOT NULL default '0', + `card3` smallint(5) unsigned NOT NULL default '0', + `option_id0` smallint(5) unsigned NOT NULL default '0', + `option_val0` smallint(5) unsigned NOT NULL default '0', + `option_parm0` tinyint(3) unsigned NOT NULL default '0', + `option_id1` smallint(5) unsigned NOT NULL default '0', + `option_val1` smallint(5) unsigned NOT NULL default '0', + `option_parm1` tinyint(3) unsigned NOT NULL default '0', + `option_id2` smallint(5) unsigned NOT NULL default '0', + `option_val2` smallint(5) unsigned NOT NULL default '0', + `option_parm2` tinyint(3) unsigned NOT NULL default '0', + `option_id3` smallint(5) unsigned NOT NULL default '0', + `option_val3` smallint(5) unsigned NOT NULL default '0', + `option_parm3` tinyint(3) unsigned NOT NULL default '0', + `option_id4` smallint(5) unsigned NOT NULL default '0', + `option_val4` smallint(5) unsigned NOT NULL default '0', + `option_parm4` tinyint(3) unsigned NOT NULL default '0', + `expire_time` int(11) unsigned NOT NULL default '0', + `bound` tinyint(3) unsigned NOT NULL default '0', + `unique_id` bigint(20) unsigned NOT NULL default '0', + PRIMARY KEY (`id`), + KEY `account_id` (`account_id`) +) ENGINE=MyISAM; diff --git a/src/char/char.c b/src/char/char.c index 1b7100cc2f..9904e92f87 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -23,6 +23,7 @@ #include "int_mercenary.h" #include "int_elemental.h" #include "int_party.h" +#include "int_storage.h" #include "inter.h" #include "char_logif.h" #include "char_mapif.h" @@ -515,7 +516,7 @@ int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p){ } /// Saves an array of 'item' entries into the specified table. -int char_memitemdata_to_sql(const struct item items[], int max, int id, enum storage_type tableswitch) { +int char_memitemdata_to_sql(const struct item items[], int max, int id, enum storage_type tableswitch, uint8 stor_id) { StringBuf buf; SqlStmt* stmt; int i, j, offset = 0, errors = 0; @@ -537,7 +538,7 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, enum sto break; case TABLE_STORAGE: printname = "Storage"; - tablename = schema_config.storage_db; + tablename = inter_premiumStorage_getTableName(stor_id); selectoption = "account_id"; break; case TABLE_GUILD_STORAGE: @@ -720,15 +721,14 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, enum sto errors++; } - ShowInfo("Saved %s data for %s: %d\n", printname, selectoption, id); - + ShowInfo("Saved %s (%d) data to table %s for %s: %d\n", printname, stor_id, tablename, selectoption, id); StringBuf_Destroy(&buf); aFree(flag); return errors; } -bool char_memitemdata_from_sql( struct s_storage* p, int max, int id, enum storage_type tableswitch ){ +bool char_memitemdata_from_sql(struct s_storage* p, int max, int id, enum storage_type tableswitch, uint8 stor_id) { StringBuf buf; SqlStmt* stmt; int i,j, offset = 0; @@ -750,7 +750,7 @@ bool char_memitemdata_from_sql( struct s_storage* p, int max, int id, enum stora break; case TABLE_STORAGE: printname = "Storage"; - tablename = schema_config.storage_db; + tablename = inter_premiumStorage_getTableName(stor_id); selectoption = "account_id"; storage = p->u.items_storage; break; @@ -768,6 +768,8 @@ bool char_memitemdata_from_sql( struct s_storage* p, int max, int id, enum stora memset(p, 0, sizeof(struct s_storage)); //clean up memory p->id = id; p->type = tableswitch; + p->stor_id = stor_id; + p->max_amount = inter_premiumStorage_getMax(p->stor_id); stmt = SqlStmt_Malloc(sql_handle); if (stmt == NULL) { @@ -824,7 +826,7 @@ bool char_memitemdata_from_sql( struct s_storage* p, int max, int id, enum stora memcpy(&storage[i], &item, sizeof(item)); p->amount = i; - ShowInfo("Loaded %s data from DB for %s: %d (total: %d)\n", printname, selectoption, id, p->amount); + ShowInfo("Loaded %s (%d) data from table %s for %s: %d (total: %d)\n", printname, p->stor_id, tablename, selectoption, id, p->amount); SqlStmt_FreeResult(stmt); SqlStmt_Free(stmt); @@ -2181,7 +2183,7 @@ bool char_checkdb(void){ int i; const char* sqltable[] = { schema_config.char_db, schema_config.hotkey_db, schema_config.scdata_db, schema_config.cart_db, - schema_config.inventory_db, schema_config.charlog_db, schema_config.storage_db, + schema_config.inventory_db, schema_config.charlog_db, schema_config.char_reg_str_table, schema_config.char_reg_num_table, schema_config.acc_reg_str_table, schema_config.acc_reg_num_table, schema_config.skill_db, schema_config.interlog_db, schema_config.memo_db, schema_config.guild_db, schema_config.guild_alliance_db, schema_config.guild_castle_db, @@ -2404,13 +2406,6 @@ bool char_checkdb(void){ Sql_ShowDebug(sql_handle); return false; } - //checking storage_db - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `id`,`account_id`,`nameid`,`amount`,`equip`,`identify`,`refine`," - "`attribute`,`card0`,`card1`,`card2`,`card3`,`option_id0`,`option_val0`,`option_parm0`,`option_id1`,`option_val1`,`option_parm1`,`option_id2`,`option_val2`,`option_parm2`,`option_id3`,`option_val3`,`option_parm3`,`option_id4`,`option_val4`,`option_parm4`,`expire_time`,`bound`,`unique_id`" - " FROM `%s` LIMIT 1;", schema_config.storage_db) ){ - Sql_ShowDebug(sql_handle); - return false; - } //checking guild_storage_db if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `id`,`guild_id`,`nameid`,`amount`,`equip`,`identify`,`refine`," "`attribute`,`card0`,`card1`,`card2`,`card3`,`option_id0`,`option_val0`,`option_parm0`,`option_id1`,`option_val1`,`option_parm1`,`option_id2`,`option_val2`,`option_parm2`,`option_id3`,`option_val3`,`option_parm3`,`option_id4`,`option_val4`,`option_parm4`,`expire_time`,`bound`,`unique_id`" @@ -2449,8 +2444,6 @@ void char_sql_config_read(const char* cfgName) { safestrncpy(schema_config.inventory_db, w2, sizeof(schema_config.inventory_db)); else if(!strcmpi(w1,"charlog_db")) safestrncpy(schema_config.charlog_db, w2, sizeof(schema_config.charlog_db)); - else if(!strcmpi(w1,"storage_db")) - safestrncpy(schema_config.storage_db, w2, sizeof(schema_config.storage_db)); else if(!strcmpi(w1,"skill_db")) safestrncpy(schema_config.skill_db, w2, sizeof(schema_config.skill_db)); else if(!strcmpi(w1,"interlog_db")) diff --git a/src/char/char.h b/src/char/char.h index 5829388a6b..2886a8c886 100644 --- a/src/char/char.h +++ b/src/char/char.h @@ -4,8 +4,6 @@ #ifndef _CHAR_SQL_H_ #define _CHAR_SQL_H_ -#define DB_NAME_LEN 256 //max len of dbs - #include "../config/core.h" #include "../common/core.h" // CORE_ST_LAST #include "../common/msg_conf.h" @@ -264,8 +262,8 @@ int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf); int char_delete_char_sql(uint32 char_id); int char_rename_char_sql(struct char_session_data *sd, uint32 char_id); int char_divorce_char_sql(int partner_id1, int partner_id2); -int char_memitemdata_to_sql(const struct item items[], int max, int id, enum storage_type tableswitch); -bool char_memitemdata_from_sql( struct s_storage* p, int max, int id, enum storage_type tableswitch ); +int char_memitemdata_to_sql(const struct item items[], int max, int id, enum storage_type tableswitch, uint8 stor_id); +bool char_memitemdata_from_sql(struct s_storage* p, int max, int id, enum storage_type tableswitch, uint8 stor_id); void disconnect_player(uint32 account_id); diff --git a/src/char/int_storage.c b/src/char/int_storage.c index 55f6b3b3fe..91fe118715 100644 --- a/src/char/int_storage.c +++ b/src/char/int_storage.c @@ -1,6 +1,7 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder +#include "../common/malloc.h" #include "../common/mmo.h" #include "../common/showmsg.h" #include "../common/socket.h" @@ -14,6 +15,54 @@ #define STORAGE_MEMINC 16 +/** + * Check if sotrage ID is valid + * @param id Storage ID + * @return True:Valid, False:Invalid + **/ +bool inter_premiumStorage_exists(uint8 id) { + if (interserv_config.storages && interserv_config.storage_count) { + int i; + for (i = 0; i < interserv_config.storage_count; i++) { + if (interserv_config.storages[i].id == id) + return true; + } + } + return false; +} + +/** + * Get max storage amount + * @param id Storage ID + * @return Max amount + **/ +int inter_premiumStorage_getMax(uint8 id) { + if (interserv_config.storages && interserv_config.storage_count) { + int i; + for (i = 0; i < interserv_config.storage_count; i++) { + if (&interserv_config.storages[i] && interserv_config.storages[i].id == id) + return interserv_config.storages[i].max_num; + } + } + return MAX_STORAGE; +} + +/** + * Get table name of storage + * @param id Storage ID + * @return Table name + **/ +const char *inter_premiumStorage_getTableName(uint8 id) { + if (interserv_config.storages && interserv_config.storage_count) { + int i; + for (i = 0; i < interserv_config.storage_count; i++) { + if (&interserv_config.storages[i] && interserv_config.storages[i].id == id) + return interserv_config.storages[i].table; + } + } + return schema_config.storage_db; +} + /** * Save inventory entries to SQL * @param char_id: Character ID to save @@ -22,7 +71,7 @@ */ static int inventory_tosql(uint32 char_id, struct s_storage* p) { - return char_memitemdata_to_sql(p->u.items_inventory, MAX_INVENTORY, char_id, TABLE_INVENTORY); + return char_memitemdata_to_sql(p->u.items_inventory, MAX_INVENTORY, char_id, TABLE_INVENTORY, p->stor_id); } /** @@ -33,7 +82,7 @@ static int inventory_tosql(uint32 char_id, struct s_storage* p) */ static int storage_tosql(uint32 account_id, struct s_storage* p) { - return char_memitemdata_to_sql(p->u.items_storage, MAX_STORAGE, account_id, TABLE_STORAGE); + return char_memitemdata_to_sql(p->u.items_storage, MAX_STORAGE, account_id, TABLE_STORAGE, p->stor_id); } /** @@ -44,7 +93,7 @@ static int storage_tosql(uint32 account_id, struct s_storage* p) */ static int cart_tosql(uint32 char_id, struct s_storage* p) { - return char_memitemdata_to_sql(p->u.items_cart, MAX_CART, char_id, TABLE_CART); + return char_memitemdata_to_sql(p->u.items_cart, MAX_CART, char_id, TABLE_CART, p->stor_id); } /** @@ -55,7 +104,7 @@ static int cart_tosql(uint32 char_id, struct s_storage* p) */ static bool inventory_fromsql(uint32 char_id, struct s_storage* p) { - return char_memitemdata_from_sql( p, MAX_INVENTORY, char_id, TABLE_INVENTORY ); + return char_memitemdata_from_sql( p, MAX_INVENTORY, char_id, TABLE_INVENTORY, p->stor_id ); } /** @@ -66,18 +115,19 @@ static bool inventory_fromsql(uint32 char_id, struct s_storage* p) */ static bool cart_fromsql(uint32 char_id, struct s_storage* p) { - return char_memitemdata_from_sql( p, MAX_CART, char_id, TABLE_CART ); + return char_memitemdata_from_sql( p, MAX_CART, char_id, TABLE_CART, p->stor_id ); } /** * Fetch storage entries from table * @param char_id: Character ID to fetch * @param p: Storage list to save the entries + * @param stor_id: Storage ID * @return True if success, False if failed */ static bool storage_fromsql(uint32 account_id, struct s_storage* p) { - return char_memitemdata_from_sql( p, MAX_STORAGE, account_id, TABLE_STORAGE ); + return char_memitemdata_from_sql( p, MAX_STORAGE, account_id, TABLE_STORAGE, p->stor_id ); } /** @@ -89,7 +139,7 @@ static bool storage_fromsql(uint32 account_id, struct s_storage* p) bool guild_storage_tosql(int guild_id, struct s_storage* p) { //ShowInfo("Guild Storage has been saved (GID: %d)\n", guild_id); - return char_memitemdata_to_sql(p->u.items_guild, MAX_GUILD_STORAGE, guild_id, TABLE_GUILD_STORAGE); + return char_memitemdata_to_sql(p->u.items_guild, MAX_GUILD_STORAGE, guild_id, TABLE_GUILD_STORAGE, p->stor_id); } /** @@ -100,13 +150,31 @@ bool guild_storage_tosql(int guild_id, struct s_storage* p) */ bool guild_storage_fromsql(int guild_id, struct s_storage* p) { - return char_memitemdata_from_sql( p, MAX_GUILD_STORAGE, guild_id, TABLE_GUILD_STORAGE ); + return char_memitemdata_from_sql( p, MAX_GUILD_STORAGE, guild_id, TABLE_GUILD_STORAGE, p->stor_id ); +} + +static void inter_storage_checkDB(void) { + int i = 0; + // Checking storage tables + for (i = 0; i < interserv_config.storage_count; i++) { + if (!&interserv_config.storages[i] || !interserv_config.storages[i].name || !interserv_config.storages[i].table || interserv_config.storages[i].table == '\0') + continue; + if (SQL_ERROR == Sql_Query(sql_handle, "SELECT `id`,`account_id`,`nameid`,`amount`,`equip`,`identify`,`refine`," + "`attribute`,`card0`,`card1`,`card2`,`card3`,`option_id0`,`option_val0`,`option_parm0`,`option_id1`,`option_val1`,`option_parm1`," + "`option_id2`,`option_val2`,`option_parm2`,`option_id3`,`option_val3`,`option_parm3`,`option_id4`,`option_val4`,`option_parm4`," + "`expire_time`,`bound`,`unique_id`" + " FROM `%s` LIMIT 1;", interserv_config.storages[i].table) ){ + Sql_ShowDebug(sql_handle); + } + } + Sql_FreeResult(sql_handle); } //--------------------------------------------------------- // storage data initialize void inter_storage_sql_init(void) { + inter_storage_checkDB(); return; } @@ -423,41 +491,56 @@ static void mapif_storage_data_loaded(int fd, uint32 account_id, char type, stru * @param char_id * @param success * @param type + * @param stor_id */ -void mapif_storage_saved(int fd, uint32 account_id, uint32 char_id, bool success, char type) { - WFIFOHEAD(fd,8); +void mapif_storage_saved(int fd, uint32 account_id, uint32 char_id, bool success, char type, uint8 stor_id) { + WFIFOHEAD(fd,9); WFIFOW(fd, 0) = 0x388b; WFIFOL(fd, 2) = account_id; WFIFOB(fd, 6) = success; WFIFOB(fd, 7) = type; - WFIFOSET(fd,8); + WFIFOB(fd, 8) = stor_id; + WFIFOSET(fd,9); } /** * Requested inventory/cart/storage data for a player - * ZI 0x308a .B .L .L + * ZI 0x308a .B .L .L .B .B * @param fd */ bool mapif_parse_StorageLoad(int fd) { uint32 aid, cid; int type; + uint8 stor_id, mode; struct s_storage stor; bool res = true; - RFIFOHEAD(fd); type = RFIFOB(fd,2); aid = RFIFOL(fd,3); cid = RFIFOL(fd,7); + stor_id = RFIFOB(fd,11); memset(&stor, 0, sizeof(struct s_storage)); + stor.stor_id = stor_id; //ShowInfo("Loading storage for AID=%d.\n", aid); switch (type) { case TABLE_INVENTORY: res = inventory_fromsql(cid, &stor); break; - case TABLE_STORAGE: res = storage_fromsql(aid, &stor); break; + case TABLE_STORAGE: + if (!inter_premiumStorage_exists(stor_id)) { + ShowError("Invalid storage with id %d\n", stor_id); + return false; + } + res = storage_fromsql(aid, &stor); + break; case TABLE_CART: res = cart_fromsql(cid, &stor); break; default: return false; } + + mode = RFIFOB(fd, 12); + stor.state.put = (mode&STOR_MODE_PUT) ? 1 : 0; + stor.state.get = (mode&STOR_MODE_GET) ? 1 : 0; + mapif_storage_data_loaded(fd, aid, type, stor, res); return true; } @@ -482,11 +565,17 @@ bool mapif_parse_StorageSave(int fd) { //ShowInfo("Saving storage data for AID=%d.\n", aid); switch(type){ case TABLE_INVENTORY: inventory_tosql(cid, &stor); break; - case TABLE_STORAGE: storage_tosql(aid, &stor); break; - case TABLE_CART: cart_tosql(cid, &stor); break; + case TABLE_STORAGE: + if (!inter_premiumStorage_exists(stor.stor_id)) { + ShowError("Invalid storage with id %d\n", stor.stor_id); + return false; + } + storage_tosql(aid, &stor); + break; + case TABLE_CART: cart_tosql(cid, &stor); break; default: return false; } - mapif_storage_saved(fd, aid, cid, true, type); + mapif_storage_saved(fd, aid, cid, true, type, stor.stor_id); return false; } diff --git a/src/char/int_storage.h b/src/char/int_storage.h index 9c391e4b45..80c88ff34e 100644 --- a/src/char/int_storage.h +++ b/src/char/int_storage.h @@ -11,6 +11,10 @@ void inter_storage_sql_final(void); void inter_storage_delete(uint32 account_id); void inter_guild_storage_delete(int guild_id); +bool inter_premiumStorage_exists(uint8 id); +int inter_premiumStorage_getMax(uint8 id); +const char *inter_premiumStorage_getTableName(uint8 id); + bool inter_storage_parse_frommap(int fd); bool guild_storage_tosql(int guild_id, struct s_storage *p); diff --git a/src/char/inter.c b/src/char/inter.c index e7b9ffc7dc..ecb43854b4 100644 --- a/src/char/inter.c +++ b/src/char/inter.c @@ -39,7 +39,7 @@ char char_server_id[32] = "ragnarok"; char char_server_pw[32] = ""; // Allow user to send empty password (bugreport:7787) char char_server_db[32] = "ragnarok"; char default_codepage[32] = ""; //Feature by irmin. - +struct Inter_Config interserv_config; unsigned int party_share_level = 10; /// Received packet Lengths from map-server @@ -52,7 +52,7 @@ int inter_recv_packet_length[] = { -1,-1,10,10, 0,-1,12, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3050- Auction System [Zephyrus] 6,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3060- Quest system [Kevin] [Inkfish] -1,10, 6,-1, 0, 0, 0, 0, 0, 0, 0, 0, -1,10, 6,-1, // 3070- Mercenary packets [Zephyrus], Elemental packets [pakpil] - 48,14,-1, 6, 0, 0, 0, 0, 0, 0,11,-1, 0, 0, 0, 0, // 3080- Pet System, Storage + 48,14,-1, 6, 0, 0, 0, 0, 0, 0,13,-1, 0, 0, 0, 0, // 3080- Pet System, Storage -1,10,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3090- Homunculus packets [albator] }; @@ -773,6 +773,8 @@ static int inter_config_read(const char* cfgName) party_share_level = (unsigned int)atof(w2); else if(!strcmpi(w1,"log_inter")) charserv_config.log_inter = atoi(w2); + else if(!strcmpi(w1,"inter_server_conf")) + strcpy(interserv_config.cfgFile, w2); else if(!strcmpi(w1,"import")) inter_config_read(w2); } @@ -801,11 +803,86 @@ int inter_log(char* fmt, ...) return 0; } +/** + * Read inter config file + **/ +static void inter_config_readConf(void) { + int count = 0; + config_setting_t *config = NULL; + + if (conf_read_file(&interserv_config.cfg, interserv_config.cfgFile)) + return; + + // Read storages + config = config_lookup(&interserv_config.cfg, "storages"); + if (config && (count = config_setting_length(config))) { + int i; + for (i = 0; i < count; i++) { + int id, max_num; + const char *name, *tablename; + struct s_storage_table table; + config_setting_t *entry = config_setting_get_elem(config, i); + + if (!config_setting_lookup_int(entry, "id", &id)) { + ShowConfigWarning(entry, "inter_config_readConf: Cannot find storage \"id\" in member %d", i); + continue; + } + + if (!config_setting_lookup_string(entry, "name", &name)) { + ShowConfigWarning(entry, "inter_config_readConf: Cannot find storage \"name\" in member %d", i); + continue; + } + + if (!config_setting_lookup_string(entry, "table", &tablename)) { + ShowConfigWarning(entry, "inter_config_readConf: Cannot find storage \"table\" in member %d", i); + continue; + } + + if (!config_setting_lookup_int(entry, "max", &max_num)) + max_num = MAX_STORAGE; + else if (max_num > MAX_STORAGE) { + ShowConfigWarning(entry, "Storage \"%s\" has \"max\" %d, max is MAX_STORAGE (%d)!\n", name, max_num, MAX_STORAGE); + max_num = MAX_STORAGE; + } + + memset(&table, 0, sizeof(struct s_storage_table)); + + RECREATE(interserv_config.storages, struct s_storage_table, interserv_config.storage_count+1); + interserv_config.storages[interserv_config.storage_count].id = id; + safestrncpy(interserv_config.storages[interserv_config.storage_count].name, name, NAME_LENGTH); + safestrncpy(interserv_config.storages[interserv_config.storage_count].table, tablename, DB_NAME_LEN); + interserv_config.storages[interserv_config.storage_count].max_num = max_num; + interserv_config.storage_count++; + } + } + + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' storage informations in '"CL_WHITE"%s"CL_RESET"'\n", interserv_config.storage_count, interserv_config.cfgFile); +} + +void inter_config_finalConf(void) { + + if (interserv_config.storages) + aFree(interserv_config.storages); + interserv_config.storages = NULL; + interserv_config.storage_count = 0; + + config_destroy(&interserv_config.cfg); +} + +static void inter_config_defaults(void) { + interserv_config.storage_count = 0; + interserv_config.storages = NULL; + + safestrncpy(interserv_config.cfgFile, "conf/inter_server.conf", sizeof(interserv_config.cfgFile)); +} + // initialize int inter_init_sql(const char *file) { //int i; + + inter_config_defaults(); inter_config_read(file); //DB connection initialized @@ -826,6 +903,7 @@ int inter_init_sql(const char *file) } wis_db = idb_alloc(DB_OPT_RELEASE_DATA); + inter_config_readConf(); inter_guild_sql_init(); inter_storage_sql_init(); inter_party_sql_init(); @@ -845,6 +923,7 @@ void inter_final(void) { wis_db->destroy(wis_db, NULL); + inter_config_finalConf(); inter_guild_sql_final(); inter_storage_sql_final(); inter_party_sql_final(); @@ -860,8 +939,28 @@ void inter_final(void) return; } +/** + * IZ 0x388c .W { .? }*? + * Sends storage information to map-server + * @param fd + **/ +void inter_Storage_sendInfo(int fd) { + int size = sizeof(struct s_storage_table), len = 4 + interserv_config.storage_count * size, i = 0; + // Send storage table information + WFIFOHEAD(fd, len); + WFIFOW(fd, 0) = 0x388c; + WFIFOW(fd, 2) = len; + for (i = 0; i < interserv_config.storage_count; i++) { + if (!&interserv_config.storages[i] || !interserv_config.storages[i].name) + continue; + memcpy(WFIFOP(fd, 4 + size*i), &interserv_config.storages[i], size); + } + WFIFOSET(fd, len); +} + int inter_mapif_init(int fd) { + inter_Storage_sendInfo(fd); return 0; } diff --git a/src/char/inter.h b/src/char/inter.h index 16e7974120..d8de38e3df 100644 --- a/src/char/inter.h +++ b/src/char/inter.h @@ -4,8 +4,19 @@ #ifndef _INTER_SQL_H_ #define _INTER_SQL_H_ +#include "../common/conf.h" +#include "../common/mmo.h" #include "../common/sql.h" +struct Inter_Config { + char cfgFile[128]; ///< Inter-Config file + config_t cfg; ///< Config + struct s_storage_table *storages; ///< Storage name & table information + uint8 storage_count; ///< Number of available storage +}; + +extern struct Inter_Config interserv_config; + int inter_init_sql(const char *file); void inter_final(void); int inter_parse_frommap(int fd); diff --git a/src/common/mmo.h b/src/common/mmo.h index c5dd6f82f7..31bbe881ba 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -79,6 +79,7 @@ #define MAX_QUEST_DROPS 3 ///Max quest drops for a quest #define MAX_PC_BONUS_SCRIPT 50 ///Max bonus script can be fetched from `bonus_script` table on player load [Cydh] #define MAX_ITEM_RDM_OPT 5 /// Max item random option [Napster] +#define DB_NAME_LEN 256 //max len of dbs // for produce #define MIN_ATTRIBUTE 0 @@ -303,13 +304,26 @@ enum storage_type { TABLE_GUILD_STORAGE, }; +enum e_storage_mode { + STOR_MODE_NONE = 0x0, + STOR_MODE_GET = 0x1, + STOR_MODE_PUT = 0x2, + STOR_MODE_ALL = 0x3, +}; + struct s_storage { bool dirty; ///< Dirty status, data needs to be saved bool status; ///< Current status of storage (opened or closed) - int amount; ///< Amount of items in storage + uint16 amount; ///< Amount of items in storage bool lock; ///< If locked, can't use storage when item bound retrieval uint32 id; ///< Account ID / Character ID / Guild ID (owner of storage) enum storage_type type; ///< Type of storage (inventory, cart, storage, guild storage) + uint16 max_amount; + uint8 stor_id; ///< Storage ID + struct { + unsigned get : 1; + unsigned put : 1; + } state; union { // Max for inventory, storage, cart, and guild storage are 1637 each without changing this struct and struct item [2014/10/27] struct item items_inventory[MAX_INVENTORY]; struct item items_storage[MAX_STORAGE]; @@ -318,6 +332,13 @@ struct s_storage { } u; }; +struct s_storage_table { + char name[NAME_LENGTH]; + char table[DB_NAME_LEN]; + uint16 max_num; + uint8 id; +}; + struct s_pet { uint32 account_id; uint32 char_id; diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 5f73e01854..19fac25783 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -922,6 +922,11 @@ ACMD_FUNC(guildstorage) return -1; } + if (sd->state.storage_flag == 3) { + clif_displaymessage(fd, msg_txt(sd,250)); + return -1; + } + storage_guild_storageopen(sd); clif_displaymessage(fd, msg_txt(sd,920)); // Guild storage opened. return 0; @@ -5490,7 +5495,7 @@ ACMD_FUNC(storeall) if (sd->inventory.u.items_inventory[i].amount) { if(sd->inventory.u.items_inventory[i].equip != 0) pc_unequipitem(sd, i, 3); - storage_storageadd(sd, i, sd->inventory.u.items_inventory[i].amount); + storage_storageadd(sd, &sd->storage, i, sd->inventory.u.items_inventory[i].amount); } } storage_storageclose(sd); @@ -5508,10 +5513,14 @@ ACMD_FUNC(clearstorage) clif_displaymessage(fd, msg_txt(sd,250)); return -1; } + if (sd->state.storage_flag == 3) { + clif_displaymessage(fd, msg_txt(sd,250)); + return -1; + } j = sd->storage.amount; for (i = 0; i < j; ++i) { - storage_delitem(sd, i, sd->storage.u.items_storage[i].amount); + storage_delitem(sd, &sd->storage, i, sd->storage.u.items_storage[i].amount); } sd->state.storage_flag = 1; storage_storageclose(sd); @@ -5544,6 +5553,11 @@ ACMD_FUNC(cleargstorage) return -1; } + if (sd->state.storage_flag == 3) { + clif_displaymessage(fd, msg_txt(sd,250)); + return -1; + } + gstorage = guild2storage2(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; @@ -8606,7 +8620,7 @@ ACMD_FUNC(itemlist) if( strcmp(parent_cmd, "storagelist") == 0 ) { location = "storage"; items = sd->storage.u.items_storage; - size = sd->storage_size; + size = sd->storage.max_amount; } else if( strcmp(parent_cmd, "cartlist") == 0 ) { location = "cart"; items = sd->cart.u.items_cart; diff --git a/src/map/chrif.c b/src/map/chrif.c index 65bf2f37f8..1563fdbc78 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -300,13 +300,15 @@ int chrif_save(struct map_session_data *sd, int flag) { chrif_bsdata_save(sd, (flag && (flag != 3))); if (sd->state.storage_flag == 1) - intif_storage_save(sd,TABLE_STORAGE); - intif_storage_save(sd,TABLE_INVENTORY); - intif_storage_save(sd,TABLE_CART); + intif_storage_save(sd,&sd->storage); + intif_storage_save(sd,&sd->inventory); + intif_storage_save(sd,&sd->cart); //For data sync if (sd->state.storage_flag == 2) storage_guild_storagesave(sd->status.account_id, sd->status.guild_id, flag); + if (&sd->premiumStorage && sd->premiumStorage.dirty) + intif_storage_save(sd, &sd->premiumStorage); if (flag) sd->state.storage_flag = 0; //Force close it. @@ -1602,10 +1604,10 @@ void chrif_parse_ack_vipActive(int fd) { sd->vip.enabled = 1; sd->vip.time = vip_time; // Increase storage size for VIP. - sd->storage_size = battle_config.vip_storage_increase + MIN_STORAGE; - if (sd->storage_size > MAX_STORAGE) { + sd->storage.max_amount = battle_config.vip_storage_increase + MIN_STORAGE; + if (sd->storage.max_amount > MAX_STORAGE) { ShowError("intif_parse_ack_vipActive: Storage size for player %s (%d:%d) is larger than MAX_STORAGE. Storage size has been set to MAX_STORAGE.\n", sd->status.name, sd->status.account_id, sd->status.char_id); - sd->storage_size = MAX_STORAGE; + sd->storage.max_amount = MAX_STORAGE; } // Magic Stone requirement avoidance for VIP. if (battle_config.vip_gemstone) @@ -1613,7 +1615,7 @@ void chrif_parse_ack_vipActive(int fd) { } else if (sd->vip.enabled) { sd->vip.enabled = 0; sd->vip.time = 0; - sd->storage_size = MIN_STORAGE; + sd->storage.max_amount = MIN_STORAGE; sd->special_state.no_gemstone = 0; clif_displaymessage(sd->fd,msg_txt(sd,438)); } @@ -1998,6 +2000,12 @@ void do_init_chrif(void) { exit(EXIT_FAILURE); } + if (sizeof(struct s_storage) > 0xFFFF){ + ShowError("s_storage size = %d is too big to be transmitted. (must be below 0xFFFF) \n", + sizeof(struct s_storage)); + exit(EXIT_FAILURE); + } + if((sizeof(struct bonus_script_data) * MAX_PC_BONUS_SCRIPT) > 0xFFFF){ ShowError("bonus_script_data size = %d is too big, please reduce MAX_PC_BONUS_SCRIPT (%d) size. (must be below 0xFFFF).\n", (sizeof(struct bonus_script_data) * MAX_PC_BONUS_SCRIPT), MAX_PC_BONUS_SCRIPT); diff --git a/src/map/clif.c b/src/map/clif.c index e495d84c4b..b04995719f 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -2813,7 +2813,7 @@ void clif_equiplist(struct map_session_data *sd) } } -void clif_storagelist(struct map_session_data* sd, struct item* items, int items_length) +void clif_storagelist(struct map_session_data* sd, struct item* items, int items_length, const char *storename) { static const int client_buf = 0x5000; // Max buffer to send struct item_data *id; @@ -2883,7 +2883,7 @@ void clif_storagelist(struct map_session_data* sd, struct item* items, int items WFIFOW(sd->fd,0)=cmd; WFIFOW(sd->fd,2)=sidx+nn*s; #if PACKETVER >= 20120925 - memset((char*)WFIFOP(sd->fd,4),0,24); //storename + safestrncpy((char*)WFIFOP(sd->fd,4), storename, NAME_LENGTH); //storename #endif memcpy(WFIFOP(sd->fd,sidx),buf + sidx + i*s,nn*s); WFIFOSET(sd->fd,WFIFOW(sd->fd,2)); @@ -2895,12 +2895,23 @@ void clif_storagelist(struct map_session_data* sd, struct item* items, int items WFIFOW(sd->fd,0)=cmde; WFIFOW(sd->fd,2)=sidxe+nn*se; #if PACKETVER >= 20120925 - memset((char*)WFIFOP(sd->fd,4),0,24); //storename + safestrncpy((char*)WFIFOP(sd->fd,4), storename, NAME_LENGTH); //storename #endif memcpy(WFIFOP(sd->fd,sidxe),bufe + sidxe + i*se,nn*se); WFIFOSET(sd->fd,WFIFOW(sd->fd,2)); } + // Empty storage + if (n == 0 && ne == 0) { + WFIFOHEAD(sd->fd, 4+NAME_LENGTH); + WFIFOW(sd->fd,0) = cmd; + WFIFOW(sd->fd,2) = 4+NAME_LENGTH; +#if PACKETVER >= 20120925 + safestrncpy((char*)WFIFOP(sd->fd,4), storename, NAME_LENGTH); //storename +#endif + WFIFOSET(sd->fd,WFIFOW(sd->fd,2)); + } + if( buf ) aFree(buf); if( bufe ) aFree(bufe); } @@ -9155,7 +9166,7 @@ void clif_refresh_storagewindow(struct map_session_data *sd) { // Notify the client that the storage is open if( sd->state.storage_flag == 1 ) { storage_sortitem(sd->storage.u.items_storage, ARRAYLENGTH(sd->storage.u.items_storage)); - clif_storagelist(sd, sd->storage.u.items_storage, ARRAYLENGTH(sd->storage.u.items_storage)); + clif_storagelist(sd, sd->storage.u.items_storage, ARRAYLENGTH(sd->storage.u.items_storage), storage_getName(0)); clif_updatestorageamount(sd, sd->storage.amount, MAX_STORAGE); } // Notify the client that the gstorage is open otherwise it will @@ -9167,7 +9178,7 @@ void clif_refresh_storagewindow(struct map_session_data *sd) { intif_request_guild_storage(sd->status.account_id, sd->status.guild_id); else { storage_sortitem(gstor->u.items_guild, ARRAYLENGTH(gstor->u.items_guild)); - clif_storagelist(sd, gstor->u.items_guild, ARRAYLENGTH(gstor->u.items_guild)); + clif_storagelist(sd, gstor->u.items_guild, ARRAYLENGTH(gstor->u.items_guild), "Guild Storage"); clif_updatestorageamount(sd, gstor->amount, MAX_GUILD_STORAGE); } } @@ -12504,10 +12515,12 @@ void clif_parse_MoveToKafra(int fd, struct map_session_data *sd) return; if (sd->state.storage_flag == 1) - storage_storageadd(sd, item_index, item_amount); + storage_storageadd(sd, &sd->storage, item_index, item_amount); else if (sd->state.storage_flag == 2) storage_guild_storageadd(sd, item_index, item_amount); + else if (sd->state.storage_flag == 3) + storage_storageadd(sd, &sd->premiumStorage, item_index, item_amount); } @@ -12524,9 +12537,11 @@ void clif_parse_MoveFromKafra(int fd,struct map_session_data *sd) item_amount = RFIFOL(fd,info->pos[1]); if (sd->state.storage_flag == 1) - storage_storageget(sd, item_index, item_amount); + storage_storageget(sd, &sd->storage, item_index, item_amount); else if(sd->state.storage_flag == 2) storage_guild_storageget(sd, item_index, item_amount); + else if(sd->state.storage_flag == 3) + storage_storageget(sd, &sd->premiumStorage, item_index, item_amount); } @@ -12544,9 +12559,11 @@ void clif_parse_MoveToKafraFromCart(int fd, struct map_session_data *sd){ return; if (sd->state.storage_flag == 1) - storage_storageaddfromcart(sd, idx, amount); + storage_storageaddfromcart(sd, &sd->storage, idx, amount); else if (sd->state.storage_flag == 2) storage_guild_storageaddfromcart(sd, idx, amount); + else if (sd->state.storage_flag == 3) + storage_storageaddfromcart(sd, &sd->premiumStorage, idx, amount); } @@ -12563,10 +12580,12 @@ void clif_parse_MoveFromKafraToCart(int fd, struct map_session_data *sd){ return; if (sd->state.storage_flag == 1) - storage_storagegettocart(sd, idx, amount); + storage_storagegettocart(sd, &sd->storage, idx, amount); else if (sd->state.storage_flag == 2) storage_guild_storagegettocart(sd, idx, amount); + else if (sd->state.storage_flag == 3) + storage_storagegettocart(sd, &sd->premiumStorage, idx, amount); } @@ -12579,6 +12598,8 @@ void clif_parse_CloseKafra(int fd, struct map_session_data *sd) else if( sd->state.storage_flag == 2 ) storage_guild_storageclose(sd); + else if( sd->state.storage_flag == 3 ) + storage_premiumStorage_close(sd); } diff --git a/src/map/clif.h b/src/map/clif.h index cb61868904..731e94625a 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -616,7 +616,7 @@ void clif_tradecompleted(struct map_session_data* sd, int fail); void clif_tradeundo(struct map_session_data* sd); // storage -void clif_storagelist(struct map_session_data* sd, struct item* items, int items_length); +void clif_storagelist(struct map_session_data* sd, struct item* items, int items_length, const char *storename); void clif_updatestorageamount(struct map_session_data* sd, int amount, int max_amount); void clif_storageitemadded(struct map_session_data* sd, struct item* i, int index, int amount); void clif_storageitemremoved(struct map_session_data* sd, int index, int amount); diff --git a/src/map/intif.c b/src/map/intif.c index 446e7b150a..ea059cea04 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -35,7 +35,7 @@ static const int packet_len_table[] = { -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,-1, 8, 0, 0, 0, 0, //0x3880 Pet System, Storages + 12,-1, 7, 3, 0, 0, 0, 0, 0, 0,-1, 9, -1, 0, 0, 0, //0x3880 Pet System, Storages -1,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3890 Homunculus [albator] }; @@ -3146,7 +3146,7 @@ static bool intif_parse_StorageReceived(int fd) char type = RFIFOB(fd,4); uint32 account_id = RFIFOL(fd, 5); struct map_session_data *sd = map_id2sd(account_id); - struct s_storage *stor; //storage + struct s_storage *stor, *p; //storage size_t sz_stor = sizeof(struct s_storage); if (!sd) { @@ -3159,22 +3159,31 @@ static bool intif_parse_StorageReceived(int fd) return false; } + p = (struct s_storage *)RFIFOP(fd,10); + switch (type) { case TABLE_INVENTORY: stor = &sd->inventory; break; - case TABLE_STORAGE: stor = &sd->storage; break; + case TABLE_STORAGE: + if (p->stor_id == 0) + stor = &sd->storage; + else + stor = &sd->premiumStorage; + break; case TABLE_CART: stor = &sd->cart; break; default: return false; } - if (stor->status) { // Already open.. lets ignore this update - ShowWarning("intif_parse_StorageReceived: storage received for a client already open (User %d:%d)\n", sd->status.account_id, sd->status.char_id); - return false; - } - if (stor->dirty) { // Already have storage, and it has been modified and not saved yet! Exploit! - ShowWarning("intif_parse_StorageReceived: received storage for an already modified non-saved storage! (User %d:%d)\n", sd->status.account_id, sd->status.char_id); - return false; + if (stor->stor_id == p->stor_id) { + if (stor->status) { // Already open.. lets ignore this update + ShowWarning("intif_parse_StorageReceived: storage received for a client already open (User %d:%d)\n", sd->status.account_id, sd->status.char_id); + return false; + } + if (stor->dirty) { // Already have storage, and it has been modified and not saved yet! Exploit! + ShowWarning("intif_parse_StorageReceived: received storage for an already modified non-saved storage! (User %d:%d)\n", sd->status.account_id, sd->status.char_id); + return false; + } } if (RFIFOW(fd,2)-10 != sz_stor) { ShowError("intif_parse_StorageReceived: data size error %d %d\n",RFIFOW(fd,2)-10 , sz_stor); @@ -3182,7 +3191,7 @@ static bool intif_parse_StorageReceived(int fd) return false; } - memcpy(stor, RFIFOP(fd,10), sz_stor); //copy the items data to correct destination + memcpy(stor, p, sz_stor); //copy the items data to correct destination switch (type) { case TABLE_INVENTORY: { @@ -3224,7 +3233,15 @@ static bool intif_parse_StorageReceived(int fd) break; case TABLE_STORAGE: - pc_check_available_item(sd, ITMCHK_STORAGE); + if (stor->stor_id) + storage_premiumStorage_open(sd); + else { +#ifdef VIP_ENABLE + if (!pc_isvip(sd)) + stor->max_amount = MIN_STORAGE; +#endif + pc_check_available_item(sd, ITMCHK_STORAGE); + } break; } return true; @@ -3232,7 +3249,7 @@ static bool intif_parse_StorageReceived(int fd) /** * Save inventory/cart/storage data for a player - * IZ 0x388b .L .B .B + * IZ 0x388b .L .B .B .B * @param fd */ static void intif_parse_StorageSaved(int fd) @@ -3244,6 +3261,8 @@ static void intif_parse_StorageSaved(int fd) break; case TABLE_STORAGE: //storage //ShowInfo("Storage has been saved (AID: %d).\n", RFIFOL(fd, 2)); + if (RFIFOB(fd, 8)) + storage_premiumStorage_saved(map_id2sd(RFIFOL(fd, 2))); break; case TABLE_CART: // cart //ShowInfo("Cart has been saved (AID: %d).\n", RFIFOL(fd, 2)); @@ -3251,7 +3270,7 @@ static void intif_parse_StorageSaved(int fd) struct map_session_data *sd = map_id2sd(RFIFOL(fd, 2)); if( sd && sd->state.prevend ){ - intif_storage_request(sd,TABLE_CART); + intif_storage_request(sd,TABLE_CART,0,STOR_MODE_ALL); } } break; @@ -3262,24 +3281,54 @@ static void intif_parse_StorageSaved(int fd) ShowError("Failed to save inventory/cart/storage data (AID: %d, type: %d).\n", RFIFOL(fd, 2), RFIFOB(fd, 7)); } +/** + * IZ 0x388c .W { .? }*? + * Receive storage information + **/ +void intif_parse_StorageInfo_recv(int fd) { + int i, size = sizeof(struct s_storage_table), count = (RFIFOW(fd, 2) - 4) / size; + + storage_count = 0; + if (storage_db) + aFree(storage_db); + storage_db = NULL; + + for (i = 0; i < count; i++) { + char name[NAME_LENGTH+1]; + safestrncpy(name, (char *)RFIFOP(fd, 5 + size * i), NAME_LENGTH); + if (!name || name[0] == '\0') + continue; + RECREATE(storage_db, struct s_storage_table, storage_count+1); + memcpy(&storage_db[storage_count], RFIFOP(fd, 4 + size * i), size); + storage_count++; + } + + if (battle_config.etc_log) + ShowInfo("Received '"CL_WHITE"%d"CL_RESET"' storage info from inter-server.\n", storage_count); +} + /** * Request inventory/cart/storage data for a player - * ZI 0x308a .B .L .L + * ZI 0x308a .B .L .L .B * @param sd: Player data * @param type: Storage type + * @param stor_id: Storage ID + * @param mode: Storage mode * @return false - error, true - message sent */ -bool intif_storage_request(struct map_session_data *sd, enum storage_type type) +bool intif_storage_request(struct map_session_data *sd, enum storage_type type, uint8 stor_id, uint8 mode) { if (CheckForCharServer()) return false; - WFIFOHEAD(inter_fd, 11); + WFIFOHEAD(inter_fd, 13); WFIFOW(inter_fd, 0) = 0x308a; WFIFOB(inter_fd, 2) = type; WFIFOL(inter_fd, 3) = sd->status.account_id; WFIFOL(inter_fd, 7) = sd->status.char_id; - WFIFOSET(inter_fd, 11); + WFIFOB(inter_fd, 11) = stor_id; + WFIFOB(inter_fd, 12) = mode; + WFIFOSET(inter_fd, 13); return true; } @@ -3287,37 +3336,23 @@ bool intif_storage_request(struct map_session_data *sd, enum storage_type type) * Request to save inventory/cart/storage data from player * ZI 0x308b .W .B .L .L .?B * @param sd: Player data - * @param type: Storage type + * @param stor: Storage data * @ return false - error, true - message sent */ -bool intif_storage_save(struct map_session_data *sd, enum storage_type type) +bool intif_storage_save(struct map_session_data *sd, struct s_storage *stor) { int stor_size = sizeof(struct s_storage); - struct s_storage *stor; nullpo_retr(false, sd); + nullpo_retr(false, stor); if (CheckForCharServer()) return false; - switch(type) { - case TABLE_INVENTORY: - stor = &sd->inventory; - break; - case TABLE_STORAGE: - stor = &sd->storage; - break; - case TABLE_CART: - stor = &sd->cart; - break; - default: - return false; - } - WFIFOHEAD(inter_fd, stor_size+13); WFIFOW(inter_fd, 0) = 0x308b; WFIFOW(inter_fd, 2) = stor_size+13; - WFIFOB(inter_fd, 4) = type; + WFIFOB(inter_fd, 4) = stor->type; WFIFOL(inter_fd, 5) = sd->status.account_id; WFIFOL(inter_fd, 9) = sd->status.char_id; memcpy(WFIFOP(inter_fd, 13), stor, stor_size); @@ -3440,6 +3475,7 @@ int intif_parse(int fd) // Storage case 0x388a: intif_parse_StorageReceived(fd); break; case 0x388b: intif_parse_StorageSaved(fd); break; + case 0x388c: intif_parse_StorageInfo_recv(fd); break; // Homunculus System case 0x3890: intif_parse_CreateHomunculus(fd); break; diff --git a/src/map/intif.h b/src/map/intif.h index 79c8d4d9a0..e5d6b9c45c 100644 --- a/src/map/intif.h +++ b/src/map/intif.h @@ -111,8 +111,8 @@ int intif_elemental_save(struct s_elemental *ele); int intif_request_accinfo(int u_fd, int aid, int group_lv, char* query, char type); // STORAGE -bool intif_storage_request(struct map_session_data *sd, enum storage_type type); -bool intif_storage_save(struct map_session_data *sd, enum storage_type type); +bool intif_storage_request(struct map_session_data *sd, enum storage_type type, uint8 stor_id, uint8 mode); +bool intif_storage_save(struct map_session_data *sd, struct s_storage *stor); int CheckForCharServer(void); diff --git a/src/map/pc.c b/src/map/pc.c index 56a64cb300..5c5a774412 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1151,6 +1151,7 @@ bool pc_authok(struct map_session_data *sd, uint32 login_id2, time_t expiration_ memset(&sd->inventory, 0, sizeof(struct s_storage)); memset(&sd->cart, 0, sizeof(struct s_storage)); memset(&sd->storage, 0, sizeof(struct s_storage)); + memset(&sd->premiumStorage, 0, sizeof(struct s_storage)); memset(&sd->equip_index, -1, sizeof(sd->equip_index)); if( sd->status.option&OPTION_INVISIBLE && !pc_can_use_command( sd, "hide", COMMAND_ATCOMMAND ) ){ @@ -1399,11 +1400,9 @@ void pc_reg_received(struct map_session_data *sd) return; sd->state.active = 1; - intif_storage_request(sd,TABLE_INVENTORY); // Request inventory data - intif_storage_request(sd,TABLE_CART); // Request cart data - intif_storage_request(sd,TABLE_STORAGE); // Request storage data - - sd->storage_size = MIN_STORAGE; //default to min + intif_storage_request(sd,TABLE_STORAGE, 0, STOR_MODE_ALL); // Request storage data + intif_storage_request(sd,TABLE_CART, 0, STOR_MODE_ALL); // Request cart data + intif_storage_request(sd,TABLE_INVENTORY, 0, STOR_MODE_ALL); // Request inventory data if (sd->status.party_id) party_member_joined(sd); @@ -9970,7 +9969,7 @@ void pc_check_available_item(struct map_session_data *sd, uint8 type) } if (battle_config.item_check&ITMCHK_STORAGE || type&ITMCHK_STORAGE) { // Check for invalid(ated) items in storage. - for(i = 0; i < sd->storage_size; i++) { + for(i = 0; i < sd->storage.max_amount; i++) { nameid = sd->storage.u.items_storage[i].nameid; if (!nameid) @@ -9979,7 +9978,7 @@ void pc_check_available_item(struct map_session_data *sd, uint8 type) sprintf(output, msg_txt(sd, 711), nameid); // Item %hu has been removed from your storage. clif_displaymessage(sd->fd, output); ShowWarning("Removed invalid/disabled item (ID: %hu, amount: %d) from storage (char_id: %d).\n", nameid, sd->storage.u.items_storage[i].amount, sd->status.char_id); - storage_delitem(sd, i, sd->storage.u.items_storage[i].amount); + storage_delitem(sd, &sd->storage, i, sd->storage.u.items_storage[i].amount); continue; } if (!sd->storage.u.items_storage[i].unique_id && !itemdb_isstackable(nameid)) diff --git a/src/map/pc.h b/src/map/pc.h index 5d5e78e19f..0f3ebc1093 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -206,7 +206,7 @@ struct map_session_data { unsigned int arrow_atk : 1; unsigned int gangsterparadise : 1; unsigned int rest : 1; - unsigned int storage_flag : 2; //0: closed, 1: Normal Storage open, 2: guild storage open [Skotlex] + unsigned int storage_flag : 3; //0: closed, 1: Normal Storage open, 2: guild storage open [Skotlex], 3: Premium Storage unsigned int snovice_dead_flag : 1; //Explosion spirits on death: 0 off, 1 used. unsigned int abra_flag : 2; // Abracadabra bugfix by Aru unsigned int autocast : 1; // Autospell flag [Inkfish] @@ -275,7 +275,7 @@ struct map_session_data { struct mmo_charstatus status; // Item Storages - struct s_storage storage; + struct s_storage storage, premiumStorage; struct s_storage inventory; struct s_storage cart; @@ -654,7 +654,6 @@ struct map_session_data { int c_marker[MAX_SKILL_CRIMSON_MARKER]; /// Store target that marked by Crimson Marker [Cydh] bool flicker; /// Check RL_FLICKER usage status [Cydh] - int storage_size; /// Holds player storage size (VIP system). #ifdef VIP_ENABLE struct vip_info vip; #endif diff --git a/src/map/script.c b/src/map/script.c index 9ba4e0eb98..8050e6d2fe 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -7382,7 +7382,7 @@ static void buildin_delitem_delete(struct map_session_data* sd, int idx, int* am pc_cart_delitem(sd,idx,delamount,0,LOG_TYPE_SCRIPT); break; case TABLE_STORAGE: - storage_delitem(sd,idx,delamount); + storage_delitem(sd,&sd->storage,idx,delamount); log_pick_pc(sd,LOG_TYPE_SCRIPT,-delamount,itm); break; case TABLE_GUILD_STORAGE: @@ -22012,7 +22012,28 @@ BUILDIN_FUNC(getguildalliance) script_pushint(st, 2); else script_pushint(st, 1); + return SCRIPT_CMD_SUCCESS; +} +/* + * openstorage2 ,{,} + * mode @see enum e_storage_mode + **/ +BUILDIN_FUNC(openstorage2) { + int stor_id = script_getnum(st, 2); + TBL_PC *sd = NULL; + + if (!script_accid2sd(4, sd)) { + script_pushint(st, 0); + return SCRIPT_CMD_FAILURE; + } + + if (!storage_exists(stor_id)) { + ShowError("buildin_openstorage2: Invalid storage_id '%d'!\n", stor_id); + return SCRIPT_CMD_FAILURE; + } + + script_pushint(st, storage_premiumStorage_load(sd, stor_id, script_getnum(st, 3))); return SCRIPT_CMD_SUCCESS; } @@ -22607,6 +22628,7 @@ struct script_function buildin_func[] = { BUILDIN_DEF(setrandomoption,"iiiii?"), BUILDIN_DEF(needed_status_point,"ii?"), BUILDIN_DEF(jobcanentermap,"s?"), + BUILDIN_DEF(openstorage2,"ii?"), // WoE TE BUILDIN_DEF(agitstart3,""), diff --git a/src/map/script_constants.h b/src/map/script_constants.h index 074a90d034..524d6daf0b 100644 --- a/src/map/script_constants.h +++ b/src/map/script_constants.h @@ -3170,6 +3170,10 @@ export_constant(CARD0_CREATE); export_constant(CARD0_PET); + export_constant(STOR_MODE_NONE); + export_constant(STOR_MODE_GET); + export_constant(STOR_MODE_PUT); + #undef export_constant #endif /* _SCRIPT_CONSTANTS_H_ */ diff --git a/src/map/skill.c b/src/map/skill.c index 2cc66b5f4f..01abe1a11b 100755 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -7319,7 +7319,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui sd->vend_skill_lv = skill_lv; ARR_FIND(0, MAX_CART, i, sd->cart.u.items_cart[i].nameid && sd->cart.u.items_cart[i].id == 0); if (i < MAX_CART) - intif_storage_save(sd, TABLE_CART); + intif_storage_save(sd, &sd->cart); else clif_openvendingreq(sd,2+skill_lv); } diff --git a/src/map/storage.c b/src/map/storage.c index 92cadc8777..5f5bc4f1eb 100644 --- a/src/map/storage.c +++ b/src/map/storage.c @@ -20,6 +20,41 @@ static DBMap* guild_storage_db; ///Databases of guild_storage : int guild_id -> struct guild_storage* +struct s_storage_table *storage_db; +int storage_count; + +/** + * Get storage name + * @param id Storage ID + * @return Storage name or "Storage" if not found + * @author [Cydh] + **/ +const char *storage_getName(uint8 id) { + if (storage_db && storage_count) { + int i; + for (i = 0; i < storage_count; i++) { + if (&storage_db[i] && storage_db[i].id == id && storage_db[i].name && storage_db[i].name[0] != '\0') + return storage_db[i].name; + } + } + return "Storage"; +} + +/** + * Check if sotrage ID is valid + * @param id Storage ID + * @return True:Valid, False:Invalid + **/ +bool storage_exists(uint8 id) { + if (storage_db && storage_count) { + int i; + for (i = 0; i < storage_count; i++) { + if (storage_db[i].id == id) + return true; + } + } + return false; +} /** * Storage item comparator (for qsort) @@ -64,6 +99,8 @@ void storage_sortitem(struct item* items, unsigned int size) void do_init_storage(void) { guild_storage_db = idb_alloc(DB_OPT_RELEASE_DATA); + storage_db = NULL; + storage_count = 0; } /** @@ -74,6 +111,10 @@ void do_init_storage(void) void do_final_storage(void) { guild_storage_db->destroy(guild_storage_db,NULL); + if (storage_db) + aFree(storage_db); + storage_db = NULL; + storage_count = 0; } /** @@ -119,9 +160,9 @@ int storage_storageopen(struct map_session_data *sd) } sd->state.storage_flag = 1; - storage_sortitem(sd->storage.u.items_storage, ARRAYLENGTH(sd->storage.u.items_storage)); - clif_storagelist(sd, sd->storage.u.items_storage, ARRAYLENGTH(sd->storage.u.items_storage)); - clif_updatestorageamount(sd, sd->storage.amount, sd->storage_size); + 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; } @@ -153,44 +194,98 @@ int compare_item(struct item *a, struct item *b) return 0; } +/** + * Check if item can be added to storage + * @param stor Storage data + * @param idx Index item from inventory/cart + * @param items List of items from inventory/cart + * @param amount Amount of item will be added + * @param max_num Max inventory/cart + * @return @see enum e_storage_add + **/ +static enum e_storage_add storage_canAddItem(struct s_storage *stor, int idx, struct item items[], int amount, int max_num) { + if (stor->amount >= stor->max_amount) + return STORAGE_ADD_NOROOM; // storage full + + if (idx < 0 || idx >= max_num) + return STORAGE_ADD_INVALID; + + if (items[idx].nameid <= 0) + return STORAGE_ADD_INVALID; // No item on that spot + + if (amount < 1 || amount > items[idx].amount) + return STORAGE_ADD_INVALID; + + if (!stor->state.put) + return STORAGE_ADD_NOACCESS; + + return STORAGE_ADD_OK; +} + +/** + * Check if item can be moved from storage + * @param stor Storage data + * @param idx Index from storage + * @param amount Number of item + * @return @see enum e_storage_add + **/ +static enum e_storage_add storage_canGetItem(struct s_storage *stor, int idx, int amount) { + // If last index check is sd->storage_size, if player isn't VIP anymore but there's item, player can't take it + // Example the storage size when not VIP anymore is 350/300, player still can take the 301st~349th item. + if( idx < 0 || idx >= ARRAYLENGTH(stor->u.items_storage) ) + return STORAGE_ADD_INVALID; + + if( stor->u.items_storage[idx].nameid <= 0 ) + return STORAGE_ADD_INVALID; //Nothing there + + if( amount < 1 || amount > stor->u.items_storage[idx].amount ) + return STORAGE_ADD_INVALID; + + if (!stor->state.get) + return STORAGE_ADD_NOACCESS; + + return STORAGE_ADD_OK; +} + /** * Make a player add an item to his storage * @param sd : player + * @param stor : Storage data * @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) +static int storage_additem(struct map_session_data* sd, struct s_storage *stor, struct item *it, int amount) { - struct s_storage* stor = &sd->storage; struct item_data *data; int i; - if( item_data->nameid == 0 || amount <= 0 ) + if( it->nameid == 0 || amount <= 0 ) return 1; - data = itemdb_search(item_data->nameid); + data = itemdb_search(it->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] + if( !itemdb_canstore(it, 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) ) { + if( (it->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->u.items_storage[i], item_data) ) { // existing items found, stack them + for( i = 0; i < stor->max_amount; i++ ) { + if( compare_item(&stor->u.items_storage[i], it) ) { // existing items found, stack them if( amount > MAX_AMOUNT - stor->u.items_storage[i].amount || ( data->stack.storage && amount > data->stack.amount - stor->u.items_storage[i].amount ) ) return 1; stor->u.items_storage[i].amount += amount; + stor->dirty = true; clif_storageitemadded(sd,&stor->u.items_storage[i],i,amount); return 0; @@ -199,16 +294,17 @@ static int storage_additem(struct map_session_data* sd, struct item* item_data, } // find free slot - ARR_FIND( 0, sd->storage_size, i, stor->u.items_storage[i].nameid == 0 ); - if( i >= sd->storage_size ) + ARR_FIND( 0, stor->max_amount, i, stor->u.items_storage[i].nameid == 0 ); + if( i >= stor->max_amount ) return 1; // add item to slot - memcpy(&stor->u.items_storage[i],item_data,sizeof(stor->u.items_storage[0])); + memcpy(&stor->u.items_storage[i],it,sizeof(stor->u.items_storage[0])); stor->amount++; stor->u.items_storage[i].amount = amount; + stor->dirty = true; clif_storageitemadded(sd,&stor->u.items_storage[i],i,amount); - clif_updatestorageamount(sd, stor->amount, sd->storage_size); + clif_updatestorageamount(sd, stor->amount, stor->max_amount); return 0; } @@ -220,22 +316,23 @@ static int storage_additem(struct map_session_data* sd, struct item* item_data, * @param amount :number of item to remove * @return 0:sucess, 1:fail */ -int storage_delitem(struct map_session_data* sd, int n, int amount) +int storage_delitem(struct map_session_data* sd, struct s_storage *stor, int index, int amount) { - if( sd->storage.u.items_storage[n].nameid == 0 || sd->storage.u.items_storage[n].amount < amount ) + if( stor->u.items_storage[index].nameid == 0 || stor->u.items_storage[index].amount < amount ) return 1; - sd->storage.u.items_storage[n].amount -= amount; + stor->u.items_storage[index].amount -= amount; + stor->dirty = true; - if( sd->storage.u.items_storage[n].amount == 0 ) { - memset(&sd->storage.u.items_storage[n],0,sizeof(sd->storage.u.items_storage[0])); - sd->storage.amount--; - if( sd->state.storage_flag == 1 ) - clif_updatestorageamount(sd, sd->storage.amount, sd->storage_size); + 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 ) - clif_storageitemremoved(sd,n,amount); + if( sd->state.storage_flag == 1 || sd->state.storage_flag == 3 ) + clif_storageitemremoved(sd,index,amount); return 0; } @@ -243,32 +340,27 @@ int storage_delitem(struct map_session_data* sd, int n, int amount) /** * Add an item to the storage from the inventory. * @param sd : player + * @param stor : Storage data * @param index : inventory index to take the item from * @param amount : number of item to take * @return 0:fail, 1:success */ -void storage_storageadd(struct map_session_data* sd, int index, int amount) +void storage_storageadd(struct map_session_data* sd, struct s_storage *stor, int index, int amount) { + enum e_storage_add result; + nullpo_retv(sd); - if( sd->storage.amount > sd->storage_size ) - return; // storage full - - if( index < 0 || index >= MAX_INVENTORY ) + result = storage_canAddItem(stor, index, sd->inventory.u.items_inventory, amount, MAX_INVENTORY); + if (result == STORAGE_ADD_INVALID) return; - - if( sd->inventory.u.items_inventory[index].nameid <= 0 ) - return; // No item on that spot - - if( amount < 1 || amount > sd->inventory.u.items_inventory[index].amount ) - return; - - if( storage_additem(sd,&sd->inventory.u.items_inventory[index],amount) == 0 ) + else if (result == STORAGE_ADD_OK && storage_additem(sd,stor,&sd->inventory.u.items_inventory[index],amount) == 0) { pc_delitem(sd,index,amount,0,4,LOG_TYPE_STORAGE); - else { - clif_storageitemremoved(sd,index,0); - clif_dropitem(sd,index,0); + return; } + + clif_storageitemremoved(sd,index,0); + clif_dropitem(sd,index,0); } /** @@ -278,21 +370,19 @@ void storage_storageadd(struct map_session_data* sd, int index, int amount) * @param amount : number of item to take * @return 0:fail, 1:success */ -void storage_storageget(struct map_session_data* sd, int index, int amount) +void storage_storageget(struct map_session_data *sd, struct s_storage *stor, int index, int amount) { unsigned char flag = 0; + enum e_storage_add result; - if( index < 0 || index >= sd->storage_size ) + nullpo_retv(sd); + + result = storage_canGetItem(stor, index, amount); + if (result != STORAGE_ADD_OK) return; - if( sd->storage.u.items_storage[index].nameid <= 0 ) - return; //Nothing there - - if( amount < 1 || amount > sd->storage.u.items_storage[index].amount ) - return; - - if( (flag = pc_additem(sd,&sd->storage.u.items_storage[index],amount,LOG_TYPE_STORAGE)) == 0 ) - storage_delitem(sd,index,amount); + if ((flag = pc_additem(sd,&stor->u.items_storage[index],amount,LOG_TYPE_STORAGE)) == ADDITEM_SUCCESS) + storage_delitem(sd,stor,index,amount); else { clif_storageitemremoved(sd,index,0); clif_additem(sd,0,0,flag); @@ -302,58 +392,49 @@ void storage_storageget(struct map_session_data* sd, int index, int amount) /** * Move an item from cart to storage. * @param sd : player + * @param stor : Storage data * @param index : cart index to take the item from * @param amount : number of item to take * @return 0:fail, 1:success */ -void storage_storageaddfromcart(struct map_session_data* sd, int index, int amount) +void storage_storageaddfromcart(struct map_session_data *sd, struct s_storage *stor, int index, int amount) { + enum e_storage_add result; nullpo_retv(sd); - if( sd->storage.amount > sd->storage_size ) - return; // storage full / storage closed - - if( index < 0 || index >= MAX_CART ) + result = storage_canAddItem(stor, index, sd->cart.u.items_inventory, amount, MAX_INVENTORY); + if (result == STORAGE_ADD_INVALID) return; - - if( sd->cart.u.items_cart[index].nameid <= 0 ) - return; //No item there. - - if( amount < 1 || amount > sd->cart.u.items_cart[index].amount ) - return; - - if( storage_additem(sd,&sd->cart.u.items_cart[index],amount) == 0 ) + else if (result == STORAGE_ADD_OK && storage_additem(sd,stor,&sd->cart.u.items_cart[index],amount) == 0) { pc_cart_delitem(sd,index,amount,0,LOG_TYPE_STORAGE); - else { - clif_storageitemremoved(sd,index,0); - clif_dropitem(sd,index,0); + return; } + + clif_storageitemremoved(sd,index,0); + clif_dropitem(sd,index,0); } /** * Get from Storage to the Cart inventory * @param sd : player + * @param stor : Storage data * @param index : storage index to take the item from * @param amount : number of item to take * @return 0:fail, 1:success */ -void storage_storagegettocart(struct map_session_data* sd, int index, int amount) +void storage_storagegettocart(struct map_session_data* sd, struct s_storage *stor, int index, int amount) { - unsigned char flag; + unsigned char flag = 0; + enum e_storage_add result; nullpo_retv(sd); - if( index < 0 || index >= sd->storage_size ) + result = storage_canGetItem(stor, index, amount); + if (result != STORAGE_ADD_OK) return; - if( sd->storage.u.items_storage[index].nameid <= 0 ) - return; //Nothing there. - - if( amount < 1 || amount > sd->storage.u.items_storage[index].amount ) - return; - - if( (flag = pc_cart_additem(sd,&sd->storage.u.items_storage[index],amount,LOG_TYPE_STORAGE)) == 0 ) - storage_delitem(sd,index,amount); + if ((flag = pc_cart_additem(sd,&stor->u.items_storage[index],amount,LOG_TYPE_STORAGE)) == 0) + storage_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); @@ -487,7 +568,7 @@ char storage_guild_storageopen(struct map_session_data* sd) gstor->status = true; sd->state.storage_flag = 2; storage_sortitem(gstor->u.items_guild, ARRAYLENGTH(gstor->u.items_guild)); - clif_storagelist(sd, gstor->u.items_guild, ARRAYLENGTH(gstor->u.items_guild)); + clif_storagelist(sd, gstor->u.items_guild, ARRAYLENGTH(gstor->u.items_guild), "Guild Storage"); clif_updatestorageamount(sd, gstor->amount, MAX_GUILD_STORAGE); return 0; @@ -871,3 +952,121 @@ void storage_guild_storage_quit(struct map_session_data* sd, int flag) sd->state.storage_flag = 0; stor->status = false; } + +/** + * 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); +} + +/** + * Request to open premium storage + * @param sd Player who request + * @param num Storage number + * @param mode Storage mode @see enum e_storage_mode + * @return 1:Success to request, 0:Failed + * @author [Cydh] + **/ +bool storage_premiumStorage_load(struct map_session_data *sd, uint8 num, uint8 mode) { + nullpo_ret(sd); + + if (sd->state.storage_flag) + return 0; + + if (sd->state.vending || sd->state.buyingstore || sd->state.prevend || sd->state.autotrade) + return 0; + + if (sd->state.banking || sd->state.callshop) + return 0; + + 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 0; + } + + if (!&sd->premiumStorage || sd->premiumStorage.stor_id != num) + return intif_storage_request(sd, TABLE_STORAGE, num, mode); + else { + sd->premiumStorage.state.put = (mode&STOR_MODE_PUT) ? 1 : 0; + sd->premiumStorage.state.get = (mode&STOR_MODE_GET) ? 1 : 0; + storage_premiumStorage_open(sd); + } + return 1; +} + +/** + * Request to save premium storage + * @param sd Player who has the storage + * @author [Cydh] + **/ +void storage_premiumStorage_save(struct map_session_data *sd) { + nullpo_retv(sd); + + if (!&sd->premiumStorage) + return; + + intif_storage_save(sd, &sd->premiumStorage); +} + +/** + * Ack of secondary premium has been saved + * @param sd Player who has the storage + **/ +void storage_premiumStorage_saved(struct map_session_data *sd) { + if (!sd) + return; + + if (&sd->premiumStorage) { + sd->premiumStorage.dirty = 0; + } + if (sd->state.storage_flag == 3) { + sd->state.storage_flag = 0; + clif_storageclose(sd); + } +} + +/** + * Request to close premium storage + * @param sd Player who has the storage + * @author [Cydh] + **/ +void storage_premiumStorage_close(struct map_session_data *sd) { + nullpo_retv(sd); + + if (!&sd->premiumStorage) + return; + + if (sd->premiumStorage.dirty) { + intif_storage_save(sd, &sd->premiumStorage); + if (sd->state.storage_flag == 3) { + sd->state.storage_flag = 0; + clif_storageclose(sd); + } + } + else + storage_premiumStorage_saved(sd); +} + +/** + * Force save then close the premium storage + * @param sd Player who has the storage + * @author [Cydh] + **/ +void storage_premiumStorage_quit(struct map_session_data *sd) { + nullpo_retv(sd); + + if (!&sd->premiumStorage) + return; + + intif_storage_save(sd, &sd->premiumStorage); +} diff --git a/src/map/storage.h b/src/map/storage.h index 6ef94f5259..165d441184 100644 --- a/src/map/storage.h +++ b/src/map/storage.h @@ -10,12 +10,25 @@ struct item; //#include "map.h" struct map_session_data; -int storage_delitem(struct map_session_data* sd, int n, int amount); +extern struct s_storage_table *storage_db; +extern int storage_count; + +enum e_storage_add { + STORAGE_ADD_OK, + STORAGE_ADD_NOROOM, + STORAGE_ADD_NOACCESS, + STORAGE_ADD_INVALID, +}; + +const char *storage_getName(uint8 id); +bool storage_exists(uint8 id); + +int storage_delitem(struct map_session_data* sd, struct s_storage *stor, int index, int amount); int storage_storageopen(struct map_session_data *sd); -void storage_storageadd(struct map_session_data *sd,int index,int amount); -void storage_storageget(struct map_session_data *sd,int index,int amount); -void storage_storageaddfromcart(struct map_session_data *sd,int index,int amount); -void storage_storagegettocart(struct map_session_data *sd,int index,int amount); +void storage_storageadd(struct map_session_data *sd, struct s_storage *stor, int index, int amount); +void storage_storageget(struct map_session_data *sd, struct s_storage *stor, int index, int amount); +void storage_storageaddfromcart(struct map_session_data *sd, struct s_storage *stor, int index, int amount); +void storage_storagegettocart(struct map_session_data *sd, struct s_storage *stor, int index, int amount); void storage_storageclose(struct map_session_data *sd); void storage_sortitem(struct item* items, unsigned int size); void do_init_storage(void); @@ -39,6 +52,14 @@ void storage_guild_storage_quit(struct map_session_data *sd,int flag); bool storage_guild_storagesave(uint32 account_id, int guild_id, int flag); void storage_guild_storagesaved(int guild_id); //Ack from char server that guild store was saved. +// Premium Storage [Cydh] +void storage_premiumStorage_open(struct map_session_data *sd); +bool storage_premiumStorage_load(struct map_session_data *sd, uint8 num, uint8 mode); +void storage_premiumStorage_save(struct map_session_data *sd); +void storage_premiumStorage_saved(struct map_session_data *sd); +void storage_premiumStorage_close(struct map_session_data *sd); +void storage_premiumStorage_quit(struct map_session_data *sd); + int compare_item(struct item *a, struct item *b); #endif /* _STORAGE_H_ */ diff --git a/src/map/unit.c b/src/map/unit.c index e73bf89f7a..966d2d64aa 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -2912,6 +2912,8 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, storage_storage_quit(sd,0); else if (sd->state.storage_flag == 2) storage_guild_storage_quit(sd, 0); + else if (sd->state.storage_flag == 3) + storage_premiumStorage_quit(sd); sd->state.storage_flag = 0; //Force close it when being warped. } diff --git a/vcproj-10/map-server.vcxproj b/vcproj-10/map-server.vcxproj index 641c198152..5006fcc76d 100644 --- a/vcproj-10/map-server.vcxproj +++ b/vcproj-10/map-server.vcxproj @@ -282,6 +282,7 @@ + diff --git a/vcproj-12/map-server.vcxproj b/vcproj-12/map-server.vcxproj index 9860aeb46a..a57fb8c1c6 100644 --- a/vcproj-12/map-server.vcxproj +++ b/vcproj-12/map-server.vcxproj @@ -286,6 +286,7 @@ + diff --git a/vcproj-13/map-server.vcxproj b/vcproj-13/map-server.vcxproj index 55b9440719..eaf55d1d87 100644 --- a/vcproj-13/map-server.vcxproj +++ b/vcproj-13/map-server.vcxproj @@ -286,6 +286,7 @@ + diff --git a/vcproj-14/map-server.vcxproj b/vcproj-14/map-server.vcxproj index 9fd854c7e0..b220a090fb 100644 --- a/vcproj-14/map-server.vcxproj +++ b/vcproj-14/map-server.vcxproj @@ -284,6 +284,7 @@ + From b831287b0e4f8be50e7376820e73392b72b814c7 Mon Sep 17 00:00:00 2001 From: aleos89 Date: Fri, 14 Oct 2016 10:09:26 -0400 Subject: [PATCH 18/22] Small documentation cleanups * Cleaned up the inter_server.conf documentation. * Cleaned up the script command openstorage2 documentation. --- conf/inter_server.conf | 19 ++++++++++--------- doc/script_commands.txt | 10 +++++----- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/conf/inter_server.conf b/conf/inter_server.conf index 448b14d05f..3f0bc2f852 100644 --- a/conf/inter_server.conf +++ b/conf/inter_server.conf @@ -1,22 +1,23 @@ /** - * Config for storages + * Config for Storages * - * To access premium storage, use 'openstorage2' script command (except for the default storage). - * If premium storages are added, just copy the structure of storage table then match the table name in this config. + * To access the premium storage, use script command 'openstorage2'. + * If premium storages are added, copy the structure of the storage table and match the table name in this config. * The 'max' of premium storages are not adjusted by 'vip_storage_increase' config nor MIN_STORAGE. * * Structure: { - id: // (int) Storage ID will be used for 'openstorage2' script command. - name: "" // (string) Storage name will be sent to the client when player open the storage. - table: "" // (string) Name of table where storage is saved, the table stucture is same like default storage name - max: // (int) *optional* Maximum number of storage, MAX_STORAGE will be used if no value defined + id: // (int) Storage ID will be used for script command 'openstorage2'. + name: "" // (string) Storage name will be sent to the client to display on the title bar. + table: "" // (string) Name of table where storage is saved. The table stucture is the same as the default storage table. + max: // (int) *optional* Maximum number of items in storage. MAX_STORAGE will be used if no value is defined. }, // Use comma to add more storages **/ + storages: ( { - // Default storage - // DO NOT CHANGE THIS EXCEPT YOU KNOW WHAT YOU ARE DOING + // Default Storage + // DO NOT CHANGE THIS UNLESS YOU KNOW WHAT YOU ARE DOING id: 0 name: "Storage" table: "storage" diff --git a/doc/script_commands.txt b/doc/script_commands.txt index b75e802804..c3c10f4314 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -5055,14 +5055,14 @@ window, to avoid any disruption when both windows overlap. *openstorage2 ,{,}; -Just like 'openstorage' command, except this command can open additional storage -by specified 'storage_id'. For storage_id, please read the conf/inter_server.conf -for storages groups. +Just like the 'openstorage' command, except this command can open additional storages +by the specified . For , please read the conf/inter_server.conf +for storage groups. -Values for 'mode' are: +Values for are: STOR_MODE_NONE : Player only can read the storage entries. STOR_MODE_GET : Player can get items from the storage. - STOR_MODE_PUT : Player can put items to the storage. + STOR_MODE_PUT : Player can put items in the storage. Example: if (vip_status(1)) { From aa0b7cd7baafb334fe330e07c45f97732fb478ba Mon Sep 17 00:00:00 2001 From: Cydh Ramdh Date: Fri, 4 Nov 2016 07:27:26 +0700 Subject: [PATCH 19/22] Removed duplicate check for storage size Signed-off-by: Cydh Ramdh --- src/map/chrif.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/map/chrif.c b/src/map/chrif.c index 1563fdbc78..78846a0ab3 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -2000,9 +2000,8 @@ void do_init_chrif(void) { exit(EXIT_FAILURE); } - if (sizeof(struct s_storage) > 0xFFFF){ - ShowError("s_storage size = %d is too big to be transmitted. (must be below 0xFFFF) \n", - sizeof(struct s_storage)); + if (sizeof(struct s_storage) > 0xFFFF) { + ShowError("s_storage size = %d is too big to be transmitted. (must be below 0xFFFF)\n", sizeof(struct s_storage)); exit(EXIT_FAILURE); } @@ -2012,11 +2011,6 @@ void do_init_chrif(void) { exit(EXIT_FAILURE); } - if(sizeof(struct s_storage) > 0xFFFF) { - ShowError("s_storage size = %d is too big to be transmitted. (must be below 0xFFFF)\n", sizeof(struct s_storage)); - exit(EXIT_FAILURE); - } - auth_db = idb_alloc(DB_OPT_BASE); auth_db_ers = ers_new(sizeof(struct auth_node),"chrif.c::auth_db_ers",ERS_OPT_NONE); From 56512ce116ab646a78b48aa1c994c908ca7ddc43 Mon Sep 17 00:00:00 2001 From: aleos89 Date: Fri, 11 Nov 2016 14:26:32 -0500 Subject: [PATCH 20/22] Corrected vending order of similar item IDs * Resolves an issue where if a similar item ID is vended more than once (non-stackable) the order of the vended items becomes incorrect when one is purchased. Thanks to @Tokeiburu! --- src/char/char.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/char/char.c b/src/char/char.c index 9904e92f87..f8f8ef6418 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -618,6 +618,7 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, enum sto && items[i].card[0] == item.card[0] && items[i].card[2] == item.card[2] && items[i].card[3] == item.card[3] + && items[i].unique_id == item.unique_id ) { //They are the same item. int k; @@ -633,7 +634,6 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, enum sto items[i].attribute == item.attribute && items[i].expire_time == item.expire_time && items[i].bound == item.bound && - items[i].unique_id == item.unique_id && (tableswitch != TABLE_INVENTORY || items[i].favorite == item.favorite) ) ; //Do nothing. else From c00c7346d215a7845d61b81636f91823f1096f92 Mon Sep 17 00:00:00 2001 From: aleos89 Date: Fri, 11 Nov 2016 15:35:38 -0500 Subject: [PATCH 21/22] Resolved some compile errors * Follow up to 9c552ca and 5aa53e4. --- src/map/clif.c | 2 +- src/map/intif.c | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/map/clif.c b/src/map/clif.c index 12867f87ec..80529cd1c7 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -2896,7 +2896,7 @@ void clif_storagelist(struct map_session_data* sd, struct item* items, int items WFIFOW(sd->fd,0)=cmde; WFIFOW(sd->fd,2)=sidxe+nn*se; #if PACKETVER >= 20120925 - safestrncpy(WFIFOP(sd->fd,4), storename, NAME_LENGTH); //storename + safestrncpy(WFIFOCP(sd->fd,4), storename, NAME_LENGTH); //storename #endif memcpy(WFIFOP(sd->fd,sidxe),bufe + sidxe + i*se,nn*se); WFIFOSET(sd->fd,WFIFOW(sd->fd,2)); diff --git a/src/map/intif.c b/src/map/intif.c index fb4cc14522..48ad3b0e94 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -3294,9 +3294,10 @@ void intif_parse_StorageInfo_recv(int fd) { storage_db = NULL; for (i = 0; i < count; i++) { - char name[NAME_LENGTH+1]; - safestrncpy(name, (char *)RFIFOP(fd, 5 + size * i), NAME_LENGTH); - if (!name || name[0] == '\0') + char name[NAME_LENGTH + 1]; + + safestrncpy(name, RFIFOCP(fd, 5 + size * i), NAME_LENGTH); + if (name[0] == '\0') continue; RECREATE(storage_db, struct s_storage_table, storage_count+1); memcpy(&storage_db[storage_count], RFIFOP(fd, 4 + size * i), size); From 8028789dee25e0f98e0be2aee37f401a323376e0 Mon Sep 17 00:00:00 2001 From: aleos89 Date: Mon, 14 Nov 2016 09:38:59 -0500 Subject: [PATCH 22/22] Removed unused functions * Removed inter_storage_delete and inter_guild_storage_delete functions as they are not used. --- src/char/int_storage.c | 13 ------------- src/char/int_storage.h | 2 -- 2 files changed, 15 deletions(-) diff --git a/src/char/int_storage.c b/src/char/int_storage.c index 91fe118715..df6e825736 100644 --- a/src/char/int_storage.c +++ b/src/char/int_storage.c @@ -184,19 +184,6 @@ void inter_storage_sql_final(void) return; } -// Delete char storage -void inter_storage_delete(uint32 account_id) -{ - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id`='%d'", schema_config.storage_db, account_id) ) - Sql_ShowDebug(sql_handle); -} - -void inter_guild_storage_delete(int guild_id) -{ - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id`='%d'", schema_config.guild_storage_db, guild_id) ) - Sql_ShowDebug(sql_handle); -} - //--------------------------------------------------------- // packet from map server diff --git a/src/char/int_storage.h b/src/char/int_storage.h index 80c88ff34e..9418a13038 100644 --- a/src/char/int_storage.h +++ b/src/char/int_storage.h @@ -8,8 +8,6 @@ struct s_storage; void inter_storage_sql_init(void); void inter_storage_sql_final(void); -void inter_storage_delete(uint32 account_id); -void inter_guild_storage_delete(int guild_id); bool inter_premiumStorage_exists(uint8 id); int inter_premiumStorage_getMax(uint8 id);