summaryrefslogtreecommitdiff
path: root/src/map/party.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/party.c')
-rw-r--r--src/map/party.c210
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