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!
This commit is contained in:
Aleos 2017-10-14 11:45:24 -04:00 committed by GitHub
parent 76923ac506
commit 951ff55573
4 changed files with 64 additions and 29 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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;