Jelajahi Sumber

Merge pull request #192 from rathena/feature/bindonequip

Official Item BindOnEquip Support
Cydh Ramdh 10 tahun lalu
induk
melakukan
4f1fa38915

+ 8 - 0
conf/battle/items.conf

@@ -98,3 +98,11 @@ item_enabled_npc: yes
 // If yes, undroppable items will be destroyed instead of appearing on the map when a player's inventory is full.
 // Default: yes
 item_flooritem_check: yes
+
+// Set default bound type for item_flag &8 (see db/[pre-]re/item_flag.txt
+// 0 - None
+// 1 - Account
+// 2 - Guild
+// 3 - Party
+// 4 - Character
+default_bind_on_equip: 4

+ 1 - 0
db/import-tmpl/item_flag.txt

@@ -5,4 +5,5 @@
 // 1 - As Dead Branch item (will be logged at `branchlog` table and cannot be used at 'nobranch' mapflag)
 // 2 - As item group container, check player's inventory and weight before consumed
 // 4 - GUID item, cannot be stacked even same or stackable item
+// 8 - Item will be bound item when equipped
 // NOTE: For removing flag by import file, use "-" to remove the flag. Example, 604,-1 will removes flag 1 from Branch_Of_Dead_Tree

+ 1 - 1
db/packet_db.txt

@@ -1057,7 +1057,7 @@ packet_ver: 22
 0x02d0,-1
 0x02d1,-1
 0x02d2,-1
-0x02d3,4
+0x02d3,4,ZC_NOTIFY_BIND_ON_EQUIP,2
 0x02d4,29
 0x02d5,2
 0x02d6,6,viewplayerequip,2

+ 1 - 0
db/pre-re/item_flag.txt

@@ -5,6 +5,7 @@
 // 1 - As Dead Branch item (will be logged at `branchlog` table and cannot be used at 'nobranch' mapflag)
 // 2 - As item group container, check player's inventory and weight before consumed
 // 4 - GUID item, cannot be stacked even same or stackable item
+// 8 - Item will be bound item when equipped
 // NOTE: For removing flag by import file, use "-" to remove the flag. Example, 604,-1 will removes flag 1 from Branch_Of_Dead_Tree
 
 // Logged as Dead Branch item

+ 1 - 0
db/re/item_flag.txt

@@ -5,6 +5,7 @@
 // 1 - As Dead Branch item (will be logged at `branchlog` table and cannot be used at 'nobranch' mapflag)
 // 2 - As item group container, check player's inventory and weight before consumed
 // 4 - GUID item, cannot be stacked even same or stackable item
+// 8 - Item will be bound item when equipped
 // NOTE: For removing flag by import file, use "-" to remove the flag. Example, 604,-1 will removes flag 1 from Branch_Of_Dead_Tree
 
 // Logged as Dead Branch item

+ 1 - 1
src/common/mmo.h

@@ -798,7 +798,7 @@ enum bound_type {
 	BOUND_CHAR, /// 4 - Character Bound
 	BOUND_MAX,
 
-	//BOUND_ONEQUIP = 1, //! TODO
+	BOUND_ONEQUIP = 1, ///< Show notification when item will be bound on equip
 	BOUND_DISPYELLOW = 2, /// Shows the item name in yellow color
 };
 

+ 1 - 0
src/map/battle.c

@@ -7946,6 +7946,7 @@ static const struct _battle_data {
 	{ "snap_dodge",                         &battle_config.snap_dodge,                      0,      0,      1,              },
 	{ "stormgust_knockback",                &battle_config.stormgust_knockback,             1,      0,      1,              },
 	{ "default_fixed_castrate",             &battle_config.default_fixed_castrate,          20,     0,      100,            },
+	{ "default_bind_on_equip",              &battle_config.default_bind_on_equip,           BOUND_CHAR, BOUND_NONE, BOUND_MAX-1, },
 };
 
 #ifndef STATS_OPT_OUT

+ 1 - 0
src/map/battle.h

@@ -580,6 +580,7 @@ extern struct Battle_Config
 	int snap_dodge; // Enable or disable dodging damage snapping away [csnv]
 	int stormgust_knockback;
 	int default_fixed_castrate;
+	int default_bind_on_equip;
 } battle_config;
 
 void do_init_battle(void);

+ 24 - 3
src/map/clif.c

@@ -2253,7 +2253,7 @@ void clif_additem(struct map_session_data *sd, int n, int amount, unsigned char
 #endif
 #if PACKETVER >= 20071002
 		/* Yellow color only for non-stackable item */
-		WFIFOW(fd,offs+27)=(sd->status.inventory[n].bound && !itemdb_isstackable(sd->status.inventory[n].nameid)) ? BOUND_DISPYELLOW : 0;
+		WFIFOW(fd,offs+27)=(sd->status.inventory[n].bound && !itemdb_isstackable(sd->status.inventory[n].nameid)) ? BOUND_DISPYELLOW : sd->inventory_data[n]->flag.bindOnEquip ? BOUND_ONEQUIP : 0;
 #endif
 	}
 
@@ -2322,7 +2322,7 @@ void clif_item_sub_v5(unsigned char *buf, int n, int idx, struct item *it, struc
 		WBUFB(buf,n+13) = it->refine; //refine lvl
 		clif_addcards(WBUFP(buf, n+14), it); //EQUIPSLOTINFO 8B
 		WBUFL(buf,n+22) = it->expire_time;
-		WBUFW(buf,n+26) = it->bound ? BOUND_DISPYELLOW : 0; //bindOnEquipType
+		WBUFW(buf,n+26) = it->bound ? BOUND_DISPYELLOW : id->flag.bindOnEquip ? BOUND_ONEQUIP : 0; //bindOnEquipType
 		WBUFW(buf,n+28) = (id->equip&EQP_VISIBLE) ? id->look : 0;
 		//V5_ITEM_flag
 		WBUFB(buf,n+30) = it->identify; //0x1 IsIdentified
@@ -2359,7 +2359,7 @@ void clif_item_sub(unsigned char *buf, int n, int idx, struct item *it, struct i
 		clif_addcards(WBUFP(buf, n+12), it); //8B
 #if PACKETVER >= 20071002
 		WBUFL(buf,n+20) = it->expire_time;
-		WBUFW(buf,n+24) = it->bound ? BOUND_DISPYELLOW : 0;
+		WBUFW(buf,n+24) = it->bound ? BOUND_DISPYELLOW : id->flag.bindOnEquip ? BOUND_ONEQUIP : 0;
 #endif
 #if PACKETVER >= 20100629
 		WBUFW(buf,n+26) = (id->equip&EQP_VISIBLE) ? id->look : 0;
@@ -17408,6 +17408,26 @@ void clif_crimson_marker(struct map_session_data *sd, struct block_list *bl, boo
 	clif_send(buf, len, &sd->bl, SELF);
 }
 
+/**
+ * 02d3 <index>.W (ZC_NOTIFY_BIND_ON_EQUIP)
+ **/
+void clif_notify_bindOnEquip(struct map_session_data *sd, int n) {
+	struct s_packet_db *info = NULL;
+	int cmd = 0;
+
+	nullpo_retv(sd);
+
+	cmd = packet_db_ack[sd->packet_ver][ZC_NOTIFY_BIND_ON_EQUIP];
+	info = &packet_db[sd->packet_ver][cmd];
+	if (!cmd || !info->len)
+		return;
+
+	WFIFOHEAD(sd->fd, info->len);
+	WFIFOW(sd->fd, 0) = cmd;
+	WFIFOW(sd->fd, info->pos[0]) = n+2;
+	WFIFOSET(sd->fd, info->len);
+}
+
 /// [Ind/Hercules]
 void clif_showscript(struct block_list* bl, const char* message) {
 	char buf[256];
@@ -18105,6 +18125,7 @@ void packetdb_readdb(void)
 		{ "ZC_PERSONAL_INFOMATION_CHN", ZC_PERSONAL_INFOMATION_CHN},
 		{ "ZC_CLEAR_DIALOG", ZC_CLEAR_DIALOG},
 		{ "ZC_C_MARKERINFO", ZC_C_MARKERINFO},
+		{ "ZC_NOTIFY_BIND_ON_EQUIP", ZC_NOTIFY_BIND_ON_EQUIP },
 	};
 	const char *filename[] = { "packet_db.txt", DBIMPORT"/packet_db.txt"};
 	int f;

+ 2 - 0
src/map/clif.h

@@ -47,6 +47,7 @@ enum e_packet_ack {
 	ZC_PERSONAL_INFOMATION_CHN,
 	ZC_CLEAR_DIALOG,
 	ZC_C_MARKERINFO,
+	ZC_NOTIFY_BIND_ON_EQUIP,
 	//add other here
 	MAX_ACK_FUNC //auto upd len
 };
@@ -888,6 +889,7 @@ void clif_showscript(struct block_list* bl, const char* message);
 void clif_party_leaderchanged(struct map_session_data *sd, int prev_leader_aid, int new_leader_aid);
 
 void clif_account_name(int fd, uint32 account_id, const char* accname);
+void clif_notify_bindOnEquip(struct map_session_data *sd, int n);
 
 //void clif_broadcast_obtain_special_item(); ///TODO!
 

+ 1 - 0
src/map/itemdb.c

@@ -919,6 +919,7 @@ static bool itemdb_read_flag(char* fields[], int columns, int current) {
 #ifdef ENABLE_ITEM_GUID
 	if (flag&4 && itemdb_isstackable2(id)) id->flag.guid = set ? 1 : 0;
 #endif
+	if (flag&8) id->flag.bindOnEquip = true;
 
 	return true;
 }

+ 1 - 0
src/map/itemdb.h

@@ -416,6 +416,7 @@ struct item_data
 		unsigned dead_branch : 1; // As dead branch item. Logged at `branchlog` table and cannot be used at 'nobranch' mapflag [Cydh]
 		unsigned group : 1; // As item group container [Cydh]
 		unsigned guid : 1; // This item always be attached with GUID and make it as bound item! [Cydh]
+		bool bindOnEquip; ///< Set item as bound when equipped
 	} flag;
 	struct {// item stacking limitation
 		unsigned short amount;

+ 6 - 0
src/map/pc.c

@@ -9166,6 +9166,12 @@ bool pc_equipitem(struct map_session_data *sd,short n,int req_pos)
 		clif_equipitemack(sd,n,0,0); //Fail
 		return false;
 	}
+
+	if (id->flag.bindOnEquip && !sd->status.inventory[n].bound) {
+		sd->status.inventory[n].bound = (char)battle_config.default_bind_on_equip;
+		clif_notify_bindOnEquip(sd,n);
+	}
+
 	if(pos == EQP_ACC) { //Accesories should only go in one of the two,
 		pos = req_pos&EQP_ACC;
 		if (pos == EQP_ACC) //User specified both slots..