summaryrefslogtreecommitdiff
path: root/src/char
diff options
context:
space:
mode:
authorSmokexyz <sagunkho@hotmail.com>2017-03-02 19:24:48 +0800
committerSmokexyz <sagunkho@hotmail.com>2017-04-04 13:38:16 +0800
commit974222a8d3f189083205bf5d330de04a43226ad3 (patch)
treeb78280b9dad90616196ee37c3992c3e46962b906 /src/char
parent20145c61053479b9acd8ed50c75a80c2a861e349 (diff)
downloadhercules-974222a8d3f189083205bf5d330de04a43226ad3.tar.gz
hercules-974222a8d3f189083205bf5d330de04a43226ad3.tar.bz2
hercules-974222a8d3f189083205bf5d330de04a43226ad3.tar.xz
hercules-974222a8d3f189083205bf5d330de04a43226ad3.zip
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)
Diffstat (limited to 'src/char')
-rw-r--r--src/char/char.c51
-rw-r--r--src/char/int_auction.c42
-rw-r--r--src/char/int_mail.c43
-rw-r--r--src/char/int_storage.c71
4 files changed, 153 insertions, 54 deletions
diff --git a/src/char/char.c b/src/char/char.c
index 9314e8c81..4395ee9c2 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -745,6 +745,9 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl
StrBuf->AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`");
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);
+
if (has_favorite)
StrBuf->AppendStr(&buf, ", `favorite`");
StrBuf->Printf(&buf, " FROM `%s` WHERE `%s`='%d'", tablename, selectoption, id);
@@ -769,9 +772,13 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl
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);
+ SQL->StmtBindColumn(stmt, 10 + j, SQLDT_SHORT, &item.card[j], 0, NULL, NULL);
+ 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);
+ }
if (has_favorite)
- SQL->StmtBindColumn(stmt, 10+MAX_SLOTS, SQLDT_UCHAR, &item.favorite, 0, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 10 + MAX_SLOTS + MAX_ITEM_OPTIONS * 2, SQLDT_UCHAR, &item.favorite, 0, NULL, NULL);
// bit array indicating which inventory items have already been matched
flag = aCalloc(max, sizeof(bool));
@@ -790,9 +797,12 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl
&& items[i].card[2] == item.card[2]
&& items[i].card[3] == item.card[3]
) {
+ int k = 0;
// They are the same item.
ARR_FIND(0, MAX_SLOTS, j, items[i].card[j] != item.card[j]);
- if (j == MAX_SLOTS
+ ARR_FIND(0, MAX_ITEM_OPTIONS, k, items[i].option[k].index != item.option[k].index || items[i].option[k].value != item.option[k].value);
+
+ if (j == MAX_SLOTS && k == MAX_ITEM_OPTIONS
&& items[i].amount == item.amount
&& items[i].equip == item.equip
&& items[i].identify == item.identify
@@ -810,6 +820,8 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl
tablename, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time, items[i].bound);
for (j = 0; j < MAX_SLOTS; ++j)
StrBuf->Printf(&buf, ", `card%d`='%d'", j, items[i].card[j]);
+ for (j = 0; j < MAX_ITEM_OPTIONS; ++j)
+ StrBuf->Printf(&buf, ", `opt_idx%d`='%d', `opt_val%d`='%d'", j, items[i].option[j].index, j, items[i].option[j].value);
if (has_favorite)
StrBuf->Printf(&buf, ", `favorite`='%d'", items[i].favorite);
StrBuf->Printf(&buf, " WHERE `id`='%d' LIMIT 1", item.id);
@@ -838,6 +850,8 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl
StrBuf->Printf(&buf, "INSERT INTO `%s`(`%s`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`", tablename, selectoption);
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);
if (has_favorite)
StrBuf->AppendStr(&buf, ", `favorite`");
StrBuf->AppendStr(&buf, ") VALUES ");
@@ -858,6 +872,8 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl
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);
for (j = 0; j < MAX_SLOTS; ++j)
StrBuf->Printf(&buf, ", '%d'", items[i].card[j]);
+ for (j = 0; j < MAX_ITEM_OPTIONS; ++j)
+ StrBuf->Printf(&buf, ", '%d', '%d'", items[i].option[j].index, items[i].option[j].value);
if (has_favorite)
StrBuf->Printf(&buf, ", '%d'", items[i].favorite);
StrBuf->AppendStr(&buf, ")");
@@ -1188,8 +1204,10 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every
//`inventory` (`id`,`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`, `expire_time`, `favorite`, `bound`, `unique_id`)
StrBuf->Init(&buf);
StrBuf->AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `bound`, `unique_id`");
- for( i = 0; i < MAX_SLOTS; ++i )
+ for (i = 0; i < MAX_SLOTS; ++i)
StrBuf->Printf(&buf, ", `card%d`", i);
+ for (i = 0; i < MAX_ITEM_OPTIONS; ++i)
+ StrBuf->Printf(&buf, ", `opt_idx%d`, `opt_val%d`", i, i);
StrBuf->Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", inventory_db, MAX_INVENTORY);
memset(&tmp_item, 0, sizeof(tmp_item));
@@ -1209,8 +1227,14 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 10, SQLDT_UINT64, &tmp_item.unique_id, 0, NULL, NULL)
)
SqlStmt_ShowDebug(stmt);
- for( i = 0; i < MAX_SLOTS; ++i )
- if( SQL_ERROR == SQL->StmtBindColumn(stmt, 11+i, SQLDT_SHORT, &tmp_item.card[i], 0, NULL, NULL) )
+ /* Card Slots */
+ for (i = 0; i < MAX_SLOTS; ++i)
+ if (SQL_ERROR == SQL->StmtBindColumn(stmt, 11 + i, SQLDT_SHORT, &tmp_item.card[i], 0, NULL, NULL))
+ SqlStmt_ShowDebug(stmt);
+ /* Item Options */
+ for (i = 0; i < MAX_ITEM_OPTIONS; i++)
+ if (SQL_ERROR == SQL->StmtBindColumn(stmt, 11 + MAX_SLOTS + i * 2, SQLDT_INT16, &tmp_item.option[i].index, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 12 + MAX_SLOTS + i * 2, SQLDT_INT16, &tmp_item.option[i].value, 0, NULL, NULL))
SqlStmt_ShowDebug(stmt);
for( i = 0; i < MAX_INVENTORY && SQL_SUCCESS == SQL->StmtNextRow(stmt); ++i )
@@ -1222,8 +1246,10 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every
//`cart_inventory` (`id`,`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`, expire_time`, `bound`, `unique_id`)
StrBuf->Clear(&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`=? LIMIT %d", cart_db, MAX_CART);
memset(&tmp_item, 0, sizeof(tmp_item));
@@ -1243,12 +1269,19 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every
) {
SqlStmt_ShowDebug(stmt);
}
- for( i = 0; i < MAX_SLOTS; ++i )
- if( SQL_ERROR == SQL->StmtBindColumn(stmt, 10+i, SQLDT_SHORT, &tmp_item.card[i], 0, NULL, NULL) )
+ /* Card Slots */
+ for (i = 0; i < MAX_SLOTS; ++i)
+ if( SQL_ERROR == SQL->StmtBindColumn(stmt, 10 + i, SQLDT_SHORT, &tmp_item.card[i], 0, NULL, NULL) )
+ SqlStmt_ShowDebug(stmt);
+ /* Item Options */
+ for (i = 0; i < MAX_ITEM_OPTIONS; ++i)
+ if (SQL_ERROR == SQL->StmtBindColumn(stmt, 10 + MAX_SLOTS + i * 2, SQLDT_INT16, &tmp_item.option[i].index, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 11 + MAX_SLOTS + i * 2, SQLDT_INT16, &tmp_item.option[i].value, 0, NULL, NULL))
SqlStmt_ShowDebug(stmt);
for( i = 0; i < MAX_CART && SQL_SUCCESS == SQL->StmtNextRow(stmt); ++i )
memcpy(&p->cart[i], &tmp_item, sizeof(tmp_item));
+
strcat(t_msg, " cart");
//read storage
diff --git a/src/char/int_auction.c b/src/char/int_auction.c
index bf690327c..2dd65f213 100644
--- a/src/char/int_auction.c
+++ b/src/char/int_auction.c
@@ -71,8 +71,10 @@ void inter_auction_save(struct auction_data *auction)
StrBuf->Init(&buf);
StrBuf->Printf(&buf, "UPDATE `%s` SET `seller_id` = '%d', `seller_name` = ?, `buyer_id` = '%d', `buyer_name` = ?, `price` = '%d', `buynow` = '%d', `hours` = '%d', `timestamp` = '%lu', `nameid` = '%d', `item_name` = ?, `type` = '%d', `refine` = '%d', `attribute` = '%d'",
auction_db, auction->seller_id, auction->buyer_id, auction->price, auction->buynow, auction->hours, (unsigned long)auction->timestamp, auction->item.nameid, auction->type, auction->item.refine, auction->item.attribute);
- for( j = 0; j < MAX_SLOTS; j++ )
+ for (j = 0; j < MAX_SLOTS; j++)
StrBuf->Printf(&buf, ", `card%d` = '%d'", j, auction->item.card[j]);
+ for (j = 0; j < MAX_ITEM_OPTIONS; j++)
+ StrBuf->Printf(&buf, ", `opt_idx%d` = '%d', `opt_val%d` = '%d'", j, auction->item.option[j].index, j, auction->item.option[j].value);
StrBuf->Printf(&buf, " WHERE `auction_id` = '%u'", auction->auction_id);
stmt = SQL->StmtMalloc(inter->sql_handle);
@@ -95,33 +97,35 @@ unsigned int inter_auction_create(struct auction_data *auction)
StringBuf buf;
struct SqlStmt *stmt;
- if( !auction )
- return false;
+ nullpo_ret(auction);
auction->timestamp = time(NULL) + (auction->hours * 3600);
StrBuf->Init(&buf);
StrBuf->Printf(&buf, "INSERT INTO `%s` (`seller_id`,`seller_name`,`buyer_id`,`buyer_name`,`price`,`buynow`,`hours`,`timestamp`,`nameid`,`item_name`,`type`,`refine`,`attribute`,`unique_id`", auction_db);
- 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, ") VALUES ('%d',?,'%d',?,'%d','%d','%d','%lu','%d',?,'%d','%d','%d','%"PRIu64"'",
auction->seller_id, auction->buyer_id, auction->price, auction->buynow, auction->hours, (unsigned long)auction->timestamp, auction->item.nameid, auction->type, auction->item.refine, auction->item.attribute, auction->item.unique_id);
- for( j = 0; j < MAX_SLOTS; j++ )
+ for (j = 0; j < MAX_SLOTS; j++)
StrBuf->Printf(&buf, ",'%d'", auction->item.card[j]);
+ for (j = 0; j < MAX_ITEM_OPTIONS; j++)
+ StrBuf->Printf(&buf, ",'%d','%d'", auction->item.option[j].index, auction->item.option[j].value);
+
StrBuf->AppendStr(&buf, ")");
stmt = SQL->StmtMalloc(inter->sql_handle);
- if( SQL_SUCCESS != SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf))
+ if (SQL_SUCCESS != SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf))
|| SQL_SUCCESS != SQL->StmtBindParam(stmt, 0, SQLDT_STRING, auction->seller_name, strnlen(auction->seller_name, NAME_LENGTH))
|| SQL_SUCCESS != SQL->StmtBindParam(stmt, 1, SQLDT_STRING, auction->buyer_name, strnlen(auction->buyer_name, NAME_LENGTH))
|| SQL_SUCCESS != SQL->StmtBindParam(stmt, 2, SQLDT_STRING, auction->item_name, strnlen(auction->item_name, ITEM_NAME_LENGTH))
- || SQL_SUCCESS != SQL->StmtExecute(stmt) )
+ || SQL_SUCCESS != SQL->StmtExecute(stmt))
{
SqlStmt_ShowDebug(stmt);
auction->auction_id = 0;
- }
- else
- {
+ } else {
struct auction_data *auction_;
int64 tick = (int64)auction->hours * 3600000;
@@ -204,8 +208,10 @@ void inter_auctions_fromsql(void)
StrBuf->Init(&buf);
StrBuf->AppendStr(&buf, "SELECT `auction_id`,`seller_id`,`seller_name`,`buyer_id`,`buyer_name`,"
"`price`,`buynow`,`hours`,`timestamp`,`nameid`,`item_name`,`type`,`refine`,`attribute`,`unique_id`");
- for( i = 0; i < MAX_SLOTS; i++ )
+ for (i = 0; i < MAX_SLOTS; i++)
StrBuf->Printf(&buf, ",`card%d`", i);
+ for (i = 0; i < MAX_ITEM_OPTIONS; i++)
+ StrBuf->Printf(&buf, ", `opt_idx%d`, `opt_val%d`", i, i);
StrBuf->Printf(&buf, " FROM `%s` ORDER BY `auction_id` DESC", auction_db);
if (SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf)))
@@ -238,14 +244,20 @@ void inter_auctions_fromsql(void)
item->identify = 1;
item->amount = 1;
item->expire_time = 0;
-
- for( i = 0; i < MAX_SLOTS; i++ )
- {
+ /* Card Slots */
+ for (i = 0; i < MAX_SLOTS; i++) {
SQL->GetData(inter->sql_handle, 15 + i, &data, NULL);
item->card[i] = atoi(data);
}
+ /* Item Options */
+ for (i = 0; i < MAX_ITEM_OPTIONS; i++) {
+ SQL->GetData(inter->sql_handle, 15 + MAX_SLOTS + i * 2, &data, NULL);
+ item->option[i].index = atoi(data);
+ SQL->GetData(inter->sql_handle, 16 + MAX_SLOTS + i * 2, &data, NULL);
+ item->option[i].value = atoi(data);
+ }
- if( auction->timestamp > now )
+ if (auction->timestamp > now)
endtick = ((int64)(auction->timestamp - now) * 1000) + tick;
else
endtick = tick + 10000; // 10 seconds to process ended auctions
diff --git a/src/char/int_mail.c b/src/char/int_mail.c
index 10f905a0d..1d00b0fdf 100644
--- a/src/char/int_mail.c
+++ b/src/char/int_mail.c
@@ -57,6 +57,8 @@ static int inter_mail_fromsql(int char_id, struct mail_data* md)
"`zeny`,`amount`,`nameid`,`refine`,`attribute`,`identify`,`unique_id`");
for (i = 0; i < MAX_SLOTS; i++)
StrBuf->Printf(&buf, ",`card%d`", i);
+ for (i = 0; i < MAX_ITEM_OPTIONS; i++)
+ StrBuf->Printf(&buf, ", `opt_idx%d`, `opt_val%d`", i, i);
// I keep the `status` < 3 just in case someone forget to apply the sqlfix
StrBuf->Printf(&buf, " FROM `%s` WHERE `dest_id`='%d' AND `status` < 3 ORDER BY `id` LIMIT %d",
@@ -90,12 +92,18 @@ static int inter_mail_fromsql(int char_id, struct mail_data* md)
SQL->GetData(inter->sql_handle,15, &data, NULL); item->unique_id = strtoull(data, NULL, 10);
item->expire_time = 0;
item->bound = 0;
-
- for (j = 0; j < MAX_SLOTS; j++)
- {
+ /* Card Slots */
+ for (j = 0; j < MAX_SLOTS; j++) {
SQL->GetData(inter->sql_handle, 16 + j, &data, NULL);
item->card[j] = atoi(data);
}
+ /* Item Options */
+ for (j = 0; j < MAX_ITEM_OPTIONS; j++) {
+ SQL->GetData(inter->sql_handle, 16 + MAX_SLOTS + j * 2, &data, NULL);
+ item->option[j].index = atoi(data);
+ SQL->GetData(inter->sql_handle, 17 + MAX_SLOTS + j * 2, &data, NULL);
+ item->option[j].value = atoi(data);
+ }
}
md->full = ( SQL->NumRows(inter->sql_handle) > MAIL_MAX_INBOX );
@@ -138,25 +146,30 @@ int inter_mail_savemessage(struct mail_message* msg)
StrBuf->Printf(&buf, "INSERT INTO `%s` (`send_name`, `send_id`, `dest_name`, `dest_id`, `title`, `message`, `time`, `status`, `zeny`, `amount`, `nameid`, `refine`, `attribute`, `identify`, `unique_id`", mail_db);
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, ") VALUES (?, '%d', ?, '%d', ?, ?, '%lu', '%u', '%d', '%d', '%d', '%d', '%d', '%d', '%"PRIu64"'",
msg->send_id, msg->dest_id, (unsigned long)msg->timestamp, msg->status, msg->zeny, msg->item.amount, msg->item.nameid, msg->item.refine, msg->item.attribute, msg->item.identify, msg->item.unique_id);
for (j = 0; j < MAX_SLOTS; j++)
StrBuf->Printf(&buf, ", '%d'", msg->item.card[j]);
+ for (j = 0; j < MAX_ITEM_OPTIONS; j++)
+ StrBuf->Printf(&buf, ", '%d', '%d'", msg->item.option[j].index, msg->item.option[j].value);
StrBuf->AppendStr(&buf, ")");
// prepare and execute query
stmt = SQL->StmtMalloc(inter->sql_handle);
- if( SQL_SUCCESS != SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf))
+ if (SQL_SUCCESS != SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf))
|| SQL_SUCCESS != SQL->StmtBindParam(stmt, 0, SQLDT_STRING, msg->send_name, strnlen(msg->send_name, NAME_LENGTH))
|| SQL_SUCCESS != SQL->StmtBindParam(stmt, 1, SQLDT_STRING, msg->dest_name, strnlen(msg->dest_name, NAME_LENGTH))
|| SQL_SUCCESS != SQL->StmtBindParam(stmt, 2, SQLDT_STRING, msg->title, strnlen(msg->title, MAIL_TITLE_LENGTH))
|| SQL_SUCCESS != SQL->StmtBindParam(stmt, 3, SQLDT_STRING, msg->body, strnlen(msg->body, MAIL_BODY_LENGTH))
- || SQL_SUCCESS != SQL->StmtExecute(stmt) )
+ || SQL_SUCCESS != SQL->StmtExecute(stmt))
{
SqlStmt_ShowDebug(stmt);
msg->id = 0;
- } else
+ } else {
msg->id = (int)SQL->StmtLastInsertId(stmt);
+ }
SQL->StmtFree(stmt);
StrBuf->Destroy(&buf);
@@ -176,8 +189,10 @@ static bool inter_mail_loadmessage(int mail_id, struct mail_message* msg)
StrBuf->Init(&buf);
StrBuf->AppendStr(&buf, "SELECT `id`,`send_name`,`send_id`,`dest_name`,`dest_id`,`title`,`message`,`time`,`status`,"
"`zeny`,`amount`,`nameid`,`refine`,`attribute`,`identify`,`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 `id` = '%d'", mail_db, mail_id);
if (SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf))
@@ -207,12 +222,18 @@ static bool inter_mail_loadmessage(int mail_id, struct mail_message* msg)
SQL->GetData(inter->sql_handle,15, &data, NULL); msg->item.unique_id = strtoull(data, NULL, 10);
msg->item.expire_time = 0;
msg->item.bound = 0;
-
- for( j = 0; j < MAX_SLOTS; j++ )
- {
+ /* Card Slots */
+ for (j = 0; j < MAX_SLOTS; j++) {
SQL->GetData(inter->sql_handle,16 + j, &data, NULL);
msg->item.card[j] = atoi(data);
}
+ /* Item Options */
+ for (j = 0 ; j < MAX_ITEM_OPTIONS; j++) {
+ SQL->GetData(inter->sql_handle, 16 + MAX_SLOTS + j * 2, &data, NULL);
+ msg->item.option[j].index = atoi(data);
+ SQL->GetData(inter->sql_handle, 17 + MAX_SLOTS + j * 2, &data, NULL);
+ msg->item.option[j].value = atoi(data);
+ }
}
StrBuf->Destroy(&buf);
@@ -269,6 +290,8 @@ static bool inter_mail_DeleteAttach(int mail_id)
StrBuf->Printf(&buf, "UPDATE `%s` SET `zeny` = '0', `nameid` = '0', `amount` = '0', `refine` = '0', `attribute` = '0', `identify` = '0'", mail_db);
for (i = 0; i < MAX_SLOTS; i++)
StrBuf->Printf(&buf, ", `card%d` = '0'", i);
+ for (i = 0; i < MAX_ITEM_OPTIONS; i++)
+ StrBuf->Printf(&buf, ", `opt_idx%d` = '0', `opt_val%d` = '0'", i, i);
StrBuf->Printf(&buf, " WHERE `id` = '%d'", mail_id);
if (SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf))) {
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);