瀏覽代碼

Updated Convex Mirror to match official behavior (#2506)

* Updated Convex Mirror to match official behavior
* Fixes #2498.
* When a MVP dies it will only show the respawn time once instead of flooding the chat window.
* The Boss icon will now properly display itself when the MVP respawns if the player has already consumed a Convex Mirror.
* Converted some integers to constant values.
* Made use of the other BOSS_INFO packet messages.
* Properly end the status when the player changes maps.
* Small cleanups and updated status change documentation.
Thanks to @esu1214 and @Lemongrass3110!
Aleos 7 年之前
父節點
當前提交
951ff55573
共有 4 個文件被更改,包括 64 次插入29 次删除
  1. 5 2
      doc/status_change.txt
  2. 32 16
      src/map/clif.cpp
  3. 9 1
      src/map/clif.h
  4. 18 10
      src/map/status.c

+ 5 - 2
doc/status_change.txt

@@ -1072,8 +1072,11 @@ SC_ITEMBOOST	(SI_ITEMBOOST)
 	val1: +% Drop
 
 SC_BOSSMAPINFO	(SI_BOSSMAPINFO)
-	desc:
-	val1:
+	desc: Used to display Boss location on minimap
+	val1: Boss game ID
+	val2: Used to keep timer message from spamming chat window
+	val3:
+	val4: Remaining tick
 
 SC_LIFEINSURANCE	(SI_LIFEINSURANCE)
 	desc: Remove death pleanlties

+ 32 - 16
src/map/clif.cpp

@@ -16436,25 +16436,37 @@ void clif_parse_Adopt_reply(int fd, struct map_session_data *sd){
 /// Convex Mirror (ZC_BOSS_INFO).
 /// 0293 <infoType>.B <x>.L <y>.L <minHours>.W <minMinutes>.W <maxHours>.W <maxMinutes>.W <monster name>.51B
 /// infoType:
-///     0 = No boss on this map (BOSS_INFO_NOT).
-///     1 = Boss is alive (position update) (BOSS_INFO_ALIVE).
-///     2 = Boss is alive (initial announce) (BOSS_INFO_ALIVE_WITHMSG).
-///     3 = Boss is dead (BOSS_INFO_DEAD).
-void clif_bossmapinfo(int fd, struct mob_data *md, short flag)
+///     BOSS_INFO_NOT = No boss on this map.
+///     BOSS_INFO_ALIVE = Boss is alive (position update).
+///     BOSS_INFO_ALIVE_WITHMSG = Boss is alive (initial announce).
+///     BOSS_INFO_DEAD = Boss is dead.
+void clif_bossmapinfo(struct map_session_data *sd, struct mob_data *md, enum e_bossmap_info flag)
 {
+	int fd = sd->fd;
+
 	WFIFOHEAD(fd,70);
 	memset(WFIFOP(fd,0),0,70);
 	WFIFOW(fd,0) = 0x293;
 
-	if( md != NULL ) {
-		if( md->bl.prev != NULL ) { // Boss on This Map
-			if( flag ) {
-				WFIFOB(fd,2) = 1;
-				WFIFOL(fd,3) = md->bl.x;
-				WFIFOL(fd,7) = md->bl.y;
-			} else
-				WFIFOB(fd,2) = 2; // First Time
-		} else if (md->spawn_timer != INVALID_TIMER) { // Boss is Dead
+	switch (flag) {
+		case BOSS_INFO_NOT:
+			WFIFOB(fd,2) = BOSS_INFO_NOT;
+			// No data required
+			break; 
+		case BOSS_INFO_ALIVE:
+			WFIFOB(fd,2) = BOSS_INFO_ALIVE;
+			// Update X/Y
+			WFIFOL(fd,3) = md->bl.x;
+			WFIFOL(fd,7) = md->bl.y;
+			break;
+		case BOSS_INFO_ALIVE_WITHMSG:
+			WFIFOB(fd,2) = BOSS_INFO_ALIVE_WITHMSG;
+			// Current X/Y
+			WFIFOL(fd,3) = md->bl.x;
+			WFIFOL(fd,7) = md->bl.y;
+			break;
+		case BOSS_INFO_DEAD:
+		{
 			const struct TimerData * timer_data = get_timer(md->spawn_timer);
 			unsigned int seconds;
 			int hours, minutes;
@@ -16464,13 +16476,17 @@ void clif_bossmapinfo(int fd, struct mob_data *md, short flag)
 			seconds = seconds - (60 * 60 * hours);
 			minutes = seconds / 60;
 
-			WFIFOB(fd,2) = 3;
+			WFIFOB(fd,2) = BOSS_INFO_DEAD;
+			// Add respawn info
 			WFIFOW(fd,11) = hours; // Hours
 			WFIFOW(fd,13) = minutes; // Minutes
 		}
-		safestrncpy(WFIFOCP(fd,19), md->db->jname, NAME_LENGTH);
+			break;
 	}
 
+	if (md != NULL)
+		safestrncpy(WFIFOCP(fd,19), md->db->jname, NAME_LENGTH);
+
 	WFIFOSET(fd,70);
 }
 

+ 9 - 1
src/map/clif.h

@@ -172,6 +172,14 @@ enum e_party_invite_reply {
 	PARTY_REPLY_INVALID_MAPPROPERTY_ME, ///< return=9 : !TODO "Cannot join a party in this map" -> MsgStringTable[1871] (since 20110205)
 };
 
+/// Enum for Convex Mirror (SC_BOSSMAPINFO)
+enum e_bossmap_info {
+	BOSS_INFO_NOT = 0,
+	BOSS_INFO_ALIVE,
+	BOSS_INFO_ALIVE_WITHMSG,
+	BOSS_INFO_DEAD,
+};
+
 #define packet_len(cmd) packet_db[cmd].len
 extern struct s_packet_db packet_db[MAX_PACKET_DB+1];
 extern int packet_db_ack[MAX_ACK_FUNC + 1];
@@ -909,7 +917,7 @@ void clif_Auction_message(int fd, unsigned char flag);
 void clif_Auction_close(int fd, unsigned char flag);
 void clif_parse_Auction_cancelreg(int fd, struct map_session_data *sd);
 
-void clif_bossmapinfo(int fd, struct mob_data *md, short flag);
+void clif_bossmapinfo(struct map_session_data *sd, struct mob_data *md, enum e_bossmap_info flag);
 void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd);
 
 // ADOPTION

+ 18 - 10
src/map/status.c

@@ -9619,14 +9619,14 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 		case SC_BOSSMAPINFO:
 			if( sd != NULL ) {
 				struct mob_data *boss_md = map_getmob_boss(bl->m); // Search for Boss on this Map
-				if( boss_md == NULL || boss_md->bl.prev == NULL ) { // No MVP on this map - MVP is dead
-					clif_bossmapinfo(sd->fd, boss_md, 1);
-					return 0; // No need to start SC
+
+				if( boss_md == NULL ) { // No MVP on this map
+					clif_bossmapinfo(sd, NULL, BOSS_INFO_NOT);
+					return 0;
 				}
 				val1 = boss_md->bl.id;
-				if( (val4 = tick/1000) < 1 )
-					val4 = 1;
 				tick_time = 1000; // [GodLesZ] tick time
+				val4 = tick / tick_time;
 			}
 			break;
 		case SC_HIDING:
@@ -11505,7 +11505,8 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 			}
 			break;
 		case SC_BOSSMAPINFO:
-			clif_bossmapinfo(sd->fd, map_id2boss(sce->val1), 0); // First Message
+			if (sd)
+				clif_bossmapinfo(sd, map_id2boss(sce->val1), BOSS_INFO_ALIVE_WITHMSG); // First Message
 			break;
 		case SC_MERC_HPUP:
 			status_percent_heal(bl, 100, 0); // Recover Full HP
@@ -12827,13 +12828,20 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 	case SC_BOSSMAPINFO:
 		if( sd && --(sce->val4) >= 0 ) {
 			struct mob_data *boss_md = map_id2boss(sce->val1);
-			if( boss_md && sd->bl.m == boss_md->bl.m ) {
-				clif_bossmapinfo(sd->fd, boss_md, 1); // Update X, Y on minimap
-				if (boss_md->bl.prev != NULL) {
-					sc_timer_next(5000 + tick, status_change_timer, bl->id, data);
+
+			if (boss_md) {
+				if (sd->bl.m != boss_md->bl.m) // Not on same map anymore
 					return 0;
+				else if (boss_md->bl.prev != NULL) { // Boss is alive - Update X, Y on minimap
+					sce->val2 = 0;
+					clif_bossmapinfo(sd, boss_md, BOSS_INFO_ALIVE);
+				} else if (boss_md->spawn_timer != INVALID_TIMER && !sce->val2) { // Boss is dead
+					sce->val2 = 1;
+					clif_bossmapinfo(sd, boss_md, BOSS_INFO_DEAD);
 				}
 			}
+			sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+			return 0;
 		}
 		break;