Index: src/char/char.c
===================================================================
--- src/char/char.c (revision 17348)
+++ src/char/char.c (working copy)
@@ -775,7 +775,7 @@
// 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`");
+ StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`");
for( j = 0; j < MAX_SLOTS; ++j )
StringBuf_Printf(&buf, ", `card%d`", j);
StringBuf_Printf(&buf, " FROM `%s` WHERE `%s`='%d'", tablename, selectoption, id);
@@ -798,8 +798,9 @@
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_UINT, &item.bound, 0, NULL, NULL);
for( j = 0; j < MAX_SLOTS; ++j )
- SqlStmt_BindColumn(stmt, 8+j, SQLDT_SHORT, &item.card[j], 0, NULL, NULL);
+ SqlStmt_BindColumn(stmt, 9+j, SQLDT_SHORT, &item.card[j], 0, NULL, NULL);
// bit array indicating which inventory items have already been matched
flag = (bool*) aCalloc(max, sizeof(bool));
@@ -826,14 +827,15 @@
items[i].identify == item.identify &&
items[i].refine == item.refine &&
items[i].attribute == item.attribute &&
- items[i].expire_time == item.expire_time )
+ items[i].expire_time == item.expire_time &&
+ items[i].bound == item.bound )
; //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'",
- tablename, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time);
+ StringBuf_Printf(&buf, "UPDATE `%s` SET `amount`='%d', `equip`='%d', `identify`='%d', `refine`='%d',`attribute`='%d', `expire_time`='%u', `bound`='%d'",
+ 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 )
StringBuf_Printf(&buf, ", `card%d`=%d", j, items[i].card[j]);
StringBuf_Printf(&buf, " WHERE `id`='%d' LIMIT 1", item.id);
@@ -861,7 +863,7 @@
SqlStmt_Free(stmt);
StringBuf_Clear(&buf);
- StringBuf_Printf(&buf, "INSERT INTO `%s`(`%s`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `unique_id`", tablename, selectoption);
+ StringBuf_Printf(&buf, "INSERT INTO `%s`(`%s`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `unique_id`, `bound`", tablename, selectoption);
for( j = 0; j < MAX_SLOTS; ++j )
StringBuf_Printf(&buf, ", `card%d`", j);
StringBuf_AppendStr(&buf, ") VALUES ");
@@ -879,8 +881,8 @@
else
found = true;
- StringBuf_Printf(&buf, "('%d', '%d', '%d', '%d', '%d', '%d', '%d', '%u', '%"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].unique_id);
+ StringBuf_Printf(&buf, "('%d', '%d', '%d', '%d', '%d', '%d', '%d', '%u', '%"PRIu64"', `%d`",
+ 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].unique_id, items[i].bound);
for( j = 0; j < MAX_SLOTS; ++j )
StringBuf_Printf(&buf, ", '%d'", items[i].card[j]);
StringBuf_AppendStr(&buf, ")");
@@ -919,7 +921,7 @@
// 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`");
+ StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `bound`");
for( j = 0; j < MAX_SLOTS; ++j )
StringBuf_Printf(&buf, ", `card%d`", j);
StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`='%d'", inventory_db, id);
@@ -943,8 +945,9 @@
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);
for( j = 0; j < MAX_SLOTS; ++j )
- SqlStmt_BindColumn(stmt, 9+j, SQLDT_SHORT, &item.card[j], 0, NULL, NULL);
+ SqlStmt_BindColumn(stmt, 10+j, SQLDT_SHORT, &item.card[j], 0, NULL, NULL);
// bit array indicating which inventory items have already been matched
flag = (bool*) aCalloc(max, sizeof(bool));
@@ -970,13 +973,14 @@
items[i].refine == item.refine &&
items[i].attribute == item.attribute &&
items[i].expire_time == item.expire_time &&
- items[i].favorite == item.favorite )
+ items[i].favorite == item.favorite &&
+ items[i].bound == item.bound )
; //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'",
- inventory_db, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time, items[i].favorite);
+ StringBuf_Printf(&buf, "UPDATE `%s` SET `amount`='%d', `equip`='%d', `identify`='%d', `refine`='%d',`attribute`='%d', `expire_time`='%u', `favorite`='%d', `bound`='%d'",
+ 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);
for( j = 0; j < MAX_SLOTS; ++j )
StringBuf_Printf(&buf, ", `card%d`=%d", j, items[i].card[j]);
StringBuf_Printf(&buf, " WHERE `id`='%d' LIMIT 1", item.id);
@@ -1001,7 +1005,7 @@
SqlStmt_Free(stmt);
StringBuf_Clear(&buf);
- StringBuf_Printf(&buf, "INSERT INTO `%s` (`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `unique_id`", inventory_db);
+ StringBuf_Printf(&buf, "INSERT INTO `%s` (`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `unique_id`, `bound`", inventory_db);
for( j = 0; j < MAX_SLOTS; ++j )
StringBuf_Printf(&buf, ", `card%d`", j);
StringBuf_AppendStr(&buf, ") VALUES ");
@@ -1018,8 +1022,8 @@
else
found = true;
- StringBuf_Printf(&buf, "('%d', '%d', '%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].favorite, items[i].unique_id);
+ StringBuf_Printf(&buf, "('%d', '%d', '%d', '%d', '%d', '%d', '%d', '%u', '%d', '%"PRIu64"', '%d'",
+ 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].unique_id, items[i].bound);
for( j = 0; j < MAX_SLOTS; ++j )
StringBuf_Printf(&buf, ", '%d'", items[i].card[j]);
StringBuf_AppendStr(&buf, ")");
@@ -1282,7 +1286,7 @@
//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`, `unique_id`");
+ StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `unique_id`, `bound`");
for( i = 0; i < MAX_SLOTS; ++i )
StringBuf_Printf(&buf, ", `card%d`", i);
StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", inventory_db, MAX_INVENTORY);
@@ -1299,10 +1303,11 @@
|| 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_ULONGLONG, &tmp_item.unique_id, 0, NULL, NULL) )
+ || SQL_ERROR == SqlStmt_BindColumn(stmt, 9, SQLDT_ULONGLONG, &tmp_item.unique_id, 0, NULL, NULL)
+ || SQL_ERROR == SqlStmt_BindColumn(stmt,10, SQLDT_CHAR, &tmp_item.bound, 0, NULL, NULL) )
SqlStmt_ShowDebug(stmt);
for( i = 0; i < MAX_SLOTS; ++i )
- if( SQL_ERROR == SqlStmt_BindColumn(stmt, 10+i, SQLDT_SHORT, &tmp_item.card[i], 0, NULL, NULL) )
+ if( SQL_ERROR == SqlStmt_BindColumn(stmt, 11+i, SQLDT_SHORT, &tmp_item.card[i], 0, NULL, NULL) )
SqlStmt_ShowDebug(stmt);
for( i = 0; i < MAX_INVENTORY && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i )
@@ -1313,7 +1318,7 @@
//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`, `unique_id`");
+ StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `unique_id`, `bound`");
for( j = 0; j < MAX_SLOTS; ++j )
StringBuf_Printf(&buf, ", `card%d`", j);
StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", cart_db, MAX_CART);
@@ -1329,10 +1334,11 @@
|| 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_ULONGLONG, &tmp_item.unique_id, 0, NULL, NULL) )
+ || SQL_ERROR == SqlStmt_BindColumn(stmt, 8, SQLDT_ULONGLONG, &tmp_item.unique_id, 0, NULL, NULL)
+ || SQL_ERROR == SqlStmt_BindColumn(stmt, 9, SQLDT_CHAR, &tmp_item.bound, 0, NULL, NULL) )
SqlStmt_ShowDebug(stmt);
for( i = 0; i < MAX_SLOTS; ++i )
- if( SQL_ERROR == SqlStmt_BindColumn(stmt, 9+i, SQLDT_SHORT, &tmp_item.card[i], 0, NULL, NULL) )
+ if( SQL_ERROR == SqlStmt_BindColumn(stmt, 10+i, SQLDT_SHORT, &tmp_item.card[i], 0, NULL, NULL) )
SqlStmt_ShowDebug(stmt);
for( i = 0; i < MAX_CART && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i )
Index: src/char/int_mail.c
===================================================================
--- src/char/int_mail.c (revision 17348)
+++ src/char/int_mail.c (working copy)
@@ -63,6 +63,7 @@
Sql_GetData(sql_handle,14, &data, NULL); item->identify = atoi(data);
Sql_GetData(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++)
{
@@ -183,6 +184,7 @@
Sql_GetData(sql_handle,14, &data, NULL); msg->item.identify = atoi(data);
Sql_GetData(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++ )
{
Index: src/char/int_storage.c
===================================================================
--- src/char/int_storage.c (revision 17348)
+++ src/char/int_storage.c (working copy)
@@ -38,7 +38,7 @@
// 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`,`unique_id`");
+ StringBuf_AppendStr(&buf, "SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`expire_time`,`unique_id`,`bound`");
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`", storage_db, account_id);
@@ -60,9 +60,10 @@
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->unique_id = strtoull(data, NULL, 10);
+ Sql_GetData(sql_handle, 9, &data, NULL); item->bound = atoi(data);
for( j = 0; j < MAX_SLOTS; ++j )
{
- Sql_GetData(sql_handle, 9+j, &data, NULL); item->card[j] = atoi(data);
+ Sql_GetData(sql_handle, 10+j, &data, NULL); item->card[j] = atoi(data);
}
}
p->storage_amount = i;
@@ -95,7 +96,7 @@
// storage {`guild_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`,`unique_id`");
+ StringBuf_AppendStr(&buf, "SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`unique_id`,`bound`");
for( j = 0; j < MAX_SLOTS; ++j )
StringBuf_Printf(&buf, ",`card%d`", j);
StringBuf_Printf(&buf, " FROM `%s` WHERE `guild_id`='%d' ORDER BY `nameid`", guild_storage_db, guild_id);
@@ -116,10 +117,11 @@
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->unique_id = strtoull(data, NULL, 10);
+ Sql_GetData(sql_handle, 8, &data, NULL); item->bound = atoi(data);
item->expire_time = 0;
for( j = 0; j < MAX_SLOTS; ++j )
{
- Sql_GetData(sql_handle, 8+j, &data, NULL); item->card[j] = atoi(data);
+ Sql_GetData(sql_handle, 9+j, &data, NULL); item->card[j] = atoi(data);
}
}
p->storage_amount = i;
@@ -234,13 +236,92 @@
return 0;
}
+int mapif_itembound_ack(int fd, int aid, int guild_id)
+{
+ WFIFOHEAD(fd,8);
+ WFIFOW(fd,0) = 0x3857;
+ WFIFOL(fd,2) = aid;
+ WFIFOW(fd,6) = guild_id;
+ WFIFOSET(fd,8);
+ return 0;
+}
+//------------------------------------------------
+//Guild bound items pull for offline characters [Akinari]
+//Fills in item structure to be used elsewhere
+//------------------------------------------------
+int mapif_parse_itembound_retrieve(int fd)
+{
+ StringBuf buf;
+ SqlStmt* stmt;
+ struct item item;
+ int j, i=0;
+ struct item items[MAX_INVENTORY];
+ int char_id = RFIFOW(fd,2);
+ int aid = RFIFOL(fd,4);
+ int guild_id = RFIFOW(fd,8);
+
+ StringBuf_Init(&buf);
+ StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`");
+ for( j = 0; j < MAX_SLOTS; ++j )
+ StringBuf_Printf(&buf, ", `card%d`", j);
+ StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`='%d'",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_SHORT, &item.nameid, 0, NULL, NULL);
+ SqlStmt_BindColumn(stmt, 2, SQLDT_SHORT, &item.amount, 0, NULL, NULL);
+ SqlStmt_BindColumn(stmt, 3, SQLDT_USHORT, &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_UINT, &item.bound, 0, NULL, NULL);
+ for( j = 0; j < MAX_SLOTS; ++j )
+ SqlStmt_BindColumn(stmt, 9+j, SQLDT_SHORT, &item.card[j], 0, NULL, NULL);
+
+ while( SQL_SUCCESS == SqlStmt_NextRow(stmt) ) {
+ if(item.bound == 2) {
+ ShowDebug("Found and item: Item=%d\n",item.nameid);
+ memcpy(&items[i],&item,sizeof(item));
+ i++;
+ }
+ }
+
+ for(j=0; j<i; j++){
+ StringBuf_Printf(&buf, "DELETE FROM `%s` WHERE `id`=%d;",inventory_db,items[j].id);
+ StringBuf_Printf(&buf, "INSERT INTO %s(nameid,amount,identify,refine,attribute,expire_time) VALUES(%d,%d,%d,%d,%d,%d);",
+ guild_storage_db,items[i].nameid,items[i].amount,items[i].identify,items[i].refine,items[i].attribute,items[i].expire_time);
+ 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;
+ }
+ }
+ mapif_load_guild_storage(fd,aid,guild_id);
+ mapif_itembound_ack(fd,aid,guild_id);
+ return 0;
+}
+
int 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 0x3856: mapif_parse_itembound_retrieve(fd); break;
default:
return 0;
}
Index: src/common/mmo.h
===================================================================
--- src/common/mmo.h (revision 17348)
+++ src/common/mmo.h (working copy)
@@ -204,7 +204,7 @@
char attribute;
short card[MAX_SLOTS];
unsigned int expire_time;
- char favorite;
+ char favorite, bound;
uint64 unique_id;
};
Index: src/map/buyingstore.c
===================================================================
--- src/map/buyingstore.c (revision 17348)
+++ src/map/buyingstore.c (working copy)
@@ -311,7 +311,7 @@
return;
}
- if( sd->status.inventory[index].expire_time || !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->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)) )
{// non-tradable item
clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid);
return;
Index: src/map/clif.c
===================================================================
--- src/map/clif.c (revision 17348)
+++ src/map/clif.c (working copy)
@@ -1790,8 +1790,8 @@
if( !itemdb_cansell(&sd->status.inventory[i], pc_get_group_level(sd)) )
continue;
- if( sd->status.inventory[i].expire_time )
- continue; // Cannot Sell Rental Items
+ if( sd->status.inventory[i].expire_time || (sd->status.inventory[i].bound && !pc_can_give_bounded_items(sd)) )
+ continue; // Cannot Sell Rental Items or Account Bounded Items
val=sd->inventory_data[i]->value_sell;
if( val < 0 )
@@ -2194,7 +2194,7 @@
WFIFOL(fd,offs+23)=sd->status.inventory[n].expire_time;
#endif
#if PACKETVER >= 20071002
- WFIFOW(fd,offs+27)=0; // HireExpireDate
+ WFIFOW(fd,offs+27)=sd->status.inventory[n].bound ? 2 : 0;
#endif
}
@@ -2300,7 +2300,7 @@
clif_addcards(WBUFP(buf, n+12), i); //8B
#if PACKETVER >= 20071002
WBUFL(buf,n+20)=i->expire_time;
- WBUFW(buf,n+24)=0; //Unknown
+ WBUFW(buf,n+24)=i->bound ? 2 : 0;
#endif
#if PACKETVER >= 20100629
WBUFW(buf,n+26)= (id->equip&EQP_VISIBLE)?id->look:0;
@@ -14189,6 +14189,14 @@
}
// Auction checks...
+ if( sd->status.inventory[sd->auction.index].bound && !pc_can_give_bounded_items(sd) ) {
+ if( sd->status.inventory[sd->auction.index].bound == 1 )
+ clif_displaymessage(sd->fd, msg_txt(sd,293));
+ else
+ clif_displaymessage(sd->fd, msg_txt(sd,294));
+ clif_Auction_message(fd, 2); // The auction has been canceled
+ return;
+ }
if( sd->status.zeny < (auction.hours * battle_config.auction_feeperhour) ) {
clif_Auction_message(fd, 5); // You do not have enough zeny to pay the Auction Fee.
return;
Index: src/map/guild.c
===================================================================
--- src/map/guild.c (revision 17348)
+++ src/map/guild.c (working copy)
@@ -860,6 +860,9 @@
if(online_member_sd == NULL)
return 0; // noone online to inform
+ //Guild bound item check
+ guild_retrieveitembound(char_id,account_id,guild_id);
+
if(!flag)
clif_guild_leave(online_member_sd, name, mes);
else
@@ -884,9 +887,32 @@
clif_charnameupdate(sd); //Update display name [Skotlex]
//TODO: send emblem update to self and people around
}
+
return 0;
}
+void guild_retrieveitembound(int char_id,int aid,int guild_id)
+{
+ TBL_PC *sd = map_id2sd(aid);
+ if(sd){ //char is online
+ int idxlist[MAX_INVENTORY]; //or malloc to reduce consumtion
+ int j,i;
+ j = pc_bound_chk(sd,2,idxlist);
+ if(j) {
+ struct guild_storage* stor = guild2storage(sd->status.guild_id);
+ ShowDebug("There is an item. index=%d\n",idxlist[0]);
+ for(i=0;i<j;i++) {
+ guild_storage_additem(sd,stor,&sd->status.inventory[idxlist[i]],sd->status.inventory[idxlist[i]].amount);
+ pc_delitem(sd,idxlist[i],sd->status.inventory[idxlist[i]].amount,0,4,LOG_TYPE_GSTORAGE);
+ }
+ storage_guild_storageclose(sd);
+ }
+ }
+ else { //char is offline ask char to do the job
+ intif_itembound_req(char_id,aid,guild_id);
+ }
+}
+
int guild_send_memberinfoshort(struct map_session_data *sd,int online)
{ // cleaned up [LuzZza]
struct guild *g;
Index: src/map/guild.h
===================================================================
--- src/map/guild.h (revision 17348)
+++ src/map/guild.h (working copy)
@@ -106,6 +106,7 @@
void guild_flags_clear(void);
void guild_guildaura_refresh(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv);
+void guild_retrieveitembound(int char_id,int aid,int guild_id);
void do_final_guild(void);
Index: src/map/intif.c
===================================================================
--- src/map/intif.c (revision 17348)
+++ src/map/intif.c (working copy)
@@ -39,7 +39,7 @@
39,-1,15,15, 14,19, 7,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3820
10,-1,15, 0, 79,19, 7,-1, 0,-1,-1,-1, 14,67,186,-1, //0x3830
-1, 0, 0,14, 0, 0, 0, 0, -1,74,-1,11, 11,-1, 0, 0, //0x3840
- -1,-1, 7, 7, 7,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3850 Auctions [Zephyrus]
+ -1,-1, 7, 7, 7,11,10, 8, 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]
11,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3880
@@ -2152,6 +2152,31 @@
return;
}
+void intif_itembound_req(int char_id,int aid,int guild_id) {
+ struct guild_storage *gstor = guild2storage2(guild_id);
+ if(gstor) {
+ WFIFOHEAD(char_fd,10);
+ WFIFOW(char_fd,0) = 0x3856;
+ WFIFOW(char_fd,2) = char_id;
+ WFIFOL(char_fd,4) = aid;
+ WFIFOW(char_fd,8) = guild_id;
+ WFIFOSET(char_fd,10);
+ gstor->lock = 1; //lock for retrive process
+ } //no guildstorage ?
+}
+
+//3857
+void intif_parse_itembound_ack(int fd) {
+ struct guild_storage *gstor;
+ int aid = RFIFOL(char_fd,2);
+ int guild_id = RFIFOW(char_fd,6);
+ TBL_PC *sd = map_id2sd(aid);
+
+ gstor = guild2storage2(guild_id);
+ if(gstor) gstor->lock = 0; //now could be used again
+ if(sd) storage_guild_storageclose(sd); //at this point guild_storage should have been open
+}
+
//-----------------------------------------------------------------
// Communication from the inter server
// Return a 0 (false) if there were any errors.
@@ -2235,6 +2260,9 @@
case 0x3854: intif_parse_Auction_message(fd); break;
case 0x3855: intif_parse_Auction_bid(fd); break;
+//Bound items
+ case 0x3857: intif_parse_itembound_ack(int fd); break;
+
// Mercenary System
case 0x3870: intif_parse_mercenary_received(fd); break;
case 0x3871: intif_parse_mercenary_deleted(fd); break;
Index: src/map/intif.h
===================================================================
--- src/map/intif.h (revision 17348)
+++ src/map/intif.h (working copy)
@@ -60,6 +60,7 @@
int intif_guild_emblem(int guild_id, int len, const char *data);
int intif_guild_castle_dataload(int num, int *castle_ids);
int intif_guild_castle_datasave(int castle_id, int index, int value);
+void intif_itembound_req(int char_id, int aid, int guild_id);
int intif_create_pet(int account_id, int char_id, short pet_type, short pet_lv, short pet_egg_id,
short pet_equip, short intimate, short hungry, char rename_flag, char incuvate, char *pet_name);
Index: src/map/pc.c
===================================================================
--- src/map/pc.c (revision 17348)
+++ src/map/pc.c (working copy)
@@ -509,6 +509,14 @@
return pc_has_permission(sd, PC_PERM_TRADE);
}
+/**
+ * Determines if player can give / drop / trade / vend bounded items
+ */
+bool pc_can_give_bounded_items(struct map_session_data *sd)
+{
+ return pc_has_permission(sd, PC_PERM_TRADE_BOUNDED);
+}
+
/*==========================================
* prepares character for saving.
*------------------------------------------*/
@@ -3878,7 +3886,7 @@
{ // Stackable | Non Rental
for( i = 0; i < MAX_INVENTORY; i++ )
{
- if( sd->status.inventory[i].nameid == item_data->nameid && memcmp(&sd->status.inventory[i].card, &item_data->card, sizeof(item_data->card)) == 0 )
+ if( sd->status.inventory[i].nameid == item_data->nameid && sd->status.inventory[i].bound == item_data->bound && memcmp(&sd->status.inventory[i].card, &item_data->card, sizeof(item_data->card)) == 0 )
{
if( amount > MAX_AMOUNT - sd->status.inventory[i].amount || ( data->stack.inventory && amount > data->stack.amount - sd->status.inventory[i].amount ) )
return 5;
@@ -4418,7 +4426,7 @@
return 1;
}
- if( !itemdb_cancartstore(item_data, pc_get_group_level(sd)) )
+ if( !itemdb_cancartstore(item_data, pc_get_group_level(sd)) || (item_data->bound == 2 && !pc_can_give_bounded_items(sd)))
{ // Check item trade restrictions [Skotlex]
clif_displaymessage (sd->fd, msg_txt(sd,264));
return 1;
@@ -4431,7 +4439,7 @@
if( itemdb_isstackable2(data) && !item_data->expire_time )
{
ARR_FIND( 0, MAX_CART, i,
- sd->status.cart[i].nameid == item_data->nameid &&
+ sd->status.cart[i].nameid == item_data->nameid && sd->status.cart[i].bound == item_data->bound &&
sd->status.cart[i].card[0] == item_data->card[0] && sd->status.cart[i].card[1] == item_data->card[1] &&
sd->status.cart[i].card[2] == item_data->card[2] && sd->status.cart[i].card[3] == item_data->card[3] );
};
@@ -4567,6 +4575,25 @@
}
/*==========================================
+ * Bound Item Check
+ * Type:
+ * 1 Account Bound
+ * 2 Guild Bound
+ * 3 Party Bound
+ *------------------------------------------*/
+int pc_bound_chk(TBL_PC *sd,int type,int *idxlist)
+{
+ int i=0, j=0;
+ for(i=0;i<MAX_INVENTORY;i++){
+ if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].amount > 0 && sd->status.inventory[i].bound == type) {
+ idxlist[j] = i;
+ j++;
+ }
+ }
+ return j;
+}
+
+/*==========================================
* Display item stolen msg to player sd
*------------------------------------------*/
int pc_show_steal(struct block_list *bl,va_list ap)
@@ -7880,7 +7907,7 @@
*------------------------------------------*/
int pc_candrop(struct map_session_data *sd, struct item *item)
{
- if( item && item->expire_time )
+ if( item && (item->expire_time || (item->bound && !pc_can_give_bounded_items(sd))) )
return 0;
if( !pc_can_give_items(sd) ) //check if this GM level can drop items
return 0;
Index: src/map/pc.h
===================================================================
--- src/map/pc.h (revision 17348)
+++ src/map/pc.h (working copy)
@@ -705,6 +705,7 @@
int pc_get_group_id(struct map_session_data *sd);
int pc_getrefinebonus(int lv,int type);
bool pc_can_give_items(struct map_session_data *sd);
+bool pc_can_give_bounded_items(struct map_session_data *sd);
bool pc_can_use_command(struct map_session_data *sd, const char *command, AtCommandType type);
#define pc_has_permission(sd, permission) ( ((sd)->permissions&permission) != 0 )
@@ -748,6 +749,9 @@
int pc_getzeny(struct map_session_data*,int, enum e_log_pick_type, struct map_session_data*);
int pc_delitem(struct map_session_data*,int,int,int,short,e_log_pick_type);
+//Bound items
+int pc_bound_chk(TBL_PC *sd,int type,int *idxlist);
+
// Special Shop System
int pc_paycash( struct map_session_data *sd, int price, int points, e_log_pick_type type );
int pc_getcash( struct map_session_data *sd, int cash, int points, e_log_pick_type type );
Index: src/map/pc_groups.h
===================================================================
--- src/map/pc_groups.h (revision 17348)
+++ src/map/pc_groups.h (working copy)
@@ -44,6 +44,7 @@
PC_PERM_DISABLE_PVP = 0x080000,
PC_PERM_DISABLE_CMD_DEAD = 0x100000,
PC_PERM_CHANNEL_ADMIN = 0x200000,
+ PC_PERM_TRADE_BOUNDED = 0x400000,
};
static const struct {
@@ -72,6 +73,7 @@
{ "disable_pvp", PC_PERM_DISABLE_PVP },
{ "disable_commands_when_dead", PC_PERM_DISABLE_CMD_DEAD },
{ "channel_admin", PC_PERM_CHANNEL_ADMIN },
+ { "can_trade_bounded", PC_PERM_TRADE_BOUNDED },
};
#endif // _PC_GROUPS_H_
Index: src/map/storage.c
===================================================================
--- src/map/storage.c (revision 17348)
+++ src/map/storage.c (working copy)
@@ -120,7 +120,8 @@
a->identify == b->identify &&
a->refine == b->refine &&
a->attribute == b->attribute &&
- a->expire_time == b->expire_time )
+ a->expire_time == b->expire_time &&
+ a->bound == b->bound )
{
int i;
for (i = 0; i < MAX_SLOTS && (a->card[i] == b->card[i]); i++);
@@ -148,7 +149,7 @@
return 1;
}
- if( !itemdb_canstore(item_data, pc_get_group_level(sd)) )
+ if( !itemdb_canstore(item_data, pc_get_group_level(sd)) || (item_data->bound == 2 && !pc_can_give_bounded_items(sd)))
{ //Check if item is storable. [Skotlex]
clif_displaymessage (sd->fd, msg_txt(sd,264));
return 1;
@@ -442,7 +443,7 @@
return 1;
}
- if( !itemdb_canguildstore(item_data, pc_get_group_level(sd)) || item_data->expire_time )
+ if( !itemdb_canguildstore(item_data, pc_get_group_level(sd)) || item_data->expire_time || (item_data->bound == 1 && !pc_can_give_bounded_items(sd)) )
{ //Check if item is storable. [Skotlex]
clif_displaymessage (sd->fd, msg_txt(sd,264));
return 1;
Index: src/map/trade.c
===================================================================
--- src/map/trade.c (revision 17348)
+++ src/map/trade.c (working copy)
@@ -368,6 +368,15 @@
return;
}
+ if( (item->bound == 1 || (item->bound == 2 && sd->status.guild_id != target_sd->status.guild_id)) && !pc_can_give_bounded_items(sd) ) { // Account/Guild Bound
+ if( item->bound == 1 )
+ clif_displaymessage(sd->fd, msg_txt(sd,293));
+ else
+ clif_displaymessage(sd->fd, msg_txt(sd,294));
+ clif_tradeitemok(sd, index+2, 1);
+ return;
+ }
+
//Locate a trade position
ARR_FIND( 0, 10, trade_i, sd->deal.item[trade_i].index == index || sd->deal.item[trade_i].amount == 0 );
if( trade_i == 10 ) //No space left
Index: src/map/vending.c
===================================================================
--- src/map/vending.c (revision 17348)
+++ src/map/vending.c (working copy)
@@ -267,6 +267,7 @@
|| !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
continue;