summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/char/char.c32
-rw-r--r--src/char/int_storage.c58
-rw-r--r--src/char/inter.c18
-rw-r--r--src/common/mmo.h12
-rw-r--r--src/config/core.h3
-rw-r--r--src/map/atcommand.c20
-rw-r--r--src/map/clif.c33
-rw-r--r--src/map/clif.h8
-rw-r--r--src/map/guild.c39
-rw-r--r--src/map/guild.h2
-rw-r--r--src/map/intif.c28
-rw-r--r--src/map/intif.h2
-rw-r--r--src/map/mail.c6
-rw-r--r--src/map/packets_struct.h1
-rw-r--r--src/map/party.c10
-rw-r--r--src/map/pc.c92
-rw-r--r--src/map/pc.h5
-rw-r--r--src/map/pc_groups.c2
-rw-r--r--src/map/pc_groups.h2
-rw-r--r--src/map/script.c252
-rw-r--r--src/map/script.h1
-rw-r--r--src/map/storage.c8
-rw-r--r--src/map/trade.c23
-rw-r--r--src/map/vending.c2
24 files changed, 275 insertions, 384 deletions
diff --git a/src/char/char.c b/src/char/char.c
index 9e84f0245..ce4fcbe53 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -747,7 +747,7 @@ int memitemdata_to_sql(const struct item items[], int max, int id, int tableswit
SQL->StmtBindColumn(stmt, 5, SQLDT_CHAR, &item.refine, 0, NULL, NULL);
SQL->StmtBindColumn(stmt, 6, SQLDT_CHAR, &item.attribute, 0, NULL, NULL);
SQL->StmtBindColumn(stmt, 7, SQLDT_UINT, &item.expire_time, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 8, SQLDT_UINT, &item.bound, 0, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 8, SQLDT_UCHAR, &item.bound, 0, NULL, NULL);
for( j = 0; j < MAX_SLOTS; ++j )
SQL->StmtBindColumn(stmt, 9+j, SQLDT_SHORT, &item.card[j], 0, NULL, NULL);
@@ -894,7 +894,7 @@ int inventory_to_sql(const struct item items[], int max, int id) {
SQL->StmtBindColumn(stmt, 6, SQLDT_CHAR, &item.attribute, 0, NULL, NULL);
SQL->StmtBindColumn(stmt, 7, SQLDT_UINT, &item.expire_time, 0, NULL, NULL);
SQL->StmtBindColumn(stmt, 8, SQLDT_CHAR, &item.favorite, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 9, SQLDT_CHAR, &item.bound, 0, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 9, SQLDT_UCHAR, &item.bound, 0, NULL, NULL);
for( j = 0; j < MAX_SLOTS; ++j )
SQL->StmtBindColumn(stmt, 10+j, SQLDT_SHORT, &item.card[j], 0, NULL, NULL);
@@ -1243,17 +1243,17 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
if( SQL_ERROR == SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf))
|| SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, 0)
|| SQL_ERROR == SQL->StmtExecute(stmt)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &tmp_item.id, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_SHORT, &tmp_item.nameid, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_SHORT, &tmp_item.amount, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 3, SQLDT_UINT, &tmp_item.equip, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 4, SQLDT_CHAR, &tmp_item.identify, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 5, SQLDT_CHAR, &tmp_item.refine, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 6, SQLDT_CHAR, &tmp_item.attribute, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 7, SQLDT_UINT, &tmp_item.expire_time, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 8, SQLDT_CHAR, &tmp_item.favorite, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 9, SQLDT_CHAR, &tmp_item.bound, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 10, SQLDT_ULONGLONG, &tmp_item.unique_id, 0, NULL, NULL) )
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &tmp_item.id, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_SHORT, &tmp_item.nameid, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_SHORT, &tmp_item.amount, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 3, SQLDT_UINT, &tmp_item.equip, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 4, SQLDT_CHAR, &tmp_item.identify, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 5, SQLDT_CHAR, &tmp_item.refine, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 6, SQLDT_CHAR, &tmp_item.attribute, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 7, SQLDT_UINT, &tmp_item.expire_time, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 8, SQLDT_CHAR, &tmp_item.favorite, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 9, SQLDT_UCHAR, &tmp_item.bound, 0, NULL, NULL)
+ || 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) )
@@ -1283,8 +1283,8 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 5, SQLDT_CHAR, &tmp_item.refine, 0, NULL, NULL)
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 6, SQLDT_CHAR, &tmp_item.attribute, 0, NULL, NULL)
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 7, SQLDT_UINT, &tmp_item.expire_time, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 8, SQLDT_CHAR, &tmp_item.bound, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 9, SQLDT_ULONGLONG, &tmp_item.unique_id, 0, NULL, NULL) )
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 8, SQLDT_UCHAR, &tmp_item.bound, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 9, 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, 10+i, SQLDT_SHORT, &tmp_item.card[i], 0, NULL, NULL) )
@@ -2959,7 +2959,7 @@ int parse_frommap(int fd)
break;
}
//Check account only if this ain't final save. Final-save goes through because of the char-map reconnect
- if (RFIFOB(fd,12) || RFIFOB(fd,13) || (
+ if (RFIFOB(fd,12) || (
(character = (struct online_char_data*)idb_get(online_char_db, aid)) != NULL &&
character->char_id == cid))
{
diff --git a/src/char/int_storage.c b/src/char/int_storage.c
index 6443aa743..30671df5e 100644
--- a/src/char/int_storage.c
+++ b/src/char/int_storage.c
@@ -107,8 +107,7 @@ int guild_storage_fromsql(int guild_id, struct guild_storage* p)
StrBuf->Destroy(&buf);
- for( i = 0; i < MAX_GUILD_STORAGE && SQL_SUCCESS == SQL->NextRow(sql_handle); ++i )
- {
+ for( i = 0; i < MAX_GUILD_STORAGE && SQL_SUCCESS == SQL->NextRow(sql_handle); ++i ) {
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);
@@ -120,9 +119,8 @@ int guild_storage_fromsql(int guild_id, struct guild_storage* p)
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;
- item->bound = 0;
- for( j = 0; j < MAX_SLOTS; ++j )
- {
+
+ for( j = 0; j < MAX_SLOTS; ++j ) {
SQL->GetData(sql_handle, 9+j, &data, NULL); item->card[j] = atoi(data);
}
}
@@ -239,14 +237,15 @@ int mapif_parse_SaveGuildStorage(int fd)
return 0;
}
-#ifdef BOUND_ITEMS
int mapif_itembound_ack(int fd, int aid, int guild_id)
{
+#ifdef GP_BOUND_ITEMS
WFIFOHEAD(fd,8);
WFIFOW(fd,0) = 0x3856;
WFIFOL(fd,2) = aid;
WFIFOW(fd,6) = guild_id;
WFIFOSET(fd,8);
+#endif
return 0;
}
@@ -254,23 +253,23 @@ int mapif_itembound_ack(int fd, int aid, int guild_id)
//Guild bound items pull for offline characters [Akinari]
//Revised by [Mhalicot]
//------------------------------------------------
-int mapif_parse_itembound_retrieve(int fd)
+int mapif_parse_ItemBoundRetrieve(int fd)
{
+#ifdef GP_BOUND_ITEMS
StringBuf buf;
SqlStmt* stmt;
struct item item;
int j, i=0, s;
- bool found=false;
struct item items[MAX_INVENTORY];
int char_id = RFIFOL(fd,2);
int aid = RFIFOL(fd,6);
int guild_id = RFIFOW(fd,10);
StrBuf->Init(&buf);
- StrBuf->AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`");
+ 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);
- StrBuf->Printf(&buf, " FROM `%s` WHERE `char_id`='%d'",inventory_db,char_id);
+ StrBuf->Printf(&buf, " FROM `%s` WHERE `char_id`='%d' AND `bound` = '%d'",inventory_db,char_id,IBT_GUILD);
stmt = SQL->StmtMalloc(sql_handle);
if( SQL_ERROR == SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf))
@@ -290,15 +289,14 @@ int mapif_parse_itembound_retrieve(int fd)
SQL->StmtBindColumn(stmt, 5, SQLDT_CHAR, &item.refine, 0, NULL, NULL);
SQL->StmtBindColumn(stmt, 6, SQLDT_CHAR, &item.attribute, 0, NULL, NULL);
SQL->StmtBindColumn(stmt, 7, SQLDT_UINT, &item.expire_time, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 8, SQLDT_UINT, &item.bound, 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, 9+j, SQLDT_SHORT, &item.card[j], 0, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 10+j, SQLDT_SHORT, &item.card[j], 0, NULL, NULL);
while( SQL_SUCCESS == SQL->StmtNextRow(stmt) ) {
- if(item.bound == 2) {
- memcpy(&items[i],&item,sizeof(struct item));
- i++;
- }
+ memcpy(&items[i],&item,sizeof(struct item));
+ i++;
}
SQL->FreeResult(sql_handle);
@@ -312,10 +310,9 @@ int mapif_parse_itembound_retrieve(int fd)
StrBuf->Clear(&buf);
StrBuf->Printf(&buf, "DELETE FROM `%s` WHERE",inventory_db);
for(j=0; j<i; j++) {
- if( found )
+ if( j )
StrBuf->AppendStr(&buf, " OR");
- else
- found = true;
+
StrBuf->Printf(&buf, " `id`=%d",items[j].id);
}
@@ -329,21 +326,18 @@ int mapif_parse_itembound_retrieve(int fd)
}
//Now let's update the guild storage with those deleted items
- found = false;
StrBuf->Clear(&buf);
- StrBuf->Printf(&buf, "INSERT INTO `%s` (`guild_id`, `nameid`, `amount`, `identify`, `refine`, `attribute`, `expire_time`, `bound`", guild_storage_db);
+ StrBuf->Printf(&buf, "INSERT INTO `%s` (`guild_id`, `nameid`, `amount`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`", guild_storage_db);
for( j = 0; j < MAX_SLOTS; ++j )
StrBuf->Printf(&buf, ", `card%d`", j);
StrBuf->AppendStr(&buf, ") VALUES ");
for( j = 0; j < i; ++j ) {
- if( found )
+ if( j )
StrBuf->AppendStr(&buf, ",");
- else
- found = true;
StrBuf->Printf(&buf, "('%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d'",
- guild_id, items[j].nameid, items[j].amount, items[j].identify, items[j].refine, items[j].attribute, items[j].expire_time, items[j].bound);
+ guild_id, items[j].nameid, items[j].amount, 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 )
StrBuf->Printf(&buf, ", '%d'", items[j].card[s]);
StrBuf->AppendStr(&buf, ")");
@@ -364,21 +358,21 @@ int mapif_parse_itembound_retrieve(int fd)
//Finally reload storage and tell map we're done
mapif_load_guild_storage(fd,aid,guild_id,0);
mapif_itembound_ack(fd,aid,guild_id);
+#endif
return 0;
}
-#endif
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;
-#ifdef BOUND_ITEMS
- case 0x3056: mapif_parse_itembound_retrieve(fd); break;
+ case 0x3018: mapif_parse_LoadGuildStorage(fd); break;
+ case 0x3019: mapif_parse_SaveGuildStorage(fd); break;
+#ifdef GP_BOUND_ITEMS
+ case 0x3056: mapif_parse_ItemBoundRetrieve(fd); break;
#endif
- default:
- return 0;
+ default:
+ return 0;
}
return 1;
}
diff --git a/src/char/inter.c b/src/char/inter.c
index 54672faee..b213f1608 100644
--- a/src/char/inter.c
+++ b/src/char/inter.c
@@ -48,15 +48,15 @@ unsigned int party_share_level = 10;
// recv. packet list
int inter_recv_packet_length[] = {
-1,-1, 7,-1, -1,13,36, (2 + 4 + 4 + 4 + NAME_LENGTH), 0, 0, 0, 0, 0, 0, 0, 0, // 3000-
- 6,-1, 0, 0, 0, 0, 0, 0, 10,-1, 0, 0, 0, 0, 0, 0, // 3010-
- -1,10,-1,14, 14,19, 6,-1, 14,14, 0, 0, 0, 0, 0, 0, // 3020- Party
- -1, 6,-1,-1, 55,19, 6,-1, 14,-1,-1,-1, 18,19,186,-1, // 3030-
- -1, 9, 0, 0, 0, 0, 0, 0, 7, 6,10,10, 10,-1, 0, 0, // 3040-
- -1,-1,10,10, 0,-1, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3050- Auction System [Zephyrus] [Mhalicot]
- 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-
- -1,10,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3090- Homunculus packets [albator]
+ 6,-1, 0, 0, 0, 0, 0, 0, 10,-1, 0, 0, 0, 0, 0, 0, // 3010-
+ -1,10,-1,14, 14,19, 6,-1, 14,14, 0, 0, 0, 0, 0, 0, // 3020- Party
+ -1, 6,-1,-1, 55,19, 6,-1, 14,-1,-1,-1, 18,19,186,-1, // 3030-
+ -1, 9, 0, 0, 0, 0, 0, 0, 7, 6,10,10, 10,-1, 0, 0, // 3040-
+ -1,-1,10,10, 0,-1,12, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3050- Auction System [Zephyrus], Item Bound [Mhalicot]
+ 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-
+ -1,10,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3090- Homunculus packets [albator]
};
struct WisData {
diff --git a/src/common/mmo.h b/src/common/mmo.h
index f676893ea..369f5c894 100644
--- a/src/common/mmo.h
+++ b/src/common/mmo.h
@@ -222,7 +222,8 @@ struct item {
char attribute;
short card[MAX_SLOTS];
unsigned int expire_time;
- char favorite, bound;
+ char favorite;
+ unsigned char bound;
uint64 unique_id;
};
@@ -249,6 +250,15 @@ enum e_mmo_charstatus_opt {
OPT_ALLOW_PARTY = 0x2,
};
+enum e_item_bound_type {
+ IBT_MIN = 0x1,
+ IBT_ACCOUNT = 0x1,
+ IBT_GUILD = 0x2,
+ IBT_PARTY = 0x3,
+ IBT_CHARACTER = 0x4,
+ IBT_MAX = 0x4,
+};
+
struct s_skill {
unsigned short id;
unsigned char lv;
diff --git a/src/config/core.h b/src/config/core.h
index 481c35af8..daadc6455 100644
--- a/src/config/core.h
+++ b/src/config/core.h
@@ -62,8 +62,7 @@
//#define NSI_UNIQUE_ID
/// Comment to disable Guild/Party Bound item system
-/// By default, we recover/remove Guild/Party Bound items automatically
-#define BOUND_ITEMS
+#define GP_BOUND_ITEMS
/// Uncomment to enable real-time server stats (in and out data and ram usage). [Ai4rei]
//#define SHOW_SERVER_STATS
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index 3f3e9679e..e19428d36 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -1104,7 +1104,7 @@ ACMD(item)
sscanf(message, "%99s %d %d", item_name, &number, &bound) < 2
))) {
clif->message(fd, msg_txt(295)); // Please enter an item name or ID (usage: @itembound <item name/ID> <quantity> <bound_type>).
- return -1;
+ return false;
} else if (!message || !*message || (
sscanf(message, "\"%99[^\"]\" %d", item_name, &number) < 1 &&
sscanf(message, "%99s %d", item_name, &number) < 1 ))
@@ -1123,7 +1123,7 @@ ACMD(item)
return false;
}
- if( bound < 0 || bound > 4 ) {
+ if( bound < IBT_MIN || bound > IBT_MAX ) {
clif->message(fd, msg_txt(298)); // Invalid bound type
return false;
}
@@ -1137,9 +1137,6 @@ ACMD(item)
return false;
}
get_count = 1;
- } else if( bound ) {
- clif->message(fd, msg_txt(499)); // Cannot create bounded stackable items.
- return false;
}
for (i = 0; i < number; i += get_count) {
@@ -1148,7 +1145,7 @@ ACMD(item)
memset(&item_tmp, 0, sizeof(item_tmp));
item_tmp.nameid = item_id;
item_tmp.identify = 1;
- item_tmp.bound = bound;
+ item_tmp.bound = (unsigned char)bound;
if ((flag = pc->additem(sd, &item_tmp, get_count, LOG_TYPE_COMMAND)))
clif->additem(sd, 0, 0, flag);
@@ -1192,9 +1189,9 @@ ACMD(item2)
if (number <= 0)
number = 1;
- if( bound < 0 || bound > 4 ) {
+ if( bound < IBT_MIN || bound > IBT_MAX ) {
clif->message(fd, msg_txt(298)); // Invalid bound type
- return -1;
+ return false;
}
item_id = 0;
@@ -1225,10 +1222,6 @@ ACMD(item2)
if (refine > MAX_REFINE)
refine = MAX_REFINE;
} else {
- if( bound ) {
- clif->message(fd, msg_txt(499)); // Cannot create bounded stackable items.
- return false;
- }
identify = 1;
refine = attr = 0;
}
@@ -1238,11 +1231,12 @@ ACMD(item2)
item_tmp.identify = identify;
item_tmp.refine = refine;
item_tmp.attribute = attr;
+ item_tmp.bound = (unsigned char)bound;
item_tmp.card[0] = c1;
item_tmp.card[1] = c2;
item_tmp.card[2] = c3;
item_tmp.card[3] = c4;
- item_tmp.bound = bound;
+
if ((flag = pc->additem(sd, &item_tmp, get_count, LOG_TYPE_COMMAND)))
clif->additem(sd, 0, 0, flag);
}
diff --git a/src/map/clif.c b/src/map/clif.c
index 04614158a..fecf0be0e 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -1802,13 +1802,13 @@ void clif_selllist(struct map_session_data *sd)
if( !itemdb_cansell(&sd->status.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)) )
- continue; // Cannot Sell Rental Items or Account Bounded Items
+ if( sd->status.inventory[i].expire_time )
+ continue; // Cannot Sell Rental Items
if( sd->status.inventory[i].bound && !pc->can_give_bounded_items(sd))
continue; // Don't allow sale of bound items
- val=sd->inventory_data[i]->value_sell;
+ val=sd->inventory_data[i]->value_sell;
if( val < 0 )
continue;
WFIFOW(fd,4+c*10)=i+2;
@@ -2232,7 +2232,10 @@ void clif_additem(struct map_session_data *sd, int n, int amount, int fail) {
p.HireExpireDate = sd->status.inventory[n].expire_time;
#endif
#if PACKETVER >= 20071002
- p.bindOnEquipType = sd->status.inventory[n].bound ? 2 : 0;
+ /* why restrict the flag to non-stackable? because this is the only packet allows stackable to,
+ * show the color, and therefore it'd be inconsistent with the rest (aka it'd show yellow, you relog/refresh and boom its gone)
+ */
+ p.bindOnEquipType = sd->status.inventory[n].bound && !itemdb->isstackable2(sd->inventory_data[n]) ? 2 : 0;
#endif
}
p.result = (unsigned char)fail;
@@ -2381,7 +2384,6 @@ void clif_item_normal(short idx, struct NORMALITEM_INFO *p, struct item *i, stru
#if PACKETVER >= 20080102
p->HireExpireDate = i->expire_time;
- p->bindOnEquipType = i->bound ? 2 : 0;
#endif
#if PACKETVER >= 20120925
@@ -15067,8 +15069,8 @@ void clif_parse_Auction_setitem(int fd, struct map_session_data *sd)
if( !pc->can_give_items(sd) || sd->status.inventory[idx].expire_time ||
!sd->status.inventory[idx].identify ||
- !itemdb_canauction(&sd->status.inventory[idx],pc->get_group_level(sd)) ||
- (sd->status.inventory[idx].bound && !pc->can_give_bounded_items(sd)) ) { // Quest Item or something else
+ !itemdb_canauction(&sd->status.inventory[idx],pc->get_group_level(sd)) || // Quest Item or something else
+ (sd->status.inventory[idx].bound && !pc->can_give_bounded_items(sd)) ) {
clif->auction_setitem(sd->fd, idx, true);
return;
}
@@ -15145,13 +15147,11 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd)
return;
}
- // Auction checks...
- if( sd->status.inventory[sd->auction.index].bound && !pc->can_give_bounded_items(sd) ) {
- clif->message(sd->fd, msg_txt(293));
- 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;
}
-
+
if( auction.buynow > battle_config.auction_maximumprice )
{ // Zeny Limits
auction.buynow = battle_config.auction_maximumprice;
@@ -15177,6 +15177,13 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd)
return;
}
+ // Auction checks...
+ if( sd->status.inventory[sd->auction.index].bound && !pc->can_give_bounded_items(sd) ) {
+ clif->message(sd->fd, msg_txt(293));
+ clif->auction_message(fd, 2); // The auction has been canceled
+ return;
+ }
+
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));
diff --git a/src/map/clif.h b/src/map/clif.h
index 710cb6590..cc222d8aa 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -450,6 +450,14 @@ enum e_UNEQUIP_ITEM_ACK {
#endif
};
+enum e_trade_item_ok {
+ TIO_SUCCESS = 0x0,
+ TIO_OVERWEIGHT = 0x1,
+ TIO_CANCEL = 0x2,
+ /* feedback-friendly code that causes the client not to display a error message */
+ TIO_INDROCKS = 0x9,
+};
+
/**
* Structures
**/
diff --git a/src/map/guild.c b/src/map/guild.c
index 719d6bf69..cba568bd8 100644
--- a/src/map/guild.c
+++ b/src/map/guild.c
@@ -866,7 +866,7 @@ int guild_member_withdraw(int guild_id, int account_id, int char_id, int flag, c
if(online_member_sd == NULL)
return 0; // noone online to inform
-#ifdef BOUND_ITEMS
+#ifdef GP_BOUND_ITEMS
//Guild bound item check
guild->retrieveitembound(char_id,account_id,guild_id);
#endif
@@ -904,25 +904,12 @@ int guild_member_withdraw(int guild_id, int account_id, int char_id, int flag, c
return 0;
}
-#ifdef BOUND_ITEMS
-void guild_retrieveitembound(int char_id,int aid,int guild_id)
-{
+void guild_retrieveitembound(int char_id,int aid,int guild_id) {
+#ifdef GP_BOUND_ITEMS
TBL_PC *sd = map->id2sd(aid);
if(sd){ //Character is online
- int idxlist[MAX_INVENTORY];
- int j,i;
- j = pc->bound_chk(sd,2,idxlist);
- if(j) {
- struct guild_storage *gstor = gstorage->id2storage(guild_id);
- for(i=0;i<j;i++) { //Loop the matching items, guild_storage_additem takes care of opening storage
- if(gstor)
- gstorage->additem(sd,gstor,&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);
- }
- gstorage->close(sd); //Close and save the storage
- }
- }
- else { //Character is offline, ask char server to do the job
+ pc->bound_clear(sd,IBT_GUILD);
+ } else { //Character is offline, ask char server to do the job
struct guild_storage *gstor = gstorage->id2storage2(guild_id);
if(gstor && gstor->storage_status == 1) { //Someone is in guild storage, close them
struct s_mapiterator* iter = mapit_getallusers();
@@ -936,8 +923,8 @@ void guild_retrieveitembound(int char_id,int aid,int guild_id)
}
intif->itembound_req(char_id,aid,guild_id);
}
-}
#endif
+}
int guild_send_memberinfoshort(struct map_session_data *sd,int online)
{ // cleaned up [LuzZza]
@@ -1854,11 +1841,6 @@ int guild_break(struct map_session_data *sd,char *name) {
struct unit_data *ud;
int i;
-#ifdef BOUND_ITEMS
- int j;
- int idxlist[MAX_INVENTORY];
-#endif
-
nullpo_ret(sd);
if( (g=sd->guild)==NULL )
@@ -1901,11 +1883,8 @@ int guild_break(struct map_session_data *sd,char *name) {
}
}
-#ifdef BOUND_ITEMS
- //Guild bound item check - Removes the bound flag
- j = pc->bound_chk(sd,2,idxlist);
- for(i=0;i<j;i++)
- sd->status.inventory[idxlist[i]].bound = 0;
+#ifdef GP_BOUND_ITEMS
+ pc->bound_clear(sd,IBT_GUILD);
#endif
intif->guild_break(g->guild_id);
@@ -2380,4 +2359,6 @@ void guild_defaults(void) {
guild->check_member = guild_check_member;
guild->get_alliance_count = guild_get_alliance_count;
guild->castle_reconnect_sub = guild_castle_reconnect_sub;
+ /* */
+ guild->retrieveitembound = guild_retrieveitembound;
}
diff --git a/src/map/guild.h b/src/map/guild.h
index 9326d8d5a..1a04a98ef 100644
--- a/src/map/guild.h
+++ b/src/map/guild.h
@@ -148,9 +148,7 @@ struct guild_interface {
/* guild aura */
void (*aura_refresh) (struct map_session_data *sd, uint16 skill_id, uint16 skill_lv);
/* item bound [Mhalicot]*/
-#ifdef BOUND_ITEMS
void (*retrieveitembound) (int char_id,int aid,int guild_id);
-#endif
/* */
int (*payexp_timer) (int tid, int64 tick, int id, intptr_t data);
TBL_PC* (*sd_check) (int guild_id, int account_id, int char_id);
diff --git a/src/map/intif.c b/src/map/intif.c
index b8b16a356..5cf385fe4 100644
--- a/src/map/intif.c
+++ b/src/map/intif.c
@@ -994,7 +994,6 @@ void intif_parse_LoadGuildStorage(int fd)
ShowError("intif_parse_LoadGuildStorage: user not found %d\n",RFIFOL(fd,4));
return;
}
-
}
gstor=gstorage->id2storage(guild_id);
if(!gstor) {
@@ -1002,12 +1001,12 @@ void intif_parse_LoadGuildStorage(int fd)
return;
}
if (gstor->storage_status == 1) { // 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;
+ ShowWarning("intif_parse_LoadGuildStorage: storage received for a client already open (User %d:%d)\n", flag?sd->status.account_id:0, flag?sd->status.char_id:0);
+ return;
}
if (gstor->dirty) { // Already have storage, and it has been modified and not saved yet! Exploit! [Skotlex]
- 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;
+ ShowWarning("intif_parse_LoadGuildStorage: received storage for an already modified non-saved storage! (User %d:%d)\n", flag?sd->status.account_id:0, flag?sd->status.char_id:0);
+ return;
}
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));
@@ -1017,7 +1016,7 @@ void intif_parse_LoadGuildStorage(int fd)
memcpy(gstor,RFIFOP(fd,13),sizeof(struct guild_storage));
if( flag )
- gstorage->open(sd);
+ gstorage->open(sd);
}
// ACK guild_storage saved
@@ -2013,8 +2012,8 @@ void intif_parse_MessageToFD(int fd) {
/*==========================================
* Item Bound System [Xantara][Mhalicot]
*------------------------------------------*/
-#ifdef BOUND_ITEMS
void intif_itembound_req(int char_id,int aid,int guild_id) {
+#ifdef GP_BOUND_ITEMS
struct guild_storage *gstor = gstorage->id2storage2(guild_id);
WFIFOHEAD(inter_fd,12);
WFIFOW(inter_fd,0) = 0x3056;
@@ -2024,17 +2023,20 @@ void intif_itembound_req(int char_id,int aid,int guild_id) {
WFIFOSET(inter_fd,12);
if(gstor)
gstor->lock = 1; //Lock for retrieval process
+#endif
}
//3856
void intif_parse_Itembound_ack(int fd) {
+#ifdef GP_BOUND_ITEMS
struct guild_storage *gstor;
int guild_id = RFIFOW(fd,6);
gstor = gstorage->id2storage2(guild_id);
- if(gstor) gstor->lock = 0; //Unlock now that operation is completed
-}
+ if(gstor)
+ gstor->lock = 0; //Unlock now that operation is completed
#endif
+}
//-----------------------------------------------------------------
// Communication from the inter server
// Return a 0 (false) if there were any errors.
@@ -2118,9 +2120,9 @@ int intif_parse(int fd)
case 0x3854: intif->pAuctionMessage(fd); break;
case 0x3855: intif->pAuctionBid(fd); break;
//Bound items
-#ifdef BOUND_ITEMS
+#ifdef GP_BOUND_ITEMS
case 0x3856: intif->pItembound_ack(fd); break;
-#endif
+#endif
// Mercenary System
case 0x3870: intif->pMercenaryReceived(fd); break;
case 0x3871: intif->pMercenaryDeleted(fd); break;
@@ -2160,7 +2162,7 @@ void intif_defaults(void) {
10,-1,15, 0, 79,19, 7,-1, 0,-1,-1,-1, 14,67,186,-1, //0x3830
-1, 0, 0,14, 0, 0, 0, 0, -1,74,-1,11, 11,-1, 0, 0, //0x3840
-1,-1, 7, 7, 7,11, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3850 Auctions [Zephyrus] itembound[Akinari]
- -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3860 Quests [Kevin] [Inkfish]
+ -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
-1,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3890 Homunculus [albator]
@@ -2248,6 +2250,8 @@ void intif_defaults(void) {
/* */
intif->CheckForCharServer = CheckForCharServer;
/* */
+ intif->itembound_req = intif_itembound_req;
+ /* parse functions */
intif->pWisMessage = intif_parse_WisMessage;
intif->pWisEnd = intif_parse_WisEnd;
intif->pWisToGM_sub = mapif_parse_WisToGM_sub;
diff --git a/src/map/intif.h b/src/map/intif.h
index 577d58923..5e996b6fe 100644
--- a/src/map/intif.h
+++ b/src/map/intif.h
@@ -75,9 +75,7 @@ struct intif_interface {
int (*guild_emblem) (int guild_id, int len, const char *data);
int (*guild_castle_dataload) (int num, int *castle_ids);
int (*guild_castle_datasave) (int castle_id, int index, int value);
-#ifdef BOUND_ITEMS
void (*itembound_req) (int char_id, int aid, int guild_id);
-#endif
int (*request_petdata) (int account_id, int char_id, int pet_id);
int (*save_petdata) (int account_id, struct s_pet *p);
int (*delete_petdata) (int pet_id);
diff --git a/src/map/mail.c b/src/map/mail.c
index 6b1537d87..76c94879b 100644
--- a/src/map/mail.c
+++ b/src/map/mail.c
@@ -82,9 +82,9 @@ unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount) {
if( amount < 0 || amount > sd->status.inventory[idx].amount )
return 1;
if( !pc->can_give_items(sd) || sd->status.inventory[idx].expire_time ||
- !itemdb_canmail(&sd->status.inventory[idx],pc->get_group_level(sd)) ||
- (sd->status.inventory[idx].bound && !pc->can_give_bounded_items(sd)) )
- return 1;
+ !itemdb_canmail(&sd->status.inventory[idx],pc->get_group_level(sd)) ||
+ (sd->status.inventory[idx].bound && !pc->can_give_bounded_items(sd)) )
+ return 1;
sd->mail.index = idx;
sd->mail.nameid = sd->status.inventory[idx].nameid;
diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h
index e6f68ea4f..813aebee0 100644
--- a/src/map/packets_struct.h
+++ b/src/map/packets_struct.h
@@ -212,7 +212,6 @@ struct NORMALITEM_INFO {
#endif
#if PACKETVER >= 20080102
int HireExpireDate;
- unsigned short bindOnEquipType;
#endif
#if PACKETVER >= 20120925
struct {
diff --git a/src/map/party.c b/src/map/party.c
index 16b9d99f9..0a7467162 100644
--- a/src/map/party.c
+++ b/src/map/party.c
@@ -547,14 +547,10 @@ int party_member_withdraw(int party_id, int account_id, int char_id)
}
if( sd && sd->status.party_id == party_id && sd->status.char_id == char_id ) {
-#ifdef BOUND_ITEMS
- int idxlist[MAX_INVENTORY]; //or malloc to reduce consumtion
- int j,i;
- j = pc->bound_chk(sd,3,idxlist);
- for(i=0;i<j;i++)
- pc->delitem(sd,idxlist[i],sd->status.inventory[idxlist[i]].amount,0,1,LOG_TYPE_OTHER);
+#ifdef GP_BOUND_ITEMS
+ pc->bound_clear(sd,IBT_PARTY);
#endif
- sd->status.party_id = 0;
+ sd->status.party_id = 0;
clif->charnameupdate(sd); //Update name display [Skotlex]
//TODO: hp bars should be cleared too
if( p->instances )
diff --git a/src/map/pc.c b/src/map/pc.c
index 31a38372a..752151888 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -573,7 +573,7 @@ bool pc_can_give_items(struct map_session_data *sd)
*/
bool pc_can_give_bounded_items(struct map_session_data *sd)
{
- return pc->has_permission(sd, PC_PERM_TRADE_BOUNDED);
+ return pc->has_permission(sd, PC_PERM_TRADE_BOUND);
}
/*==========================================
@@ -999,10 +999,6 @@ int pc_isequip(struct map_session_data *sd,int n)
*------------------------------------------*/
bool pc_authok(struct map_session_data *sd, int 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
int64 tick = timer->gettick();
uint32 ip = session[sd->fd]->client_addr;
@@ -1203,12 +1199,9 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
**/
pc->itemcd_do(sd,true);
-#ifdef BOUND_ITEMS
- // Party bound item check
- if(sd->status.party_id == 0 && (j = pc->bound_chk(sd,3,idxlist))) { // Party was deleted while character offline
- for(i=0;i<j;i++)
- pc->delitem(sd,idxlist[i],sd->status.inventory[idxlist[i]].amount,0,1,LOG_TYPE_OTHER);
- }
+#ifdef GP_BOUND_ITEMS
+ if( sd->status.party_id == 0 )
+ pc->bound_clear(sd,IBT_PARTY);
#endif
/* [Ind/Hercules] */
@@ -3962,6 +3955,28 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l
if(sd->weight + w > sd->max_weight)
return 2;
+ if( item_data->bound ) {
+ switch( (enum e_item_bound_type)item_data->bound ) {
+ case IBT_CHARACTER:
+ case IBT_ACCOUNT:
+ break; /* no restrictions */
+ case IBT_PARTY:
+ if( !sd->status.party_id ) {
+ ShowError("pc_additem: can't add party_bound item to character without party!\n");
+ ShowError("pc_additem: %s - x%d %s (%d)\n",sd->status.name,amount,data->jname,data->nameid);
+ return 7;/* need proper code? */
+ }
+ break;
+ case IBT_GUILD:
+ if( !sd->status.guild_id ) {
+ ShowError("pc_additem: can't add guild_bound item to character without guild!\n");
+ ShowError("pc_additem: %s - x%d %s (%d)\n",sd->status.name,amount,data->jname,data->nameid);
+ return 7;/* need proper code? */
+ }
+ break;
+ }
+ }
+
i = MAX_INVENTORY;
if( itemdb->isstackable2(data) && item_data->expire_time == 0 )
@@ -3969,7 +3984,7 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l
for( i = 0; i < MAX_INVENTORY; i++ )
{
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;
sd->status.inventory[i].amount += amount;
@@ -4520,7 +4535,7 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun
return 1;
}
- if( !itemdb_cancartstore(item_data, pc->get_group_level(sd)) || (item_data->bound > 1 && !pc->can_give_bounded_items(sd)))
+ if( !itemdb_cancartstore(item_data, pc->get_group_level(sd)) || (item_data->bound > IBT_ACCOUNT && !pc->can_give_bounded_items(sd)))
{ // Check item trade restrictions [Skotlex]
clif->message (sd->fd, msg_txt(264));
return 1;/* TODO: there is no official response to this? */
@@ -4667,24 +4682,38 @@ int pc_getitemfromcart(struct map_session_data *sd,int idx,int amount)
return flag;
}
- /*==========================================
- * Bound Item Check
- * Type:
- * 1 Account Bound
- * 2 Guild Bound
- * 3 Party Bound
- * 4 Character 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++;
- }
+void pc_bound_clear(struct map_session_data *sd, enum e_item_bound_type type) {
+ int i;
+
+ switch( type ) {
+ /* both restricted to inventory */
+ case IBT_PARTY:
+ case IBT_CHARACTER:
+ for( i = 0; i < MAX_INVENTORY; i++ ){
+ if( sd->status.inventory[i].bound == type ) {
+ pc->delitem(sd,i,sd->status.inventory[i].amount,0,1,LOG_TYPE_OTHER);
+ }
+ }
+ break;
+ case IBT_ACCOUNT:
+ ShowError("Helllo! You reached pc_bound_clear for IBT_ACCOUNT, unfortunately no scenario was expected for this!\n");
+ break;
+ case IBT_GUILD: {
+ struct guild_storage *gstor = gstorage->id2storage(sd->status.guild_id);
+
+ for( i = 0; i < MAX_INVENTORY; i++ ){
+ if(sd->status.inventory[i].bound == type) {
+ if( gstor )
+ gstorage->additem(sd,gstor,&sd->status.inventory[i],sd->status.inventory[i].amount);
+ pc->delitem(sd,i,sd->status.inventory[i].amount,0,1,gstor?LOG_TYPE_GSTORAGE:LOG_TYPE_OTHER);
+ }
+ }
+ if( gstor )
+ gstorage->close(sd);
+ }
+ break;
}
- return j;
+
}
/*==========================================
* Display item stolen msg to player sd
@@ -10366,7 +10395,6 @@ void pc_defaults(void) {
pc->class2idx = pc_class2idx;
pc->get_group_level = pc_get_group_level;
pc->can_give_items = pc_can_give_items;
- pc->bound_chk = pc_bound_chk;
pc->can_give_bounded_items = pc_can_give_bounded_items;
pc->can_use_command = pc_can_use_command;
@@ -10600,4 +10628,6 @@ void pc_defaults(void) {
pc->rental_expire = pc_rental_expire;
pc->scdata_received = pc_scdata_received;
+
+ pc->bound_clear = pc_bound_clear;
}
diff --git a/src/map/pc.h b/src/map/pc.h
index 3645fc599..93463d19b 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -791,9 +791,6 @@ struct pc_interface {
int (*getzeny) (struct map_session_data *sd,int zeny, enum e_log_pick_type type, struct map_session_data *tsd);
int (*delitem) (struct map_session_data *sd,int n,int amount,int type, short reason, e_log_pick_type log_type);
- //Bound items
- int (*bound_chk) (TBL_PC *sd,int type,int *idxlist);
-
// Special Shop System
int (*paycash) (struct map_session_data *sd, int price, int points);
int (*getcash) (struct map_session_data *sd, int cash, int points);
@@ -986,6 +983,8 @@ struct pc_interface {
void (*rental_expire) (struct map_session_data *sd, int i);
void (*scdata_received) (struct map_session_data *sd);
+
+ void (*bound_clear) (struct map_session_data *sd, enum e_item_bound_type type);
};
struct pc_interface *pc;
diff --git a/src/map/pc_groups.c b/src/map/pc_groups.c
index c44e2634a..f95878e97 100644
--- a/src/map/pc_groups.c
+++ b/src/map/pc_groups.c
@@ -417,7 +417,7 @@ void do_init_pc_groups(void) {
{ "disable_pvp", PC_PERM_DISABLE_PVP },
{ "disable_commands_when_dead", PC_PERM_DISABLE_CMD_DEAD },
{ "hchsys_admin", PC_PERM_HCHSYS_ADMIN },
- { "can_trade_bounded", PC_PERM_TRADE_BOUNDED },
+ { "can_trade_bound", PC_PERM_TRADE_BOUND },
};
unsigned char i, len = ARRAYLENGTH(pc_g_defaults);
diff --git a/src/map/pc_groups.h b/src/map/pc_groups.h
index df99b19df..943fb7fa5 100644
--- a/src/map/pc_groups.h
+++ b/src/map/pc_groups.h
@@ -30,7 +30,7 @@ enum e_pc_permission {
PC_PERM_DISABLE_PVP = 0x080000, // #20
PC_PERM_DISABLE_CMD_DEAD = 0x100000,
PC_PERM_HCHSYS_ADMIN = 0x200000,
- PC_PERM_TRADE_BOUNDED = 0x400000,
+ PC_PERM_TRADE_BOUND = 0x400000,
};
// Cached config settings for quick lookup
diff --git a/src/map/script.c b/src/map/script.c
index 6dce018ef..cf3c3fb50 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -3779,6 +3779,17 @@ int script_reload(void) {
return 0;
}
+/* returns name of current function being run, from within the stack [Ind/Hercules] */
+const char *script_getfuncname(struct script_state *st) {
+ struct script_data *data;
+
+ data = &st->stack->stack_data[st->start];
+
+ if( data->type == C_NAME && script->str_data[data->u.num].type == C_FUNC )
+ return script->get_str(data->u.num);
+
+ return NULL;
+}
//-----------------------------------------------------------------------------
// buildin functions
@@ -5763,10 +5774,13 @@ BUILDIN(checkweight2)
/*==========================================
* getitem <item id>,<amount>{,<account ID>};
* getitem "<item name>",<amount>{,<account ID>};
+ *
+ * getitembound <item id>,<amount>,<type>{,<account ID>};
+ * getitembound "<item id>",<amount>,<type>{,<account ID>};
*------------------------------------------*/
BUILDIN(getitem)
{
- int nameid,amount,get_count,i,flag = 0;
+ int nameid,amount,get_count,i,flag = 0, offset = 0;
struct item it;
TBL_PC *sd;
struct script_data *data;
@@ -5778,7 +5792,7 @@ BUILDIN(getitem)
{// "<item name>"
const char *name=script->conv_str(st,data);
if( (item_data = itemdb->search_name(name)) == NULL ){
- ShowError("buildin_getitem: Nonexistant item %s requested.\n", name);
+ ShowError("buildin_%s: Nonexistant item %s requested.\n", script->getfuncname(st), name);
return false; //No item created.
}
nameid=item_data->nameid;
@@ -5790,11 +5804,11 @@ BUILDIN(getitem)
flag = 1;
}
if( nameid <= 0 || !(item_data = itemdb->exists(nameid)) ){
- ShowError("buildin_getitem: Nonexistant item %d requested.\n", nameid);
+ ShowError("buildin_%s: Nonexistant item %d requested.\n", script->getfuncname(st), nameid);
return false; //No item created.
}
} else {
- ShowError("buildin_getitem: invalid data type for argument #1 (%d).", data->type);
+ ShowError("buildin_%s: invalid data type for argument #1 (%d).", script->getfuncname(st), data->type);
return false;
}
@@ -5804,13 +5818,28 @@ BUILDIN(getitem)
memset(&it,0,sizeof(it));
it.nameid=nameid;
+
if(!flag)
it.identify=1;
else
it.identify=itemdb->isidentified2(item_data);
- if( script_hasdata(st,4) )
- sd=map->id2sd(script_getnum(st,4)); // <Account ID>
+ if( !strcmp(script->getfuncname(st),"getitembound") ) {
+ int bound = script_getnum(st,4);
+ if( bound < IBT_MIN || bound > IBT_MAX ) { //Not a correct bound type
+ ShowError("script_getitembound: Not a correct bound type! Type=%d\n",bound);
+ return false;
+ }
+ if( item_data->type == IT_PETEGG || item_data->type == IT_PETARMOR ) {
+ ShowError("script_getitembound: can't bind a pet egg/armor!\n",bound);
+ return false;
+ }
+ it.bound = (unsigned char)bound;
+ offset += 1;
+ }
+
+ if( script_hasdata(st,4+offset) )
+ sd=map->id2sd(script_getnum(st,4+offset)); // <Account ID>
else
sd=script->rid2sd(st); // Attached player
@@ -5842,15 +5871,24 @@ BUILDIN(getitem)
*------------------------------------------*/
BUILDIN(getitem2)
{
- int nameid,amount,get_count,i,flag = 0;
- int iden,ref,attr,c1,c2,c3,c4;
+ int nameid,amount,get_count,i,flag = 0, offset = 0;
+ int iden,ref,attr,c1,c2,c3,c4, bound = 0;
struct item_data *item_data;
struct item item_tmp;
TBL_PC *sd;
struct script_data *data;
- if( script_hasdata(st,11) )
- sd=map->id2sd(script_getnum(st,11)); // <Account ID>
+ if( !strcmp(script->getfuncname(st),"getitembound2") ) {
+ bound = script_getnum(st,11);
+ if( bound < IBT_MIN || bound > IBT_MAX ) { //Not a correct bound type
+ ShowError("script_getitembound2: Not a correct bound type! Type=%d\n",bound);
+ return false;
+ }
+ offset += 1;
+ }
+
+ if( script_hasdata(st,11+offset) )
+ sd=map->id2sd(script_getnum(st,11+offset)); // <Account ID>
else
sd=script->rid2sd(st); // Attached player
@@ -5878,6 +5916,11 @@ BUILDIN(getitem2)
c3=(short)script_getnum(st,9);
c4=(short)script_getnum(st,10);
+ if( bound && (itemdb_type(nameid) == IT_PETEGG || itemdb_type(nameid) == IT_PETARMOR) ) {
+ ShowError("script_getitembound2: can't bind a pet egg/armor!\n",bound);
+ return false;
+ }
+
if(nameid<0) { // Invalide nameid
nameid = -nameid;
flag = 1;
@@ -5907,6 +5950,7 @@ BUILDIN(getitem2)
item_tmp.identify=0;
item_tmp.refine=ref;
item_tmp.attribute=attr;
+ item_tmp.bound=(unsigned char)bound;
item_tmp.card[0]=(short)c1;
item_tmp.card[1]=(short)c2;
item_tmp.card[2]=(short)c3;
@@ -17562,185 +17606,6 @@ BUILDIN(bg_join_team) {
return true;
}
-
-/*==============[Mhalicot]==================
- * getitembound <item id>,<amount>,<type>{,<account ID>};
- * getitembound "<item id>",<amount>,<type>{,<account ID>};
- * Type:
- * 1 - Account Bound
- * 2 - Guild Bound
- * 3 - Party Bound
- * 4 - Character Bound
- *------------------------------------------*/
-BUILDIN(getitembound)
-{
- int nameid, amount, i, flag;
- struct item it;
- struct script_data *data;
- char bound = script_getnum(st,4);
- TBL_PC *sd;
-
- data = script_getdata(st,2);
- get_val(st,data);
- if( data_isstring(data) ) { // "<item name>"
- const char *name = script->conv_str(st,data);
- struct item_data *item_data = itemdb->search_name(name);
- if( item_data == NULL ) {
- ShowError("buildin_getitembound: Nonexistant item %s requested.\n", name);
- return 1; //No item created.
- }
- nameid = item_data->nameid;
- } else if( data_isint(data) ) { // <item id>
- nameid = script->conv_num(st,data);
- if( nameid <= 0 || !itemdb->exists(nameid) ) {
- ShowError("buildin_getitembound: Nonexistant item %d requested.\n", nameid);
- return 1; //No item created.
- }
- } else {
- ShowError("buildin_getitembound: invalid data type for argument #1 (%d).", data->type);
- return 1;
- }
-
- if( itemdb->isstackable(nameid) || itemdb_type(nameid) == IT_PETEGG ) {
- ShowError("buildin_getitembound: invalid item type. Bound only work for non stackeable items (Item %d).", nameid);
- return 1;
- }
-
- if( (amount = script_getnum(st,3)) <= 0)
- return 0; //return if amount <=0, skip the useless iteration
-
- memset(&it,0,sizeof(it));
- it.nameid = nameid;
- it.identify = 1;
- it.bound = bound;
-
- if( bound < 1 || bound > 4) { //Not a correct bound type
- ShowError("script_getitembound: Not a correct bound type! Type=%d\n",bound);
- return 1;
- }
-
- if( script_hasdata(st,5) )
- sd=map->id2sd(script_getnum(st,5)); // Account ID
- else
- sd=script->rid2sd(st); // Attached player
-
- if( sd == NULL ) // no target
- return 0;
-
- for( i = 0; i < amount; i++ ) {
- if( (flag = pc->additem(sd, &it, 1, LOG_TYPE_SCRIPT)) ) {
- clif->additem(sd, 0, 0, flag);
- if( pc->candrop(sd,&it) )
- map->addflooritem(&it,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
- }
- }
-
- return 0;
-}
-
-/*==============[Mhalicot]==================
- * getitembound2 <item id>,<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>,<bound type>;
- * getitembound2 "<item name>",<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>,<bound type>;
- *------------------------------------------*/
-BUILDIN(getitembound2)
-{
- int nameid,amount,get_count,i,flag = 0;
- int iden,ref,attr,c1,c2,c3,c4;
- char bound=0;
- struct item_data *item_data;
- struct item item_tmp;
- TBL_PC *sd;
- struct script_data *data;
-
- bound = script_getnum(st,11);
- if( bound < 1 || bound > 4) { //Not a correct bound type
- ShowError("script_getitembound2: Not a correct bound type! Type=%d\n",bound);
- return 1;
- }
- if( script_hasdata(st,12) )
- sd=map->id2sd(script_getnum(st,12));
- else
- sd=script->rid2sd(st); // Attached player
-
- if( sd == NULL ) // no target
- return true;
-
- data=script_getdata(st,2);
- script->get_val(st,data);
- if( data_isstring(data) ){
- const char *name=script->conv_str(st,data);
- struct item_data *item_data = itemdb->search_name(name);
- if( item_data )
- nameid=item_data->nameid;
- else
- nameid=UNKNOWN_ITEM_ID;
- }else
- nameid=script->conv_num(st,data);
-
- amount=script_getnum(st,3);
- iden=script_getnum(st,4);
- ref=script_getnum(st,5);
- attr=script_getnum(st,6);
- c1=(short)script_getnum(st,7);
- c2=(short)script_getnum(st,8);
- c3=(short)script_getnum(st,9);
- c4=(short)script_getnum(st,10);
-
- if(nameid<0) { // Invalide nameid
- nameid = -nameid;
- flag = 1;
- }
-
- if(nameid > 0) {
- memset(&item_tmp,0,sizeof(item_tmp));
- item_data=itemdb->exists(nameid);
- if (item_data == NULL)
- return -1;
- if(item_data->type==IT_WEAPON || item_data->type==IT_ARMOR){
- if(ref > MAX_REFINE) ref = MAX_REFINE;
- }
- else if(item_data->type==IT_PETEGG) {
- iden = 1;
- ref = 0;
- }
- else {
- iden = 1;
- ref = attr = 0;
- }
-
- item_tmp.nameid=nameid;
- if(!flag)
- item_tmp.identify=iden;
- else if(item_data->type==IT_WEAPON || item_data->type==IT_ARMOR)
- item_tmp.identify=0;
- item_tmp.refine=ref;
- item_tmp.attribute=attr;
- item_tmp.card[0]=(short)c1;
- item_tmp.card[1]=(short)c2;
- item_tmp.card[2]=(short)c3;
- item_tmp.card[3]=(short)c4;
- item_tmp.bound=bound;
-
- //Check if it's stackable.
- if (!itemdb->isstackable(nameid))
- get_count = 1;
- else
- get_count = amount;
-
- for (i = 0; i < amount; i += get_count) {
- // if not pet egg
- if (!pet->create_egg(sd, nameid)) {
- if ((flag = pc->additem(sd, &item_tmp, get_count, LOG_TYPE_SCRIPT))) {
- clif->additem(sd, 0, 0, flag);
- if( pc->candrop(sd,&item_tmp) )
- map->addflooritem(&item_tmp,get_count,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
- }
- }
- }
- }
-
- return true;
-}
/*==============[Mhalicot]==================
* countbound {<type>};
* Creates an array of bounded item IDs
@@ -17749,6 +17614,7 @@ BUILDIN(getitembound2)
* 1 - Account Bound
* 2 - Guild Bound
* 3 - Party Bound
+ * 4 - Character Bound
*------------------------------------------*/
BUILDIN(countbound)
{
@@ -18355,11 +18221,12 @@ void script_parse_builtin(void) {
BUILDIN_DEF(bindatcmd, "ss???"),
BUILDIN_DEF(unbindatcmd, "s"),
BUILDIN_DEF(useatcmd, "s"),
+
/**
- * Item bound [Mhalicot\Hercules]
+ * Item bound [Xantara] [Akinari] [Mhalicot/Hercules]
**/
- BUILDIN_DEF(getitembound,"vii?"),
- BUILDIN_DEF(getitembound2,"viiiiiiiii?"),
+ BUILDIN_DEF2(getitem,"getitembound","vii?"),
+ BUILDIN_DEF2(getitem2,"getitembound2","viiiiiiiii?"),
BUILDIN_DEF(countbound, "?"),
//Quest Log System [Inkfish]
@@ -18652,6 +18519,7 @@ void script_defaults(void) {
script->buildin_mobuseskill_sub = buildin_mobuseskill_sub;
script->cleanfloor_sub = script_cleanfloor_sub;
script->run_func = run_func;
+ script->getfuncname = script_getfuncname;
/* script_config base */
script->config.warn_func_mismatch_argtypes = 1;
diff --git a/src/map/script.h b/src/map/script.h
index 6aebc8a30..a846365dd 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -630,6 +630,7 @@ struct script_interface {
int (*buildin_mobuseskill_sub) (struct block_list *bl, va_list ap);
int (*cleanfloor_sub) (struct block_list *bl, va_list ap);
int (*run_func) (struct script_state *st);
+ const char *(*getfuncname) (struct script_state *st);
};
struct script_interface *script;
diff --git a/src/map/storage.c b/src/map/storage.c
index cffbf23ec..0a2e6d118 100644
--- a/src/map/storage.c
+++ b/src/map/storage.c
@@ -141,7 +141,7 @@ int storage_additem(struct map_session_data* sd, struct item* item_data, int amo
return 1;
}
- if( (item_data->bound > 1) && !pc->can_give_bounded_items(sd) ) {
+ if( item_data->bound > IBT_ACCOUNT && !pc->can_give_bounded_items(sd) ) {
clif->message(sd->fd, msg_txt(294));
return 1;
}
@@ -435,13 +435,13 @@ int guild_storage_additem(struct map_session_data* sd, struct guild_storage* sto
return 1;
}
- if( !itemdb_canguildstore(item_data, pc->get_group_level(sd)) || item_data->expire_time || (item_data->bound && !pc->can_give_bounded_items(sd)) )
+ if( !itemdb_canguildstore(item_data, pc->get_group_level(sd)) || item_data->expire_time )
{ //Check if item is storable. [Skotlex]
clif->message (sd->fd, msg_txt(264));
return 1;
}
- if( (item_data->bound == 1 || item_data->bound > 2) && !pc->can_give_bounded_items(sd) ) {
+ if( item_data->bound && item_data->bound != IBT_GUILD && !pc->can_give_bounded_items(sd) ) {
clif->message(sd->fd, msg_txt(294));
return 1;
}
@@ -531,6 +531,8 @@ int storage_guild_storageadd(struct map_session_data* sd, int index, int amount)
if(gstorage->additem(sd,stor,&sd->status.inventory[index],amount)==0)
pc->delitem(sd,index,amount,0,4,LOG_TYPE_GSTORAGE);
+ else
+ clif->dropitem(sd, index,0);
return 1;
}
diff --git a/src/map/trade.c b/src/map/trade.c
index 7085fdda3..327d19880 100644
--- a/src/map/trade.c
+++ b/src/map/trade.c
@@ -335,7 +335,7 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount)
if( amount == 0 )
{ //Why do this.. ~.~ just send an ack, the item won't display on the trade window.
- clif->tradeitemok(sd, index, 0);
+ clif->tradeitemok(sd, index, TIO_SUCCESS);
return;
}
@@ -354,35 +354,38 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount)
(pc->get_partner(sd) != target_sd || !itemdb_canpartnertrade(item, src_lv, dst_lv)) ) //Can't partner-trade
{
clif->message (sd->fd, msg_txt(260));
- clif->tradeitemok(sd, index+2, 1);
+ clif->tradeitemok(sd, index+2, TIO_INDROCKS);
return;
}
if( item->expire_time )
{ // Rental System
clif->message (sd->fd, msg_txt(260));
- clif->tradeitemok(sd, index+2, 1);
+ clif->tradeitemok(sd, index+2, TIO_INDROCKS);
return;
}
- if( ((item->bound == 1 || item->bound > 2) || (item->bound == 2 && sd->status.guild_id != target_sd->status.guild_id)) && !pc->can_give_bounded_items(sd) ) { // Item Bound
+ if( item->bound &&
+ !( item->bound == IBT_GUILD && sd->status.guild_id == target_sd->status.guild_id ) &&
+ !( item->bound == IBT_PARTY && sd->status.party_id == target_sd->status.party_id )
+ && !pc->can_give_bounded_items(sd) ) {
clif->message(sd->fd, msg_txt(293));
- clif->tradeitemok(sd, index+2, 1);
+ clif->tradeitemok(sd, index+2, TIO_INDROCKS);
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
{
- clif->tradeitemok(sd, index+2, 1);
+ clif->tradeitemok(sd, index+2, TIO_OVERWEIGHT);
return;
}
trade_weight = sd->inventory_data[index]->weight * amount;
if( target_sd->weight + sd->deal.weight + trade_weight > target_sd->max_weight )
{ //fail to add item -- the player was over weighted.
- clif->tradeitemok(sd, index+2, 1);
+ clif->tradeitemok(sd, index+2, TIO_OVERWEIGHT);
return;
}
@@ -402,7 +405,7 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount)
}
sd->deal.weight += trade_weight;
- clif->tradeitemok(sd, index+2, 0); // Return the index as it was received
+ clif->tradeitemok(sd, index+2, TIO_SUCCESS); // Return the index as it was received
clif->tradeadditem(sd, target_sd, index+2, amount);
}
@@ -446,7 +449,7 @@ void trade_tradeok(struct map_session_data *sd) {
return;
}
sd->state.deal_locked = 1;
- clif->tradeitemok(sd, 0, 0);
+ clif->tradeitemok(sd, 0, TIO_SUCCESS);
clif->tradedeal_lock(sd, 0);
clif->tradedeal_lock(target_sd, 1);
}
diff --git a/src/map/vending.c b/src/map/vending.c
index 14a5e64d1..d5e5d1804 100644
--- a/src/map/vending.c
+++ b/src/map/vending.c
@@ -257,7 +257,7 @@ void vending_openvending(struct map_session_data* sd, const char* message, const
|| !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
+ || (sd->status.cart[index].bound && !pc->can_give_bounded_items(sd)) // can't trade bound items w/o permission
|| !itemdb_cantrade(&sd->status.cart[index], pc->get_group_level(sd), pc->get_group_level(sd)) ) // untradeable item
continue;