diff --git a/doc/packet_interserv.txt b/doc/packet_interserv.txt index ed698e5f82..baaf043281 100644 --- a/doc/packet_interserv.txt +++ b/doc/packet_interserv.txt @@ -703,16 +703,18 @@ Currently the max packet size is 0xFFFF (see 'WFIFOSET()' in 'src/common/socket. 0x3024 Type: ZI - Structure: .W .L .L .L - index: 0,2,6,10 - len: 14 + Structure: .W .L .L .L .24B .B + index: 0,2,6,10,14,48 + len: 49 parameter: - cmd : packet identification (0x3024) - - party_id - - aid - - cid + - party_id : Party ID + - aid : Account ID + - cid : Character ID + - name : Character Name + - type : Leave (PARTY_MEMBER_WITHDRAW_LEAVE) or kick (PARTY_MEMBER_WITHDRAW_EXPEL) the player desc: - - Request to leave party + - Request to leave party or kick party member 0x3025 Type: ZI @@ -1615,15 +1617,16 @@ Currently the max packet size is 0xFFFF (see 'WFIFOSET()' in 'src/common/socket. 0x3824 Type: IZ - Structure: .W .L .L .L .?B - index: 0,2,6,10,14 - len: 16? + Structure: .W .L .L .L .24B .B + index: 0,2,6,10,14,48 + len: 49 parameter: - cmd : packet identification (0x3824) - - party_ud - - account_id - - char_id - - ? + - party_id : Party ID + - account_id : Account ID + - char_id : Character ID + - name : Character Name + - type : Leaving reason/result desc: - Withdrawal notification party diff --git a/src/char/char.c b/src/char/char.c index a01f47b0b0..95e63aeca7 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -1701,7 +1701,7 @@ int char_delete_char_sql(uint32 char_id){ //Make the character leave the party [Skotlex] if (party_id) - inter_party_leave(party_id, account_id, char_id); + inter_party_leave(party_id, account_id, char_id, name); /* delete char's pet */ //Delete the hatched pet if you have one... diff --git a/src/char/int_party.c b/src/char/int_party.c index 72ea30a336..914691779a 100644 --- a/src/char/int_party.c +++ b/src/char/int_party.c @@ -28,7 +28,7 @@ static DBMap* party_db_; // int party_id -> struct party_data* int mapif_party_broken(int party_id,int flag); int party_check_empty(struct party_data *p); -int mapif_parse_PartyLeave(int fd, int party_id, uint32 account_id, uint32 char_id); +int mapif_parse_PartyLeave(int fd, int party_id, uint32 account_id, uint32 char_id, char *name, enum e_party_member_withdraw type); int party_check_exp_share(struct party_data *p); int mapif_party_optionchanged(int fd,struct party *p, uint32 account_id, int flag); @@ -404,14 +404,16 @@ int mapif_party_optionchanged(int fd,struct party *p,uint32 account_id,int flag) } //Withdrawal notification party -int mapif_party_withdraw(int party_id,uint32 account_id, uint32 char_id) { - unsigned char buf[16]; +int mapif_party_withdraw(int party_id, uint32 account_id, uint32 char_id, char *name, enum e_party_member_withdraw type) { + unsigned char buf[15+NAME_LENGTH]; WBUFW(buf,0) = 0x3824; WBUFL(buf,2) = party_id; WBUFL(buf,6) = account_id; WBUFL(buf,10) = char_id; - chmapif_sendall(buf, 14); + memcpy(WBUFP(buf,14), name, NAME_LENGTH); + WBUFB(buf,14+NAME_LENGTH) = type; + chmapif_sendall(buf,15+NAME_LENGTH); return 0; } @@ -586,7 +588,7 @@ int mapif_parse_PartyChangeOption(int fd,int party_id,uint32 account_id,int exp, } //Request leave party -int mapif_parse_PartyLeave(int fd, int party_id, uint32 account_id, uint32 char_id) +int mapif_parse_PartyLeave(int fd, int party_id, uint32 account_id, uint32 char_id, char *name, enum e_party_member_withdraw type) { struct party_data *p; int i,j=-1; @@ -608,14 +610,15 @@ int mapif_parse_PartyLeave(int fd, int party_id, uint32 account_id, uint32 char_ if (i >= MAX_PARTY) return 0; //Member not found? - mapif_party_withdraw(party_id, account_id, char_id); + mapif_party_withdraw(party_id, account_id, char_id, name, type); if (p->party.member[i].leader){ + // TODO: Official allow 'leaderless' party p->party.member[i].account_id = 0; for (j = 0; j < MAX_PARTY; j++) { if (!p->party.member[j].account_id) continue; - mapif_party_withdraw(party_id, p->party.member[j].account_id, p->party.member[j].char_id); + mapif_party_withdraw(party_id, p->party.member[j].account_id, p->party.member[j].char_id, p->party.member[j].name, type); p->party.member[j].account_id = 0; } //Party gets deleted on the check_empty call below. @@ -775,7 +778,7 @@ int inter_party_parse_frommap(int fd) case 0x3021: mapif_parse_PartyInfo(fd, RFIFOL(fd,2), RFIFOL(fd,6)); break; case 0x3022: mapif_parse_PartyAddMember(fd, RFIFOL(fd,4), (struct party_member*)RFIFOP(fd,8)); break; case 0x3023: mapif_parse_PartyChangeOption(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOW(fd,10), RFIFOW(fd,12)); break; - case 0x3024: mapif_parse_PartyLeave(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); break; + case 0x3024: mapif_parse_PartyLeave(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), (char *)RFIFOP(fd,14), (enum e_party_member_withdraw)RFIFOB(fd,14+NAME_LENGTH)); break; case 0x3025: mapif_parse_PartyChangeMap(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOW(fd,14), RFIFOB(fd,16), RFIFOW(fd,17)); break; case 0x3026: mapif_parse_BreakParty(fd, RFIFOL(fd,2)); break; case 0x3027: mapif_parse_PartyMessage(fd, RFIFOL(fd,4), RFIFOL(fd,8), (char*)RFIFOP(fd,12), RFIFOW(fd,2)-12); break; @@ -788,9 +791,9 @@ int inter_party_parse_frommap(int fd) } //Leave request from the server (for delete character) -int inter_party_leave(int party_id,uint32 account_id, uint32 char_id) +int inter_party_leave(int party_id,uint32 account_id, uint32 char_id, char *name) { - return mapif_parse_PartyLeave(-1,party_id,account_id, char_id); + return mapif_parse_PartyLeave(-1,party_id,account_id, char_id, name, PARTY_MEMBER_WITHDRAW_EXPEL); } int inter_party_CharOnline(uint32 char_id, int party_id) diff --git a/src/char/int_party.h b/src/char/int_party.h index 1a30ef0aed..b75975276a 100644 --- a/src/char/int_party.h +++ b/src/char/int_party.h @@ -19,7 +19,7 @@ struct party; int inter_party_parse_frommap(int fd); int inter_party_sql_init(void); void inter_party_sql_final(void); -int inter_party_leave(int party_id,uint32 account_id, uint32 char_id); +int inter_party_leave(int party_id,uint32 account_id, uint32 char_id, char *name); int inter_party_CharOnline(uint32 char_id, int party_id); int inter_party_CharOffline(uint32 char_id, int party_id); diff --git a/src/char/inter.c b/src/char/inter.c index 592a5ef7af..c529f666de 100644 --- a/src/char/inter.c +++ b/src/char/inter.c @@ -46,7 +46,7 @@ unsigned int party_share_level = 10; int inter_recv_packet_length[] = { -1,-1, 7,-1, -1,13,36, (2+4+4+4+1+NAME_LENGTH), 0,-1, 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, 6, 0, 0, 0, 0, 0, // 3020- Party + -1,10,-1,14, 15+NAME_LENGTH,19, 6,-1, 14,14, 6, 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] diff --git a/src/common/mmo.h b/src/common/mmo.h index 86c40dfced..f82b9e245f 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -838,6 +838,13 @@ enum e_pc_reg_loading { PRL_ALL = 0xFF, }; +enum e_party_member_withdraw { + PARTY_MEMBER_WITHDRAW_LEAVE, ///< /leave + PARTY_MEMBER_WITHDRAW_EXPEL, ///< Kicked + PARTY_MEMBER_WITHDRAW_CANT_LEAVE, ///< TODO: Cannot /leave + PARTY_MEMBER_WITHDRAW_CANT_EXPEL, ///< TODO: Cannot be kicked +}; + // Sanity checks... #if MAX_ZENY > INT_MAX #error MAX_ZENY is too big diff --git a/src/map/clif.c b/src/map/clif.c index 305b36beef..94a388bbe4 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -7401,37 +7401,26 @@ void clif_party_option(struct party_data *p,struct map_session_data *sd,int flag clif_send(buf,packet_len(cmd),&sd->bl,SELF); } +/** + * 0105 .L .24B .B (ZC_DELETE_MEMBER_FROM_GROUP). + * @param sd Send the notification for this player + * @param account_id Account ID of kicked member + * @param name Name of kicked member + * @param result Party leave result @see PARTY_MEMBER_WITHDRAW + * @param target Send target + **/ +void clif_party_withdraw(struct map_session_data *sd, uint32 account_id, const char* name, enum e_party_member_withdraw result, enum send_target target) { + unsigned char buf[2+4+NAME_LENGTH+1]; -/// 0105 .L .24B .B (ZC_DELETE_MEMBER_FROM_GROUP). -/// result: -/// 0 = leave -/// 1 = expel -/// 2 = cannot leave party on this map -/// 3 = cannot expel from party on this map -void clif_party_withdraw(struct party_data* p, struct map_session_data* sd, uint32 account_id, const char* name, int flag) -{ - unsigned char buf[64]; + if (!sd) + return; - nullpo_retv(p); + WBUFW(buf,0) = 0x0105; + WBUFL(buf,2) = account_id; + memcpy(WBUFP(buf,6), name, NAME_LENGTH); + WBUFB(buf,6+NAME_LENGTH) = result; - if(!sd && (flag&0xf0)==0) - { - int i; - ARR_FIND(0,MAX_PARTY,i,p->data[i].sd); - if (i < MAX_PARTY) - sd = p->data[i].sd; - } - - if(!sd) return; - - WBUFW(buf,0)=0x105; - WBUFL(buf,2)=account_id; - memcpy(WBUFP(buf,6),name,NAME_LENGTH); - WBUFB(buf,30)=flag&0x0f; - if((flag&0xf0)==0) - clif_send(buf,packet_len(0x105),&sd->bl,PARTY); - else - clif_send(buf,packet_len(0x105),&sd->bl,SELF); + clif_send(buf, 2+4+NAME_LENGTH+1, &sd->bl, target); } diff --git a/src/map/clif.h b/src/map/clif.h index 1804d5ce24..e96a5cc0f8 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -721,7 +721,7 @@ void clif_party_info(struct party_data* p, struct map_session_data *sd); void clif_party_invite(struct map_session_data *sd,struct map_session_data *tsd); void clif_party_invite_reply(struct map_session_data* sd, const char* nick, enum e_party_invite_reply reply); void clif_party_option(struct party_data *p,struct map_session_data *sd,int flag); -void clif_party_withdraw(struct party_data* p, struct map_session_data* sd, uint32 account_id, const char* name, int flag); +void clif_party_withdraw(struct map_session_data *sd, uint32 account_id, const char* name, enum e_party_member_withdraw result, enum send_target target); void clif_party_message(struct party_data* p, uint32 account_id, const char* mes, int len); void clif_party_xy(struct map_session_data *sd); void clif_party_xy_single(int fd, struct map_session_data *sd); diff --git a/src/map/intif.c b/src/map/intif.c index fb921d2430..59eb4c1c7d 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -27,7 +27,7 @@ static const int packet_len_table[]={ -1,-1,27,-1, -1, 0,37,-1, 10+NAME_LENGTH,-1, 0, 0, 0, 0, 0, 0, //0x3800-0x380f 0, 0, 0, 0, 0, 0, 0, 0, -1,11, 0, 0, 0, 0, 0, 0, //0x3810 - 39,-1,15,15, 14,19, 7,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3820 + 39,-1,15,15, 15+NAME_LENGTH,19, 7,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3820 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,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3850 Auctions [Zephyrus] itembound[Akinari] @@ -620,16 +620,18 @@ int intif_party_changeoption(int party_id,uint32 account_id,int exp,int item) * @param char_id : cid of player to leave * @return 0:char-serv disconected, 1=msg sent */ -int intif_party_leave(int party_id,uint32 account_id, uint32 char_id) +int intif_party_leave(int party_id, uint32 account_id, uint32 char_id, char *name, enum e_party_member_withdraw type) { if (CheckForCharServer()) return 0; - WFIFOHEAD(inter_fd,14); - WFIFOW(inter_fd,0)=0x3024; - WFIFOL(inter_fd,2)=party_id; - WFIFOL(inter_fd,6)=account_id; - WFIFOL(inter_fd,10)=char_id; - WFIFOSET(inter_fd,14); + WFIFOHEAD(inter_fd,15+NAME_LENGTH); + WFIFOW(inter_fd,0) = 0x3024; + WFIFOL(inter_fd,2) = party_id; + WFIFOL(inter_fd,6) = account_id; + WFIFOL(inter_fd,10) = char_id; + memcpy((char *)WFIFOP(inter_fd,14), name, NAME_LENGTH); + WFIFOB(inter_fd,14+NAME_LENGTH) = type; + WFIFOSET(inter_fd,15+NAME_LENGTH); return 1; } @@ -1527,8 +1529,8 @@ int intif_parse_PartyOptionChanged(int fd) int intif_parse_PartyMemberWithdraw(int fd) { if(battle_config.etc_log) - ShowInfo("intif: party member withdraw: Party(%d), Account(%d), Char(%d)\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); - party_member_withdraw(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); + ShowInfo("intif: party member withdraw: Type(%d) Party(%d), Account(%d), Char(%d), Name(%s)\n",RFIFOB(fd,14+NAME_LENGTH),RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),(char*)RFIFOP(fd,14)); + party_member_withdraw(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),(char*)RFIFOP(fd,14),(enum e_party_member_withdraw)RFIFOB(fd,14+NAME_LENGTH)); return 1; } diff --git a/src/map/intif.h b/src/map/intif.h index 5026ba5ff8..19a44cd75f 100644 --- a/src/map/intif.h +++ b/src/map/intif.h @@ -37,7 +37,7 @@ int intif_request_partyinfo(int party_id, uint32 char_id); int intif_party_addmember(int party_id,struct party_member *member); int intif_party_changeoption(int party_id, uint32 account_id, int exp, int item); -int intif_party_leave(int party_id,uint32 account_id, uint32 char_id); +int intif_party_leave(int party_id, uint32 account_id, uint32 char_id, char *name, enum e_party_member_withdraw type); int intif_party_changemap(struct map_session_data *sd, int online); int intif_break_party(int party_id); int intif_party_message(int party_id, uint32 account_id, const char *mes,int len); diff --git a/src/map/party.c b/src/map/party.c index 621e354f7e..f98b45c670 100644 --- a/src/map/party.c +++ b/src/map/party.c @@ -87,7 +87,7 @@ static TBL_PC* party_sd_check(int party_id, uint32 account_id, uint32 char_id) sd->status.party_id = party_id;// auto-join if not in a party if (sd->status.party_id != party_id) { //If player belongs to a different party, kick him out. - intif_party_leave(party_id,account_id,char_id); + intif_party_leave(party_id,account_id,char_id,sd->status.name,PARTY_MEMBER_WITHDRAW_LEAVE); return NULL; } @@ -165,7 +165,7 @@ void party_created(uint32 account_id,uint32 char_id,int fail,int party_id,char * if (!sd || sd->status.char_id != char_id || !sd->party_creating ) { // Character logged off before creation ack? if (!fail) // break up party since player could not be added to it. - intif_party_leave(party_id,account_id,char_id); + intif_party_leave(party_id,account_id,char_id,"",PARTY_MEMBER_WITHDRAW_LEAVE); return; } @@ -309,7 +309,7 @@ int party_recv_info(struct party* sp, uint32 char_id) if( sd == NULL ) continue; // not online - party_member_withdraw(sp->party_id, sd->status.account_id, sd->status.char_id); + party_member_withdraw(sp->party_id, sd->status.account_id, sd->status.char_id, sd->status.name, PARTY_MEMBER_WITHDRAW_LEAVE); } memcpy(&p->party, sp, sizeof(struct party)); @@ -488,7 +488,7 @@ int party_member_added(int party_id,uint32 account_id,uint32 char_id, int flag) if(sd == NULL || sd->status.char_id != char_id || !sd->party_joining ) { if (!flag) //Char logged off before being accepted into party. - intif_party_leave(party_id,account_id,char_id); + intif_party_leave(party_id,account_id,char_id,"",PARTY_MEMBER_WITHDRAW_LEAVE); return 0; } @@ -500,7 +500,7 @@ int party_member_added(int party_id,uint32 account_id,uint32 char_id, int flag) if (!p) { ShowError("party_member_added: party %d not found.\n",party_id); - intif_party_leave(party_id,account_id,char_id); + intif_party_leave(party_id,account_id,char_id,"",PARTY_MEMBER_WITHDRAW_LEAVE); return 0; } @@ -559,7 +559,7 @@ int party_removemember(struct map_session_data* sd, uint32 account_id, char* nam return 0; // no such char in party party_trade_bound_cancel(sd); - intif_party_leave(p->party.party_id,account_id,p->party.member[i].char_id); + intif_party_leave(p->party.party_id,account_id,p->party.member[i].char_id,p->party.member[i].name,PARTY_MEMBER_WITHDRAW_EXPEL); return 1; } @@ -571,7 +571,7 @@ int party_removemember2(struct map_session_data *sd,uint32 char_id,int party_id) return -3; party_trade_bound_cancel(sd); - intif_party_leave(sd->status.party_id,sd->status.account_id,sd->status.char_id); + intif_party_leave(sd->status.party_id,sd->status.account_id,sd->status.char_id,sd->status.name,PARTY_MEMBER_WITHDRAW_EXPEL); return 1; } else { int i; @@ -583,7 +583,7 @@ int party_removemember2(struct map_session_data *sd,uint32 char_id,int party_id) ARR_FIND(0,MAX_PARTY,i,p->party.member[i].char_id == char_id ); if( i >= MAX_PARTY ) return -1; - intif_party_leave(party_id,p->party.member[i].account_id,char_id); + intif_party_leave(party_id,p->party.member[i].account_id,char_id,p->party.member[i].name,PARTY_MEMBER_WITHDRAW_EXPEL); return 1; } } @@ -604,21 +604,21 @@ int party_leave(struct map_session_data *sd) return 0; party_trade_bound_cancel(sd); - intif_party_leave(p->party.party_id,sd->status.account_id,sd->status.char_id); + intif_party_leave(p->party.party_id,sd->status.account_id,sd->status.char_id,sd->status.name,PARTY_MEMBER_WITHDRAW_LEAVE); return 1; } /// Invoked (from char-server) when a party member leaves the party. -int party_member_withdraw(int party_id, uint32 account_id, uint32 char_id) +int party_member_withdraw(int party_id, uint32 account_id, uint32 char_id, char *name, enum e_party_member_withdraw type) { - struct map_session_data* sd = map_id2sd(account_id); + struct map_session_data* sd = map_charid2sd(char_id); struct party_data* p = party_search(party_id); if( p ) { int i; + clif_party_withdraw(party_getavailablesd(p), account_id, name, type, PARTY); ARR_FIND( 0, MAX_PARTY, i, p->party.member[i].account_id == account_id && p->party.member[i].char_id == char_id ); if( i < MAX_PARTY ) { - clif_party_withdraw(p,sd,account_id,p->party.member[i].name,0x0); memset(&p->party.member[i], 0, sizeof(p->party.member[0])); memset(&p->data[i], 0, sizeof(p->data[0])); p->party.count--; @@ -626,7 +626,7 @@ int party_member_withdraw(int party_id, uint32 account_id, uint32 char_id) } } - if( sd && sd->status.party_id == party_id && sd->status.char_id == char_id ) { + if( sd && sd->status.party_id == party_id ) { #ifdef BOUND_ITEMS int idxlist[MAX_INVENTORY]; //or malloc to reduce consumtion int j,i; @@ -673,7 +673,7 @@ int party_broken(int party_id) for( i = 0; i < MAX_PARTY; i++ ) { if( p->data[i].sd != NULL ) { - clif_party_withdraw(p,p->data[i].sd,p->party.member[i].account_id,p->party.member[i].name,0x10); + clif_party_withdraw(p->data[i].sd,p->party.member[i].account_id,p->party.member[i].name,PARTY_MEMBER_WITHDRAW_EXPEL,SELF); p->data[i].sd->status.party_id=0; } } diff --git a/src/map/party.h b/src/map/party.h index cec46c1b98..1249711bca 100644 --- a/src/map/party.h +++ b/src/map/party.h @@ -65,7 +65,7 @@ int party_member_added(int party_id,uint32 account_id,uint32 char_id,int flag); int party_leave(struct map_session_data *sd); int party_removemember(struct map_session_data *sd,uint32 account_id,char *name); int party_removemember2(struct map_session_data *sd,uint32 char_id,int party_id); -int party_member_withdraw(int party_id,uint32 account_id,uint32 char_id); +int party_member_withdraw(int party_id, uint32 account_id, uint32 char_id, char *name, enum e_party_member_withdraw type); int party_reply_invite(struct map_session_data *sd,int party_id,int flag); #define party_add_member(party_id,sd) party_reply_invite(sd,party_id,1) int party_recv_noinfo(int party_id, uint32 char_id); diff --git a/src/map/script.c b/src/map/script.c index ecc29e410f..8d435d9383 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -20591,9 +20591,9 @@ BUILDIN_FUNC(party_destroy) for( j = 0; j < MAX_PARTY; j++ ) { TBL_PC *sd = party->data[j].sd; if(sd) - party_member_withdraw(party->party.party_id,sd->status.account_id,sd->status.char_id); + party_member_withdraw(party->party.party_id,sd->status.account_id,sd->status.char_id,sd->status.name,PARTY_MEMBER_WITHDRAW_LEAVE); else if( party->party.member[j].char_id ) - intif_party_leave(party->party.party_id,party->party.member[j].account_id,party->party.member[j].char_id); + intif_party_leave(party->party.party_id,party->party.member[j].account_id,party->party.member[j].char_id,party->party.member[j].name,PARTY_MEMBER_WITHDRAW_LEAVE); } party_broken(party->party.party_id); script_pushint(st,1);