diff options
Diffstat (limited to 'src/map/party.c')
-rw-r--r-- | src/map/party.c | 210 |
1 files changed, 148 insertions, 62 deletions
diff --git a/src/map/party.c b/src/map/party.c index a3e59c281..26b4bae8b 100644 --- a/src/map/party.c +++ b/src/map/party.c @@ -2,7 +2,7 @@ * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2012-2015 Hercules Dev Team + * Copyright (C) 2012-2016 Hercules Dev Team * Copyright (C) Athena Dev Teams * * Hercules is free software: you can redistribute it and/or modify @@ -58,27 +58,39 @@ struct party_interface *party; * Used when creating/adding people to a party. [Skotlex] *------------------------------------------*/ void party_fill_member(struct party_member* member, struct map_session_data* sd, unsigned int leader) { + nullpo_retv(member); + nullpo_retv(sd); + member->account_id = sd->status.account_id; member->char_id = sd->status.char_id; safestrncpy(member->name, sd->status.name, NAME_LENGTH); - member->class_ = sd->status.class_; + member->class = sd->status.class; member->map = sd->mapindex; member->lv = sd->status.base_level; member->online = 1; member->leader = leader; } -/// Get the member_id of a party member. -/// Return -1 if not in party. -int party_getmemberid(struct party_data* p, struct map_session_data* sd) { + +/** + * Gets the member_id of a party member. + * + * @param p Party data. + * @param sd Member data. + * @return the member_id. + * @retval INDEX_NOT_FOUND if not in party. + */ +int party_getmemberid(struct party_data *p, struct map_session_data *sd) +{ int member_id; - nullpo_retr(-1, p); - if( sd == NULL ) - return -1;// no player + nullpo_retr(INDEX_NOT_FOUND, p); + + if (sd == NULL) + return INDEX_NOT_FOUND; // no player ARR_FIND(0, MAX_PARTY, member_id, p->party.member[member_id].account_id == sd->status.account_id && p->party.member[member_id].char_id == sd->status.char_id); - if( member_id == MAX_PARTY ) - return -1;// not found + if (member_id == MAX_PARTY) + return INDEX_NOT_FOUND; // not found return member_id; } @@ -113,7 +125,8 @@ struct map_session_data *party_sd_check(int party_id, int account_id, int char_i return sd; } -int party_db_final(DBKey key, DBData *data, va_list ap) { +int party_db_final(union DBKey key, struct DBData *data, va_list ap) +{ struct party_data *p; if ((p = DB->data2ptr(data))) { @@ -137,9 +150,8 @@ struct party_data* party_searchname(const char* str) { struct party_data* p; - DBIterator *iter = db_iterator(party->db); - for( p = dbi_first(iter); dbi_exists(iter); p = dbi_next(iter) ) - { + struct DBIterator *iter = db_iterator(party->db); + for (p = dbi_first(iter); dbi_exists(iter); p = dbi_next(iter)) { if( strncmpi(p->party.name,str,NAME_LENGTH) == 0 ) break; } @@ -148,11 +160,14 @@ struct party_data* party_searchname(const char* str) return p; } -int party_create(struct map_session_data *sd,char *name,int item,int item2) +int party_create(struct map_session_data *sd, const char *name,int item,int item2) { struct party_member leader; char tname[NAME_LENGTH]; + nullpo_retr(0, sd); + nullpo_retr(0, name); + safestrncpy(tname, name, NAME_LENGTH); trim(tname); @@ -175,7 +190,8 @@ int party_create(struct map_session_data *sd,char *name,int item,int item2) return 0; } -void party_created(int account_id,int char_id,int fail,int party_id,char *name) { +void party_created(int account_id, int char_id, int fail, int party_id, const char *name) +{ struct map_session_data *sd; sd=map->id2sd(account_id); @@ -218,33 +234,39 @@ int party_recv_noinfo(int party_id, int char_id) { void party_check_state(struct party_data *p) { int i; + nullpo_retv(p); memset(&p->state, 0, sizeof(p->state)); - for (i = 0; i < MAX_PARTY; i ++) { + for (i = 0; i < MAX_PARTY; i++) { if (!p->party.member[i].online) continue; //Those not online shouldn't apart to skill usage and all that. - switch (p->party.member[i].class_) { + switch (p->party.member[i].class) { case JOB_MONK: case JOB_BABY_MONK: case JOB_CHAMPION: + case JOB_SURA: + case JOB_SURA_T: + case JOB_BABY_SURA: p->state.monk = 1; - break; + break; case JOB_STAR_GLADIATOR: p->state.sg = 1; - break; + break; case JOB_SUPER_NOVICE: case JOB_SUPER_BABY: + case JOB_SUPER_NOVICE_E: + case JOB_SUPER_BABY_E: p->state.snovice = 1; - break; + break; case JOB_TAEKWON: p->state.tk = 1; - break; + break; } } } -int party_recv_info(struct party* sp, int char_id) +int party_recv_info(const struct party *sp, int char_id) { struct party_data* p; - struct party_member* member; + const struct party_member *member; struct map_session_data* sd; int removed[MAX_PARTY];// member_id in old data int removed_count = 0; @@ -252,6 +274,7 @@ int party_recv_info(struct party* sp, int char_id) int added_count = 0; int j; int member_id; + int leader_account_id = 0, leader_char_id = 0; nullpo_ret(sp); @@ -265,8 +288,12 @@ int party_recv_info(struct party* sp, int char_id) ARR_FIND(0, MAX_PARTY, i, sp->member[i].account_id == member->account_id && sp->member[i].char_id == member->char_id); - if (i == MAX_PARTY) + if (i == MAX_PARTY) { removed[removed_count++] = member_id; + } else if (member->leader != 0) { + leader_account_id = member->account_id; + leader_char_id = member->char_id; + } } for (member_id = 0; member_id < MAX_PARTY; ++member_id) { member = &sp->member[member_id]; @@ -294,6 +321,7 @@ int party_recv_info(struct party* sp, int char_id) continue;// not online party->member_withdraw(sp->party_id, sd->status.account_id, sd->status.char_id); } + memcpy(&p->party, sp, sizeof(struct party)); memset(&p->state, 0, sizeof(p->state)); memset(&p->data, 0, sizeof(p->data)); @@ -302,6 +330,8 @@ int party_recv_info(struct party* sp, int char_id) if ( member->char_id == 0 ) continue;// empty p->data[member_id].sd = party->sd_check(sp->party_id, member->account_id, member->char_id); + if (member->account_id == leader_account_id && member->char_id == leader_char_id) + p->party.member[member_id].leader = 1; } party->check_state(p); while( added_count > 0 ) { // new in party @@ -325,7 +355,7 @@ int party_recv_info(struct party* sp, int char_id) if( char_id != 0 ) { // requester sd = map->charid2sd(char_id); - if( sd && sd->status.party_id == sp->party_id && party->getmemberid(p,sd) == -1 ) + if (sd != NULL && sd->status.party_id == sp->party_id && party->getmemberid(p,sd) == INDEX_NOT_FOUND) sd->status.party_id = 0;// was not in the party } return 0; @@ -345,7 +375,7 @@ int party_invite(struct map_session_data *sd,struct map_session_data *tsd) ARR_FIND(0, MAX_PARTY, i, p->data[i].sd == sd); if( i == MAX_PARTY || !p->party.member[i].leader ) { - clif->message(sd->fd, msg_sd(sd,282)); + clif->message(sd->fd, msg_sd(sd,282)); // You need to be a party leader to use this command. return 0; } @@ -397,6 +427,8 @@ void party_reply_invite(struct map_session_data *sd,int party_id,int flag) { struct map_session_data* tsd; struct party_member member; + nullpo_retv(sd); + if( sd->party_invite != party_id ) {// forged sd->party_invite = 0; @@ -426,8 +458,11 @@ void party_reply_invite(struct map_session_data *sd,int party_id,int flag) { //- Player must be authed/active and belong to a party before calling this method void party_member_joined(struct map_session_data *sd) { - struct party_data* p = party->search(sd->status.party_id); + struct party_data* p; int i; + + nullpo_retv(sd); + p = party->search(sd->status.party_id); if (!p) { party->request_info(sd->status.party_id, sd->status.char_id); return; @@ -510,7 +545,7 @@ int party_member_added(int party_id,int account_id,int char_id, int flag) { } /// Party member 'sd' requesting kick of member with <account_id, name>. -int party_removemember(struct map_session_data* sd, int account_id, char* name) +int party_removemember(struct map_session_data* sd, int account_id, const char *name) { struct party_data *p; int i; @@ -526,6 +561,7 @@ int party_removemember(struct map_session_data* sd, int account_id, char* name) if( !p->party.member[i].leader ) return 0; // only party leader may remove members + nullpo_retr(0, name); ARR_FIND( 0, MAX_PARTY, i, p->party.member[i].account_id == account_id && strncmp(p->party.member[i].name,name,NAME_LENGTH) == 0 ); if( i == MAX_PARTY ) return 0; // no such char in party @@ -540,6 +576,7 @@ int party_leave(struct map_session_data *sd) struct party_data *p; int i; + nullpo_ret(sd); p = party->search(sd->status.party_id); if( p == NULL ) return 0; @@ -562,11 +599,43 @@ int party_member_withdraw(int party_id, int account_id, int char_id) int i; 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 ) { + bool was_leader = false; + int prev_leader_accountId = 0; + if (p->party.member[i].leader != 0) { + was_leader = true; + prev_leader_accountId = p->party.member[i].account_id; + } + 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--; party->check_state(p); + + if (was_leader) { + int k; + // Member was party leader, try to pick a new leader from online members + ARR_FIND(0, MAX_PARTY, k, p->party.member[k].account_id != 0 && p->party.member[k].online == 1); + + if (k == MAX_PARTY) { + // No online members, get an offline one + ARR_FIND(0, MAX_PARTY, k, p->party.member[k].account_id != 0); + } + + if (k < MAX_PARTY) { + // Update party's leader + p->party.member[k].leader = 1; + + if (p->data[k].sd != NULL) { + /** update members **/ + clif->PartyLeaderChanged(p->data[k].sd, prev_leader_accountId, p->data[k].sd->status.account_id); + } + + //Update info. + intif->party_leaderchange(p->party.party_id, p->party.member[k].account_id, p->party.member[k].char_id); + clif->party_info(p, NULL); + } + } } } @@ -658,12 +727,12 @@ bool party_changeleader(struct map_session_data *sd, struct map_session_data *ts return false; if (!tsd || tsd->status.party_id != sd->status.party_id) { - clif->message(sd->fd, msg_sd(sd,283)); + clif->message(sd->fd, msg_sd(sd,283)); // Target character must be online and in your current party. return false; } if( map->list[sd->bl.m].flag.partylock ) { - clif->message(sd->fd, msg_sd(sd,287)); + clif->message(sd->fd, msg_sd(sd,287)); // You cannot change party leaders in this map. return false; } @@ -675,8 +744,7 @@ bool party_changeleader(struct map_session_data *sd, struct map_session_data *ts return false; //Shouldn't happen if (!p->party.member[mi].leader) { - //Need to be a party leader. - clif->message(sd->fd, msg_sd(sd,282)); + clif->message(sd->fd, msg_sd(sd,282)); // You need to be a party leader to use this command. return false; } @@ -733,6 +801,8 @@ void party_send_movemap(struct map_session_data *sd) { struct party_data *p; + nullpo_retv(sd); + if( sd->status.party_id==0 ) return; @@ -772,6 +842,8 @@ int party_send_logout(struct map_session_data *sd) struct party_data *p; int i; + nullpo_ret(sd); + if(!sd->status.party_id) return 0; @@ -788,12 +860,19 @@ int party_send_logout(struct map_session_data *sd) return 1; } -int party_send_message(struct map_session_data *sd,const char *mes,int len) +int party_send_message(struct map_session_data *sd, const char *mes) { - if(sd->status.party_id==0) + int len; + + nullpo_ret(sd); + nullpo_ret(mes); + + len = (int)strlen(mes); + + if (sd->status.party_id == 0) return 0; - intif->party_message(sd->status.party_id,sd->status.account_id,mes,len); - party->recv_message(sd->status.party_id,sd->status.account_id,mes,len); + intif->party_message(sd->status.party_id, sd->status.account_id, mes, len); + party->recv_message(sd->status.party_id, sd->status.account_id, mes, len); // Chat logging type 'P' / Party Chat logs->chat(LOG_CHAT_PARTY, sd->status.party_id, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, mes); @@ -833,6 +912,8 @@ int party_skill_check(struct map_session_data *sd, int party_id, uint16 skill_id return 0; //Unknown case? } + nullpo_ret(sd); + for(i=0;i<MAX_PARTY;i++){ if ((p_sd = p->data[i].sd) == NULL) continue; @@ -840,15 +921,14 @@ int party_skill_check(struct map_session_data *sd, int party_id, uint16 skill_id continue; switch(skill_id) { case TK_COUNTER: //Increase Triple Attack rate of Monks. - if((p_sd->class_&MAPID_UPPERMASK) == MAPID_MONK - && pc->checkskill(p_sd,MO_TRIPLEATTACK)) { + if ((p_sd->job & MAPID_UPPERMASK) == MAPID_MONK && pc->checkskill(p_sd, MO_TRIPLEATTACK)) { sc_start4(&p_sd->bl,&p_sd->bl,SC_SKILLRATE_UP,100,MO_TRIPLEATTACK, 50+50*skill_lv, //+100/150/200% rate 0,0,skill->get_time(SG_FRIEND, 1)); } break; case MO_COMBOFINISH: //Increase Counter rate of Star Gladiators - if((p_sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR + if ((p_sd->job & MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR && sd->sc.data[SC_COUNTERKICK_READY] && pc->checkskill(p_sd,SG_FRIEND)) { sc_start4(&p_sd->bl,&p_sd->bl,SC_SKILLRATE_UP,100,TK_COUNTER, @@ -861,10 +941,11 @@ int party_skill_check(struct map_session_data *sd, int party_id, uint16 skill_id return 0; } -int party_send_xy_timer(int tid, int64 tick, int id, intptr_t data) { +int party_send_xy_timer(int tid, int64 tick, int id, intptr_t data) +{ + struct DBIterator *iter = db_iterator(party->db); struct party_data* p; - DBIterator *iter = db_iterator(party->db); // for each existing party, for( p = dbi_first(iter); dbi_exists(iter); p = dbi_next(iter) ) { @@ -919,11 +1000,9 @@ int party_exp_share(struct party_data* p, struct block_list* src, unsigned int b { struct map_session_data* sd[MAX_PARTY]; unsigned int i, c; -#ifdef RENEWAL_EXP - unsigned int job_exp_bonus, base_exp_bonus; -#endif nullpo_ret(p); + nullpo_ret(src); // count the number of players eligible for exp sharing for (i = c = 0; i < MAX_PARTY; i++) { @@ -948,21 +1027,7 @@ int party_exp_share(struct party_data* p, struct block_list* src, unsigned int b zeny = (unsigned int) cap_value(zeny * bonus/100, INT_MIN, INT_MAX); } -#ifdef RENEWAL_EXP - base_exp_bonus = base_exp; - job_exp_bonus = job_exp; -#endif - for (i = 0; i < c; i++) { -#ifdef RENEWAL_EXP - struct mob_data *md = BL_CAST(BL_MOB, src); - if (md != NULL && md->db->mexp == 0) { - int rate = pc->level_penalty_mod(md->level - (sd[i])->status.base_level, md->status.race, md->status.mode, 1); - - base_exp = (unsigned int)cap_value(base_exp_bonus * rate / 100, 1, UINT_MAX); - job_exp = (unsigned int)cap_value(job_exp_bonus * rate / 100, 1, UINT_MAX); - } -#endif pc->gainexp(sd[i], src, base_exp, job_exp, false); if (zeny) // zeny from mobs [Valaris] @@ -976,8 +1041,12 @@ int party_share_loot(struct party_data* p, struct map_session_data* sd, struct i { struct map_session_data *target = NULL; int i; + + nullpo_ret(item_data); + if (p && p->party.item&2 && (first_charid || !(battle_config.party_share_type&1))) { + nullpo_ret(sd); //item distribution to party members. if (battle_config.party_share_type&2) { //Round Robin @@ -1039,6 +1108,7 @@ int party_share_loot(struct party_data* p, struct map_session_data* sd, struct i int party_send_dot_remove(struct map_session_data *sd) { + nullpo_ret(sd); if (sd->status.party_id) clif->party_xy_remove(sd); return 0; @@ -1054,6 +1124,7 @@ int party_sub_count(struct block_list *bl, va_list ap) nullpo_ret(bl); Assert_ret(bl->type == BL_PC); sd = BL_UCCAST(BL_PC, bl); + nullpo_ret(sd); if (sd->state.autotrade) return 0; @@ -1128,7 +1199,7 @@ int party_sub_count_chorus(struct block_list *bl, va_list ap) if (battle_config.idle_no_share && pc_isidle(sd)) return 0; - if ( (sd->class_&MAPID_THIRDMASK) != MAPID_MINSTRELWANDERER ) + if ((sd->job & MAPID_THIRDMASK) != MAPID_MINSTRELWANDERER) return 0; return 1; @@ -1166,6 +1237,9 @@ void party_recruit_register(struct map_session_data *sd, short level, const char #ifdef PARTY_RECRUIT struct party_booking_ad_info *pb_ad; + nullpo_retv(sd); + nullpo_retv(notice); + pb_ad = (struct party_booking_ad_info*)idb_get(party->booking_db, sd->status.char_id); if( pb_ad == NULL ) @@ -1196,6 +1270,9 @@ void party_booking_register(struct map_session_data *sd, short level, short mapi struct party_booking_ad_info *pb_ad; int i; + nullpo_retv(sd); + nullpo_retv(job); + pb_ad = (struct party_booking_ad_info*)idb_get(party->booking_db, sd->status.char_id); if( pb_ad == NULL ) { @@ -1229,6 +1306,7 @@ void party_recruit_update(struct map_session_data *sd, const char *notice) { #ifdef PARTY_RECRUIT struct party_booking_ad_info *pb_ad; + nullpo_retv(sd); pb_ad = (struct party_booking_ad_info*)idb_get(party->booking_db, sd->status.char_id); if( pb_ad == NULL ) @@ -1250,6 +1328,9 @@ void party_booking_update(struct map_session_data *sd, short* job) { int i; struct party_booking_ad_info *pb_ad; + nullpo_retv(sd); + nullpo_retv(job); + pb_ad = (struct party_booking_ad_info*)idb_get(party->booking_db, sd->status.char_id); if( pb_ad == NULL ) @@ -1274,8 +1355,9 @@ void party_recruit_search(struct map_session_data *sd, short level, short mapid, int count = 0; struct party_booking_ad_info* result_list[PARTY_BOOKING_RESULTS]; bool more_result = false; - DBIterator* iter = db_iterator(party->booking_db); + struct DBIterator *iter = db_iterator(party->booking_db); + nullpo_retv(sd); memset(result_list, 0, sizeof(result_list)); for( pb_ad = dbi_first(iter); dbi_exists(iter); pb_ad = dbi_next(iter) ) @@ -1305,7 +1387,9 @@ void party_booking_search(struct map_session_data *sd, short level, short mapid, int count = 0; struct party_booking_ad_info* result_list[PARTY_BOOKING_RESULTS]; bool more_result = false; - DBIterator* iter = db_iterator(party->booking_db); + struct DBIterator *iter = db_iterator(party->booking_db); + + nullpo_retv(sd); memset(result_list, 0, sizeof(result_list)); @@ -1342,6 +1426,8 @@ bool party_booking_delete(struct map_session_data *sd) { struct party_booking_ad_info* pb_ad; + nullpo_retr(false, sd); + if((pb_ad = (struct party_booking_ad_info*)idb_get(party->booking_db, sd->status.char_id))!=NULL) { #ifdef PARTY_RECRUIT |