From 974222a8d3f189083205bf5d330de04a43226ad3 Mon Sep 17 00:00:00 2001 From: Smokexyz Date: Thu, 2 Mar 2017 19:24:48 +0800 Subject: Implementation of Item Options System. Allows the infusing of equipments with bonus item options. This feature is constrained to clients of packet versions greater than or equal to `20150226`. Item Options and their effects are defined server-side in `db/item_options.conf` and client side in `data/luafiles514/lua files/datainfo/addrandomoptionnametable.lub` The ID of the option must tally with the correct index of the description provided in the client side lua file to avoid bugs. IT_OPT_* keys and MAX_ITEM_OPTIONS macro are also exported from the source as constants. An additional flag `disable_options` has been added to sql, and as `DisableOptions: true/false (boolean, defaults to false !!for equipments only!!)` to item_db.conf files. Script commands documentation is also included. SQL file updates are included. Credits: [Smokexyz](https://github.com/Smokexyz) Style and Script Fixes by [Asheraf](https://github.com/Asheraf) Initial design Idea by [secretdataz](https://github.com/secretdataz) --- src/char/int_storage.c | 71 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 20 deletions(-) (limited to 'src/char/int_storage.c') diff --git a/src/char/int_storage.c b/src/char/int_storage.c index 8e3ebdff3..b78ad9f0e 100644 --- a/src/char/int_storage.c +++ b/src/char/int_storage.c @@ -63,8 +63,10 @@ int inter_storage_fromsql(int account_id, struct storage_data* p) // storage {`account_id`/`id`/`nameid`/`amount`/`equip`/`identify`/`refine`/`attribute`/`card0`/`card1`/`card2`/`card3`} StrBuf->Init(&buf); StrBuf->AppendStr(&buf, "SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`expire_time`,`bound`,`unique_id`"); - for( j = 0; j < MAX_SLOTS; ++j ) + for (j = 0; j < MAX_SLOTS; ++j) StrBuf->Printf(&buf, ",`card%d`", j); + for (j = 0; j < MAX_ITEM_OPTIONS; ++j) + StrBuf->Printf(&buf, ",`opt_idx%d`,`opt_val%d`", j, j); StrBuf->Printf(&buf, " FROM `%s` WHERE `account_id`='%d' ORDER BY `nameid`", storage_db, account_id); if (SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf))) @@ -84,9 +86,17 @@ int inter_storage_fromsql(int account_id, struct storage_data* p) SQL->GetData(inter->sql_handle, 7, &data, NULL); item->expire_time = (unsigned int)atoi(data); SQL->GetData(inter->sql_handle, 8, &data, NULL); item->bound = atoi(data); SQL->GetData(inter->sql_handle, 9, &data, NULL); item->unique_id = strtoull(data, NULL, 10); - for( j = 0; j < MAX_SLOTS; ++j ) - { - SQL->GetData(inter->sql_handle, 10+j, &data, NULL); item->card[j] = atoi(data); + /* Card Slots */ + for (j = 0; j < MAX_SLOTS; ++j) { + SQL->GetData(inter->sql_handle, 10 + j, &data, NULL); + item->card[j] = atoi(data); + } + /* Item Options */ + for (j = 0; j < MAX_ITEM_OPTIONS; ++j) { + SQL->GetData(inter->sql_handle, 10 + MAX_SLOTS + j * 2, &data, NULL); + item->option[j].index = atoi(data); + SQL->GetData(inter->sql_handle, 11 + MAX_SLOTS + j * 2, &data, NULL); + item->option[j].value = atoi(data); } } p->storage_amount = i; @@ -121,8 +131,10 @@ int inter_storage_guild_storage_fromsql(int guild_id, struct guild_storage* p) // storage {`guild_id`/`id`/`nameid`/`amount`/`equip`/`identify`/`refine`/`attribute`/`card0`/`card1`/`card2`/`card3`} StrBuf->Init(&buf); StrBuf->AppendStr(&buf, "SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`bound`,`unique_id`"); - for( j = 0; j < MAX_SLOTS; ++j ) + for (j = 0; j < MAX_SLOTS; ++j) StrBuf->Printf(&buf, ",`card%d`", j); + for (j = 0; j < MAX_ITEM_OPTIONS; ++j) + StrBuf->Printf(&buf, ", `opt_idx%d`, `opt_val%d`", j, j); StrBuf->Printf(&buf, " FROM `%s` WHERE `guild_id`='%d' ORDER BY `nameid`", guild_storage_db, guild_id); if( SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf))) @@ -142,9 +154,17 @@ int inter_storage_guild_storage_fromsql(int guild_id, struct guild_storage* p) SQL->GetData(inter->sql_handle, 7, &data, NULL); item->bound = atoi(data); SQL->GetData(inter->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(inter->sql_handle, 9+j, &data, NULL); item->card[j] = atoi(data); + /* Card Slots */ + for (j = 0; j < MAX_SLOTS; ++j) { + SQL->GetData(inter->sql_handle, 9 + j, &data, NULL); + item->card[j] = atoi(data); + } + /* Item Options */ + for (j = 0; j < MAX_ITEM_OPTIONS; ++j) { + SQL->GetData(inter->sql_handle, 9 + MAX_SLOTS + j * 2, &data, NULL); + item->option[j].index = atoi(data); + SQL->GetData(inter->sql_handle, 10 + MAX_SLOTS + j * 2, &data, NULL); + item->option[j].value = atoi(data); } } p->storage_amount = i; @@ -288,8 +308,10 @@ int mapif_parse_ItemBoundRetrieve_sub(int fd) StrBuf->Init(&buf); StrBuf->AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`"); - for( j = 0; j < MAX_SLOTS; ++j ) + for (j = 0; j < MAX_SLOTS; ++j) StrBuf->Printf(&buf, ", `card%d`", j); + for (j = 0; j < MAX_ITEM_OPTIONS; ++j) + StrBuf->Printf(&buf, ", `opt_idx%d`, `opt_val%d`", j, j); StrBuf->Printf(&buf, " FROM `%s` WHERE `char_id`='%d' AND `bound` = '%d'",inventory_db,char_id,IBT_GUILD); stmt = SQL->StmtMalloc(inter->sql_handle); @@ -313,17 +335,22 @@ int mapif_parse_ItemBoundRetrieve_sub(int fd) SQL->StmtBindColumn(stmt, 7, SQLDT_UINT, &item.expire_time, 0, NULL, NULL); SQL->StmtBindColumn(stmt, 8, SQLDT_UCHAR, &item.bound, 0, NULL, NULL); SQL->StmtBindColumn(stmt, 9, SQLDT_UINT64, &item.unique_id, 0, NULL, NULL); - for( j = 0; j < MAX_SLOTS; ++j ) - SQL->StmtBindColumn(stmt, 10+j, SQLDT_SHORT, &item.card[j], 0, NULL, NULL); - - while( SQL_SUCCESS == SQL->StmtNextRow(stmt)) { + /* Card Slots */ + for (j = 0; j < MAX_SLOTS; ++j) + SQL->StmtBindColumn(stmt, 10 + j, SQLDT_SHORT, &item.card[j], 0, NULL, NULL); + /* Item Options */ + for (j = 0; j < MAX_ITEM_OPTIONS; ++j) { + SQL->StmtBindColumn(stmt, 10 + MAX_SLOTS + j * 2, SQLDT_INT16, &item.option[j].index, 0, NULL, NULL); + SQL->StmtBindColumn(stmt, 11 + MAX_SLOTS + j * 2, SQLDT_INT16, &item.option[j].value, 0, NULL, NULL); + } + while (SQL_SUCCESS == SQL->StmtNextRow(stmt)) { Assert_retb(i < MAX_INVENTORY); memcpy(&items[i],&item,sizeof(struct item)); i++; } SQL->FreeResult(inter->sql_handle); - if(!i) { //No items found - No need to continue + if (i == 0) { //No items found - No need to continue StrBuf->Destroy(&buf); SQL->StmtFree(stmt); return 0; @@ -408,24 +435,28 @@ int mapif_parse_ItemBoundRetrieve_sub(int fd) StrBuf->Printf(&buf,"INSERT INTO `%s` (`guild_id`,`nameid`,`amount`,`equip`,`identify`,`refine`," "`attribute`,`expire_time`,`bound`,`unique_id`", guild_storage_db); - for( s = 0; s < MAX_SLOTS; ++s ) + for (s = 0; s < MAX_SLOTS; ++s) StrBuf->Printf(&buf, ", `card%d`", s); + for (s = 0; s < MAX_ITEM_OPTIONS; ++s) + StrBuf->Printf(&buf, ", `opt_idx%d`, `opt_val%d`", s, s); StrBuf->AppendStr(&buf," ) VALUES "); - for( j = 0; j < i; ++j ) { - if( j ) + for (j = 0; j < i; ++j) { + if (j != 0) StrBuf->AppendStr(&buf, ","); StrBuf->Printf(&buf, "('%d', '%d', '%d', '%u', '%d', '%d', '%d', '%u', '%d', '%"PRIu64"'", guild_id, items[j].nameid, items[j].amount, items[j].equip, items[j].identify, items[j].refine, items[j].attribute, items[j].expire_time, items[j].bound, items[j].unique_id); - for( s = 0; s < MAX_SLOTS; ++s ) + for (s = 0; s < MAX_SLOTS; ++s) StrBuf->Printf(&buf, ", '%d'", items[j].card[s]); + for (s = 0; s < MAX_ITEM_OPTIONS; ++s) + StrBuf->Printf(&buf, ", '%d', '%d'", items[j].option[s].index, items[j].option[s].value); StrBuf->AppendStr(&buf, ")"); } - if( SQL_ERROR == SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf)) - || SQL_ERROR == SQL->StmtExecute(stmt) ) + if (SQL_ERROR == SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf)) + || SQL_ERROR == SQL->StmtExecute(stmt)) { Sql_ShowDebug(inter->sql_handle); SQL->StmtFree(stmt); -- cgit v1.2.3-60-g2f50