// http://herc.ws/board/topic/11349-partybuff-spb/ #include "common/hercules.h" #include "map/pc.h" #include "map/clif.h" #include "map/party.h" #include "common/nullpo.h" #include "common/socket.h" #include "common/memmgr.h" #include "plugins/HPMHooking.h" #include "common/HPMDataCheck.h" HPExport struct hplugin_info pinfo = { "showbuff", SERVER_TYPE_MAP, "0.2", HPM_VERSION, }; struct player_data { int buff; bool showbuff; }; int status_change_start_post( int retVal, struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int val1, int val2, int val3, int val4, int tick, int flag) { if ( bl->type == BL_PC && retVal > 0 ) { struct map_session_data *sd = BL_CAST( BL_PC, bl ); struct party_data *p; if ( p = party->search(sd->status.party_id )) { struct player_data *ssd = getFromMSD( sd, 0 ); int before_buff = ssd->buff; if ( type == SC_BLESSING ) ssd->buff |= 0x1; if ( type == SC_INC_AGI ) ssd->buff |= 0x2; if ( type == SC_PROTECTWEAPON || type == SC_PROTECTSHIELD || type == SC_PROTECTARMOR || type == SC_PROTECTHELM ) if ( sd->sc.data[SC_PROTECTWEAPON] && sd->sc.data[SC_PROTECTSHIELD] && sd->sc.data[SC_PROTECTARMOR] && sd->sc.data[SC_PROTECTHELM] ) ssd->buff |= 0x4; if ( type == SC_SOULLINK ) ssd->buff |= 0x8; if ( type == SC_DEVOTION ) ssd->buff |= 0x10; if ( before_buff != ssd->buff ) // only send the packet if update the status is newly apply, no need to resend if just renew the status clif->party_info( p, NULL ); } } return retVal; } int status_change_end_post( int retVal, struct block_list *bl, enum sc_type type, int tid, const char *file, int line ) { if ( bl->type == BL_PC && retVal > 0 ) { struct map_session_data *sd = BL_CAST( BL_PC, bl ); struct party_data *p; if ( sd->state.active == 1 ) { // fix map-server crash when player logout if (( p = party->search(sd->status.party_id ))) { struct player_data *ssd = getFromMSD( sd, 0 ); int before_buff = ssd->buff; if ( type == SC_BLESSING ) ssd->buff &= ~0x1; if ( type == SC_INC_AGI ) ssd->buff &= ~0x2; if ( type == SC_PROTECTWEAPON || type == SC_PROTECTSHIELD || type == SC_PROTECTARMOR || type == SC_PROTECTHELM ) if ( sd->sc.data[SC_PROTECTWEAPON] && sd->sc.data[SC_PROTECTSHIELD] && sd->sc.data[SC_PROTECTARMOR] && sd->sc.data[SC_PROTECTHELM] ) ssd->buff &= ~0x4; if ( type == SC_SOULLINK ) ssd->buff &= ~0x8; if ( type == SC_DEVOTION ) ssd->buff &= ~0x10; if ( before_buff != ssd->buff ) // only send the packet if update the status is newly apply, no need to resend if just renew the status clif->party_info( p, NULL ); } } } return retVal; } char *showing_buff( struct map_session_data *sd ) { struct player_data *ssd = getFromMSD( sd, 0 ); char *temp = ""; safesnprintf( temp, NAME_LENGTH, "[%s%s%s%s%s]%s", ( ssd->buff & 0x1 )? "B" : "_", ( ssd->buff & 0x2 )? "A" : "_", ( ssd->buff & 0x4 )? "F" : "_", ( ssd->buff & 0x8 )? "S" : "_", ( ssd->buff & 0x10 )? "+" : "_", sd->status.name ); return temp; } void clif_party_info_overload( struct party_data *p, struct map_session_data *sd ) { struct PACKET_ZC_GROUP_LIST *packet; int i, c; unsigned char buf[sizeof(*packet) + sizeof(struct PACKET_ZC_GROUP_LIST_SUB) * MAX_PARTY]; nullpo_retv(p); memset( buf, 0, sizeof(buf) ); packet = (struct PACKET_ZC_GROUP_LIST *)buf; packet->packetType = partyinfo; memcpy( packet->partyName, p->party.name, NAME_LENGTH ); for ( i = 0, c = 0; i < MAX_PARTY; ++i ) { struct party_member *m = &p->party.member[i]; if ( !m->account_id ) continue; packet->members[c].AID = m->account_id; #if PACKETVER >= 20171207 packet->members[c].GID = m->char_id; #endif memcpy( packet->members[c].playerName, m->name, NAME_LENGTH ); mapindex->getmapname_ext(mapindex_id2name(m->map), packet->members[c].mapName); packet->members[c].leader = (m->leader) ? 0 : 1; packet->members[c].offline = (m->online) ? 0 : 1; #if PACKETVER >= 20170502 packet->members[c].class = m->class; packet->members[c].baseLevel = m->lv; #endif ++c; } packet->packetLen = sizeof(*packet) + c * sizeof( struct PACKET_ZC_GROUP_LIST_SUB ); if ( sd ) { struct player_data *ssd = getFromMSD( sd, 0 ); if ( ssd && ssd->showbuff ) { for ( i = 0, c = 0; i < MAX_PARTY; ++i ) { struct party_member *m = &p->party.member[i]; if ( !m->account_id ) continue; if ( m->online && p->data[i].sd != NULL ) { memcpy(packet->members[c].playerName, showing_buff(p->data[i].sd), NAME_LENGTH); } ++c; } } clif->send( buf, packet->packetLen, &sd->bl, SELF ); } else { int j; for ( j = 0; j < MAX_PARTY; ++j ) { struct party_member *m1 = &p->party.member[j]; if ( !m1 || !m1->account_id ) continue; else { struct map_session_data *tsd = map->id2sd( m1->account_id ); struct player_data *ssd = NULL; if ( !tsd ) continue; ssd = getFromMSD( tsd, 0 ); if ( ssd && ssd->showbuff ) { for ( i = 0, c = 0; i < MAX_PARTY; ++i ) { struct party_member *m = &p->party.member[i]; if ( !m->account_id ) continue; if ( m->online && p->data[i].sd != NULL ) { memcpy(packet->members[c].playerName, showing_buff(p->data[i].sd), NAME_LENGTH); } ++c; } } else { for ( i = 0, c = 0; i < MAX_PARTY; ++i ) { struct party_member *m = &p->party.member[i]; if ( !m->account_id ) continue; memcpy( packet->members[c].playerName, m->name, NAME_LENGTH ); ++c; } } clif->send( buf, packet->packetLen, map->id2bl( m1->account_id ), SELF ); } } } } bool pc_authok_pre( struct map_session_data **sd, int *login_id2, time_t *expiration_time, int *group_id, const struct mmo_charstatus **st, bool *changing_mapservers ) { struct player_data *ssd; CREATE( ssd, struct player_data, true ); ssd->buff = 0; ssd->showbuff = 0; addToMSD( *sd, ssd, 0, true ); return 0; } ACMD(showbuff) { struct player_data *ssd = getFromMSD( sd, 0 ); struct party_data *p = party->search( sd->status.party_id ); if ( ssd->showbuff ) { ssd->showbuff = 0; clif->message( sd->fd, "@showbuff is now turn OFF." ); } else { ssd->showbuff = 1; clif->message( sd->fd, "@showbuff is now turn ON." ); } clif->party_info( p, sd ); return true; } HPExport void plugin_init (void) { addHookPost( status, change_start, status_change_start_post ); addHookPost( status, change_end_, status_change_end_post ); clif->party_info = &clif_party_info_overload; addHookPre( pc, authok, pc_authok_pre ); addAtcommand( "showbuff", showbuff ); }