From 09ca47a3174082b07b95728f54bf53528cb58c49 Mon Sep 17 00:00:00 2001 From: Kenpachi Developer Date: Mon, 30 Dec 2019 16:44:17 +0100 Subject: Changed some data types from unsigned to signed. * Changed all unsigned fields in struct party_data to signed int. * Changed data type of struct party_member->lv to signed int. * Changed parameter lv in inter_party_change_map() function to signed int. * Changed signature of inter_party_change_map() function in HPMHooking files. --- src/char/int_party.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/char/int_party.c') diff --git a/src/char/int_party.c b/src/char/int_party.c index bf680c816..53243e821 100644 --- a/src/char/int_party.c +++ b/src/char/int_party.c @@ -490,7 +490,7 @@ static bool inter_party_leave(int party_id, int account_id, int char_id) } // When member goes to other map or levels up. -static bool inter_party_change_map(int party_id, int account_id, int char_id, unsigned short map, int online, unsigned int lv) +static bool inter_party_change_map(int party_id, int account_id, int char_id, unsigned short map, int online, int lv) { struct party_data *p; int i; -- cgit v1.2.3-60-g2f50 From 76c0b6cee70d9c2a382f6479b34a615f38d02be1 Mon Sep 17 00:00:00 2001 From: Kenpachi Developer Date: Mon, 30 Dec 2019 17:00:18 +0100 Subject: Updated inter_party_check_lv() function. * Improved assignment of p->min_lv and p->max_lv. * Removed unnecessary lv variable. --- src/char/int_party.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'src/char/int_party.c') diff --git a/src/char/int_party.c b/src/char/int_party.c index 53243e821..c8c18ce7f 100644 --- a/src/char/int_party.c +++ b/src/char/int_party.c @@ -46,10 +46,9 @@ struct inter_party_interface *inter_party; static int inter_party_check_lv(struct party_data *p) { int i; - unsigned int lv; nullpo_ret(p); - p->min_lv = UINT_MAX; - p->max_lv = 0; + p->min_lv = MAX_LEVEL; + p->max_lv = 1; for(i=0;iparty.member[i].online || p->party.member[i].char_id == p->family ) continue; - lv=p->party.member[i].lv; - if (lv < p->min_lv) p->min_lv = lv; - if (lv > p->max_lv) p->max_lv = lv; + p->min_lv = min(p->min_lv, p->party.member[i].lv); + p->max_lv = max(p->max_lv, p->party.member[i].lv); } if (p->party.exp && !inter_party->check_exp_share(p)) { -- cgit v1.2.3-60-g2f50 From c3c195193569d41cf85d6d08532ad51e27822476 Mon Sep 17 00:00:00 2001 From: Kenpachi Developer Date: Mon, 30 Dec 2019 17:14:03 +0100 Subject: Updated inter_party_calc_state() function. * inter_party_calc_state() function now calls inter_party_check_lv() function, instead of doing the same things on its own. --- src/char/int_party.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) (limited to 'src/char/int_party.c') diff --git a/src/char/int_party.c b/src/char/int_party.c index c8c18ce7f..09d4abea5 100644 --- a/src/char/int_party.c +++ b/src/char/int_party.c @@ -72,8 +72,6 @@ static void inter_party_calc_state(struct party_data *p) { int i; nullpo_retv(p); - p->min_lv = UINT_MAX; - p->max_lv = 0; p->party.count = p->size = p->family = 0; @@ -100,22 +98,8 @@ static void inter_party_calc_state(struct party_data *p) p->party.member[2].char_id ); } - //max/min levels. - for (i = 0; i < MAX_PARTY; i++) { - unsigned int lv = p->party.member[i].lv; - if (!lv) continue; - if (p->party.member[i].online - && p->party.member[i].char_id != p->family /* In families, the kid is not counted towards exp share rules. */ - ) { - if( lv < p->min_lv ) p->min_lv=lv; - if( p->max_lv < lv ) p->max_lv=lv; - } - } - if (p->party.exp && !inter_party->check_exp_share(p)) { - p->party.exp = 0; //Set off even share. - mapif->party_optionchanged(0, &p->party, 0, 0); - } + inter_party->check_lv(p); } // Save party to mysql -- cgit v1.2.3-60-g2f50 From 2f3b3e5c1dc6e6e18d972d23f6a4f4d056d76999 Mon Sep 17 00:00:00 2001 From: Kenpachi Developer Date: Thu, 2 Jan 2020 20:00:48 +0100 Subject: Added inter_party_is_family_party() function. * This should fix the issue where family share don't work if the family members don't occupy the first slots of the party. * Additionally made inter_party_check_exp_share() function also returning true, if party is in family state, since this state wasn't checked anywhere else and thus may caused misbehaviour, too. --- src/char/int_party.c | 97 +++++++++++++++++++++++++++++++++++++++++++--------- src/char/int_party.h | 1 + 2 files changed, 82 insertions(+), 16 deletions(-) (limited to 'src/char/int_party.c') diff --git a/src/char/int_party.c b/src/char/int_party.c index 09d4abea5..7554287b2 100644 --- a/src/char/int_party.c +++ b/src/char/int_party.c @@ -67,6 +67,84 @@ static int inter_party_check_lv(struct party_data *p) } return 1; } + +/** + * Checks if a party is a family state party. (Family share feature.) + * Conditions for a family state party: + * - All party members have to belong to the same family. Not even offline strangers are allowed. + * So only parties with 2 or 3 members come in question. + * - At least one parent has to be on the same map with the child. + * - Parents within the party have to be level 70 or higher, even when offline. + * + * @param p The party. + * @return The child's char ID on success, otherwise 0. + * + */ +static int inter_party_is_family_party(struct party_data *p) +{ + nullpo_ret(p); + + if (p->size < 2 || p->size > 3 || p->party.count < 2) + return 0; + + int child_id = 0; + + for (int i = 0; i < MAX_PARTY - 1; i++) { + if (p->party.member[i].online == 0) + continue; + + struct mmo_charstatus *char_i = idb_get(chr->char_db_, p->party.member[i].char_id); + + if (char_i == NULL) + continue; + + for (int j = i + 1; j < MAX_PARTY; j++) { + if (p->party.member[j].online == 0) + continue; + + struct mmo_charstatus *char_j = idb_get(chr->char_db_, p->party.member[j].char_id); + + if (char_j == NULL) + continue; + + if (p->party.member[i].map != p->party.member[j].map) + continue; + + if (char_i->char_id == char_j->child && char_j->base_level >= 70) + child_id = char_i->char_id; + + if (char_j->char_id == char_i->child && char_i->base_level >= 70) + child_id = char_j->char_id; + + if (child_id != 0) + break; + } + + if (child_id != 0) + break; + } + + if (child_id != 0 && p->size > 2) { + for (int i = 0; i < MAX_PARTY; i++) { + struct mmo_charstatus *party_member = idb_get(chr->char_db_, p->party.member[i].char_id); + + /// Check if there is a stranger within the party. + if (party_member != NULL && party_member->char_id != child_id && party_member->child != child_id) { + child_id = 0; /// Stranger detected. + break; + } + + /// Check if there is a parents with level lower than 70 within the party. + if (party_member != NULL && party_member->child == child_id && party_member->base_level < 70) { + child_id = 0; /// Parent with level lower than 70 detected. + break; + } + } + } + + return child_id; +} + //Calculates the state of a party. static void inter_party_calc_state(struct party_data *p) { @@ -83,22 +161,8 @@ static void inter_party_calc_state(struct party_data *p) if(p->party.member[i].online) p->party.count++; } - // FIXME[Haru]: What if the occupied positions aren't the first three? It can happen if some party members leave. This is the reason why family sharing some times stops working until you recreate your party - if( p->size == 2 && ( chr->char_child(p->party.member[0].char_id,p->party.member[1].char_id) || chr->char_child(p->party.member[1].char_id,p->party.member[0].char_id) ) ) { - //Child should be able to share with either of their parents [RoM] - if (p->party.member[0].class >= JOB_BABY && p->party.member[0].class <= JOB_SUPER_BABY) //first slot is the child? - p->family = p->party.member[0].char_id; - else - p->family = p->party.member[1].char_id; - } else if( p->size == 3 ) { - //Check Family State. - p->family = chr->char_family( - p->party.member[0].char_id, - p->party.member[1].char_id, - p->party.member[2].char_id - ); - } + p->family = inter_party->is_family_party(p); inter_party->check_lv(p); } @@ -299,7 +363,7 @@ static struct party_data *inter_party_search_partyname(const char *const str) static int inter_party_check_exp_share(struct party_data *const p) { nullpo_ret(p); - return (p->party.count < 2 || p->max_lv - p->min_lv <= party_share_level); + return (p->party.count < 2 || p->family != 0 || p->max_lv - p->min_lv <= party_share_level); } // Is there any member in the party? @@ -694,6 +758,7 @@ void inter_party_defaults(void) inter_party->sql_init = inter_party_sql_init; inter_party->sql_final = inter_party_sql_final; inter_party->check_lv = inter_party_check_lv; + inter_party->is_family_party = inter_party_is_family_party; inter_party->calc_state = inter_party_calc_state; inter_party->tosql = inter_party_tosql; inter_party->fromsql = inter_party_fromsql; diff --git a/src/char/int_party.h b/src/char/int_party.h index 317e901ac..99cf97e55 100644 --- a/src/char/int_party.h +++ b/src/char/int_party.h @@ -52,6 +52,7 @@ struct inter_party_interface { struct party_data *pt; struct DBMap *db; // int party_id -> struct party_data* int (*check_lv) (struct party_data *p); + int (*is_family_party) (struct party_data *p); void (*calc_state) (struct party_data *p); int (*tosql) (struct party *p, int flag, int index); struct party_data* (*fromsql) (int party_id); -- cgit v1.2.3-60-g2f50 From 9b0ab05d657a6cae872beaf630faa8e932758ed1 Mon Sep 17 00:00:00 2001 From: Kenpachi Developer Date: Wed, 5 Feb 2020 01:42:54 +0100 Subject: Replaced various inter_party_check_lv() calls with inter_party_calc_state() calls, to ensure that family state gets updated correctly. --- src/char/int_party.c | 35 ++++++++--------------------------- 1 file changed, 8 insertions(+), 27 deletions(-) (limited to 'src/char/int_party.c') diff --git a/src/char/int_party.c b/src/char/int_party.c index 7554287b2..bdb507612 100644 --- a/src/char/int_party.c +++ b/src/char/int_party.c @@ -454,16 +454,7 @@ static bool inter_party_add_member(int party_id, const struct party_member *memb memcpy(&p->party.member[i], member, sizeof(struct party_member)); p->party.member[i].leader = 0; - if (p->party.member[i].online) p->party.count++; - p->size++; - if (p->size == 2 || p->size == 3) // Check family state. And also accept either of their Parents. [RoM] - inter_party->calc_state(p); - else //Check even share range. - if (member->lv < p->min_lv || member->lv > p->max_lv || p->family) { - if (p->family) p->family = 0; //Family state broken. - inter_party->check_lv(p); - } - + inter_party->calc_state(p); /// Count online/offline members and check family state and even share range. mapif->party_info(-1, &p->party, 0); inter_party->tosql(&p->party, PS_ADDMEMBER, i); @@ -495,7 +486,7 @@ static bool inter_party_change_option(int party_id, int account_id, int exp, int static bool inter_party_leave(int party_id, int account_id, int char_id) { struct party_data *p; - int i,j; + int i; p = inter_party->fromsql(party_id); if( p == NULL ) @@ -516,18 +507,13 @@ static bool inter_party_leave(int party_id, int account_id, int char_id) mapif->party_withdraw(party_id, account_id, char_id); - j = p->party.member[i].lv; if (p->party.member[i].online > 0) { p->party.member[i].online = 0; p->party.count--; } inter_party->tosql(&p->party, PS_DELMEMBER, i); memset(&p->party.member[i], 0, sizeof(struct party_member)); - p->size--; - if (j == p->min_lv || j == p->max_lv || p->family) { - if(p->family) p->family = 0; //Family state broken. - inter_party->check_lv(p); - } + inter_party->calc_state(p); /// Count online/offline members and check family state and even share range. if (inter_party->check_empty(p) == 0) { mapif->party_info(-1, &p->party, 0); @@ -568,7 +554,7 @@ static bool inter_party_change_map(int party_id, int account_id, int char_id, un ) { p->party.member[i].lv = lv; - inter_party->check_lv(p); + inter_party->calc_state(p); /// Count online/offline members and check family state and even share range. } //Send online/offline update. mapif->party_membermoved(&p->party, i); @@ -579,7 +565,7 @@ static bool inter_party_change_map(int party_id, int account_id, int char_id, un p->party.member[i].lv == p->max_lv) { p->party.member[i].lv = lv; - inter_party->check_lv(p); + inter_party->calc_state(p); /// Count online/offline members and check family state and even share range. } else p->party.member[i].lv = lv; //There is no need to send level update to map servers @@ -689,10 +675,7 @@ static int inter_party_CharOnline(int char_id, int party_id) if (p->party.member[i].char_id == char_id) { if (!p->party.member[i].online) { p->party.member[i].online = 1; - p->party.count++; - if (p->party.member[i].lv < p->min_lv || - p->party.member[i].lv > p->max_lv) - inter_party->check_lv(p); + inter_party->calc_state(p); /// Count online/offline members and check family state and even share range. } break; } @@ -734,10 +717,8 @@ static int inter_party_CharOffline(int char_id, int party_id) if(p->party.member[i].char_id == char_id) { p->party.member[i].online = 0; - p->party.count--; - if(p->party.member[i].lv == p->min_lv || - p->party.member[i].lv == p->max_lv) - inter_party->check_lv(p); + inter_party->calc_state(p); /// Count online/offline members and check family state and even share range. + break; } } -- cgit v1.2.3-60-g2f50 From 6fa97e91cf53a4b4ff808760700d810d6b232b98 Mon Sep 17 00:00:00 2001 From: Kenpachi Developer Date: Tue, 14 Jan 2020 19:53:37 +0100 Subject: Applied code style to all modified functions in src/char/int_party.c. --- src/char/int_party.c | 312 ++++++++++++++++++++++++++++----------------------- 1 file changed, 169 insertions(+), 143 deletions(-) (limited to 'src/char/int_party.c') diff --git a/src/char/int_party.c b/src/char/int_party.c index bdb507612..3c3837f0c 100644 --- a/src/char/int_party.c +++ b/src/char/int_party.c @@ -42,29 +42,34 @@ static struct inter_party_interface inter_party_s; struct inter_party_interface *inter_party; -//Updates party's level range and unsets even share if broken. +/** + * Updates party's level range and disables even share if requirements are not fulfilled. + * + * @param p The party. + * @return 0 on failure, 1 on success. + * + **/ static int inter_party_check_lv(struct party_data *p) { - int i; nullpo_ret(p); + p->min_lv = MAX_LEVEL; p->max_lv = 1; - for(i=0;iparty.member[i].online || p->party.member[i].char_id == p->family ) - continue; + + for (int i = 0; i < MAX_PARTY; i++) { + if (p->party.member[i].online == 0 || p->party.member[i].char_id == p->family) + continue; /// If not online OR if it's a family party and this is the child, don't affect exp range. p->min_lv = min(p->min_lv, p->party.member[i].lv); p->max_lv = max(p->max_lv, p->party.member[i].lv); } - if (p->party.exp && !inter_party->check_exp_share(p)) { + if (p->party.exp == 1 && inter_party->check_exp_share(p) == 0) { p->party.exp = 0; mapif->party_optionchanged(0, &p->party, 0, 0); return 0; } + return 1; } @@ -79,7 +84,7 @@ static int inter_party_check_lv(struct party_data *p) * @param p The party. * @return The child's char ID on success, otherwise 0. * - */ + **/ static int inter_party_is_family_party(struct party_data *p) { nullpo_ret(p); @@ -145,20 +150,26 @@ static int inter_party_is_family_party(struct party_data *p) return child_id; } -//Calculates the state of a party. +/** + * Calculates the state of a party. + * + * @param p The party. + * + **/ static void inter_party_calc_state(struct party_data *p) { - int i; nullpo_retv(p); - p->party.count = - p->size = - p->family = 0; - //Check party size - for(i=0;iparty.member[i].lv) continue; + p->party.count = 0; + p->size = 0; + + for (int i = 0; i < MAX_PARTY; i++) { + if (p->party.member[i].lv == 0) /// Is this even possible? [Kenpachi] + continue; + p->size++; - if(p->party.member[i].online) + + if (p->party.member[i].online == 1) p->party.count++; } @@ -359,10 +370,17 @@ static struct party_data *inter_party_search_partyname(const char *const str) return p; } -// Returns whether this party can keep having exp share or not. +/** + * Checks if a party fulfills the requirements to share EXP. + * + * @param p The party. + * @return 1 if party can share EXP, otherwise 0. + * + **/ static int inter_party_check_exp_share(struct party_data *const p) { nullpo_ret(p); + return (p->party.count < 2 || p->family != 0 || p->max_lv - p->min_lv <= party_share_level); } @@ -434,23 +452,32 @@ static struct party_data *inter_party_create(const char *name, int item, int ite return p; } -// Add a player to party request +/** + * Add a player to party request. + * + * @param party_id The ID of the party. + * @param member The member to add. + * @return true on success, otherwise false. + * + **/ static bool inter_party_add_member(int party_id, const struct party_member *member) { - struct party_data *p; - int i; + nullpo_retr(false, member); - nullpo_ret(member); - p = inter_party->fromsql(party_id); - if( p == NULL || p->size == MAX_PARTY ) { + if (party_id < 1) /// Invalid party ID. return false; - } - ARR_FIND( 0, MAX_PARTY, i, p->party.member[i].account_id == 0 ); - if (i == MAX_PARTY) { - // Party full + struct party_data *p = inter_party->fromsql(party_id); + + if (p == NULL) /// Party does not exist. + return false; + + int i; + + ARR_FIND(0, MAX_PARTY, i, p->party.member[i].account_id == 0); + + if (i == MAX_PARTY) /// Party is full. return false; - } memcpy(&p->party.member[i], member, sizeof(struct party_member)); p->party.member[i].leader = 0; @@ -482,100 +509,92 @@ static bool inter_party_change_option(int party_id, int account_id, int exp, int return true; } -//Request leave party +/** + * Leave party request. + * + * @param party_id The ID of the party. + * @param account_id The account ID of the leaving character. + * @param char_id The char ID of the leaving character. + * @return true on success, otherwise false. + * + **/ static bool inter_party_leave(int party_id, int account_id, int char_id) { - struct party_data *p; - int i; + if (party_id < 1) /// Invalid party ID. + return false; - p = inter_party->fromsql(party_id); - if( p == NULL ) - {// Party does not exists? - if( SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", char_db, party_id) ) + struct party_data *p = inter_party->fromsql(party_id); + + if (p == NULL) { /// Party does not exist. + if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", char_db, party_id)) Sql_ShowDebug(inter->sql_handle); + return false; } - for (i = 0; i < MAX_PARTY; i++) { - if(p->party.member[i].account_id == account_id && - p->party.member[i].char_id == char_id) { - break; - } - } - if (i >= MAX_PARTY) - return false; //Member not found? + 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) /// Character not found in party. + return false; mapif->party_withdraw(party_id, account_id, char_id); - if (p->party.member[i].online > 0) { + if (p->party.member[i].online == 1) p->party.member[i].online = 0; - p->party.count--; - } - inter_party->tosql(&p->party, PS_DELMEMBER, i); + memset(&p->party.member[i], 0, sizeof(struct party_member)); inter_party->calc_state(p); /// Count online/offline members and check family state and even share range. + inter_party->tosql(&p->party, PS_DELMEMBER, i); - if (inter_party->check_empty(p) == 0) { + if (inter_party->check_empty(p) == 0) mapif->party_info(-1, &p->party, 0); - } + return true; } -// When member goes to other map or levels up. +/** + * Updates party data if a member changes map or levels up. + * + * @param party_id The ID of the party. + * @param account_id The character's account ID. + * @param char_id The character's char ID. + * @param map The character's map index. + * @param online The character's online state. + * @param lv The character's level. + * @return true on success, otherwise false. + * + **/ static bool inter_party_change_map(int party_id, int account_id, int char_id, unsigned short map, int online, int lv) { - struct party_data *p; - int i; + if (party_id < 1) /// Invalid party ID. + return false; - p = inter_party->fromsql(party_id); - if (p == NULL) + struct party_data *p = inter_party->fromsql(party_id); + + if (p == NULL) /// Party does not exist. return false; - for(i = 0; i < MAX_PARTY && - (p->party.member[i].account_id != account_id || - p->party.member[i].char_id != char_id); i++); + 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) + if (i == MAX_PARTY) /// Character not found in party. return false; if (p->party.member[i].online != online) - { p->party.member[i].online = online; - if (online) - p->party.count++; - else - p->party.count--; - // Even share check situations: Family state (always breaks) - // character logging on/off is max/min level (update level range) - // or character logging on/off has a different level (update level range using new level) - if (p->family || - (p->party.member[i].lv <= p->min_lv || p->party.member[i].lv >= p->max_lv) || - (p->party.member[i].lv != lv && (lv <= p->min_lv || lv >= p->max_lv)) - ) - { - p->party.member[i].lv = lv; - inter_party->calc_state(p); /// Count online/offline members and check family state and even share range. - } - //Send online/offline update. - mapif->party_membermoved(&p->party, i); - } - if (p->party.member[i].lv != lv) { - if(p->party.member[i].lv == p->min_lv || - p->party.member[i].lv == p->max_lv) - { - p->party.member[i].lv = lv; - inter_party->calc_state(p); /// Count online/offline members and check family state and even share range. - } else - p->party.member[i].lv = lv; - //There is no need to send level update to map servers - //since they do nothing with it. - } + if (p->party.member[i].lv != lv) + p->party.member[i].lv = lv; - if (p->party.member[i].map != map) { + if (p->party.member[i].map != map) p->party.member[i].map = map; - mapif->party_membermoved(&p->party, i); - } + + inter_party->calc_state(p); /// Count online/offline members and check family state and even share range. + mapif->party_membermoved(&p->party, i); /// Send online/offline update. + return true; } @@ -639,93 +658,100 @@ static int inter_party_parse_frommap(int fd) return 1; } +/** + * Sets the online state of a charcter within a party to online. + * + * @param char_id The character's char ID. + * @param party_id The ID of the party. + * @return 1 on success, otherwise 0. + * + **/ static int inter_party_CharOnline(int char_id, int party_id) { - struct party_data* p; - int i; - - if( party_id == -1 ) - {// Get party_id from the database + if (party_id == INDEX_NOT_FOUND) { /// Get party_id from the database. char* data; - if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT party_id FROM `%s` WHERE char_id='%d'", char_db, char_id) ) - { + if (SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT party_id FROM `%s` WHERE char_id='%d'", char_db, char_id)) { Sql_ShowDebug(inter->sql_handle); return 0; } - if( SQL_SUCCESS != SQL->NextRow(inter->sql_handle) ) - return 0; //Eh? No party? + if (SQL_SUCCESS != SQL->NextRow(inter->sql_handle)) + return 0; SQL->GetData(inter->sql_handle, 0, &data, NULL); party_id = atoi(data); SQL->FreeResult(inter->sql_handle); } - if (party_id == 0) - return 0; //No party... - p = inter_party->fromsql(party_id); - if(!p) { - ShowError("Character %d's party %d not found!\n", char_id, party_id); + if (party_id == 0) /// Character isn't member of a party. return 0; - } - //Set member online - for(i=0; iparty.member[i].char_id == char_id) { - if (!p->party.member[i].online) { - p->party.member[i].online = 1; - inter_party->calc_state(p); /// Count online/offline members and check family state and even share range. - } - break; - } - } + struct party_data *p = inter_party->fromsql(party_id); + + if (p == NULL) /// Party does not exist. + return 0; + + int i; + + ARR_FIND(0, MAX_PARTY, i, p->party.member[i].char_id == char_id); + + if (i == MAX_PARTY) /// Character not found in party. + return 0; + + p->party.member[i].online = 1; /// Set member online. + inter_party->calc_state(p); /// Count online/offline members and check family state and even share range. + return 1; } +/** + * Sets the online state of a charcter within a party to offline. + * + * @param char_id The character's char ID. + * @param party_id The ID of the party. + * @return 1 on success, otherwise 0. + * + **/ static int inter_party_CharOffline(int char_id, int party_id) { - struct party_data *p=NULL; - int i; - - if( party_id == -1 ) - {// Get guild_id from the database + if (party_id == INDEX_NOT_FOUND) { /// Get party_id from the database. char* data; - if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT party_id FROM `%s` WHERE char_id='%d'", char_db, char_id) ) - { + if (SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT party_id FROM `%s` WHERE char_id='%d'", char_db, char_id)) { Sql_ShowDebug(inter->sql_handle); return 0; } - if( SQL_SUCCESS != SQL->NextRow(inter->sql_handle) ) - return 0; //Eh? No party? + if (SQL_SUCCESS != SQL->NextRow(inter->sql_handle)) + return 0; SQL->GetData(inter->sql_handle, 0, &data, NULL); party_id = atoi(data); SQL->FreeResult(inter->sql_handle); } - if (party_id == 0) - return 0; //No party... - //Character has a party, set character offline and check if they were the only member online - if ((p = inter_party->fromsql(party_id)) == NULL) + if (party_id == 0) /// Character isn't member of a party. return 0; - //Set member offline - for(i=0; i< MAX_PARTY; i++) { - if(p->party.member[i].char_id == char_id) - { - p->party.member[i].online = 0; - inter_party->calc_state(p); /// Count online/offline members and check family state and even share range. + struct party_data *p = inter_party->fromsql(party_id); - break; - } - } + if (p == NULL) /// Party does not exist. + return 0; - if(!p->party.count) - //Parties don't have any data that needs be saved at this point... so just remove it from memory. + int i; + + ARR_FIND(0, MAX_PARTY, i, p->party.member[i].char_id == char_id); + + if (i == MAX_PARTY) /// Character not found in party. + return 0; + + p->party.member[i].online = 0; /// Set member offline. + inter_party->calc_state(p); /// Count online/offline members and check family state and even share range. + + if (p->party.count == 0) /// Parties don't have any data that needs be saved at this point... so just remove it from memory. idb_remove(inter_party->db, party_id); + return 1; } -- cgit v1.2.3-60-g2f50 From 6f61075415a002709f8452eb094d5b9d9b760f78 Mon Sep 17 00:00:00 2001 From: Kenpachi Developer Date: Wed, 5 Feb 2020 04:20:24 +0100 Subject: Added inter_party_del_nonexistent_party() function. --- src/char/int_party.c | 54 +++++++++++++++++++++++++++++++++++++++++++++------- src/char/int_party.h | 1 + 2 files changed, 48 insertions(+), 7 deletions(-) (limited to 'src/char/int_party.c') diff --git a/src/char/int_party.c b/src/char/int_party.c index 3c3837f0c..43661c12e 100644 --- a/src/char/int_party.c +++ b/src/char/int_party.c @@ -252,6 +252,39 @@ static int inter_party_tosql(struct party *p, int flag, int index) return 1; } +/** + * Updates the `char`.`party_id` column and removes party data from memory. + * Sets the party ID of all characters whose party ID matches the passed one to 0. + * Calls idb_remove() to remove party data from memory. + * + * @param party_id The party ID. + * @return 0 on failure, 1 on success. + * + **/ +static int inter_party_del_nonexistent_party(int party_id) +{ + struct SqlStmt *stmt = SQL->StmtMalloc(inter->sql_handle); + + if (stmt == NULL) { + SqlStmt_ShowDebug(stmt); + return 0; + } + + const char *query = "UPDATE `%s` SET `party_id`='0' WHERE `party_id`=?"; + + if (SQL_ERROR == SQL->StmtPrepare(stmt, query, char_db) + || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_UINT32, &party_id, sizeof(party_id)) + || SQL_ERROR == SQL->StmtExecute(stmt)) { + SqlStmt_ShowDebug(stmt); + SQL->StmtFree(stmt); + return 0; + } + + idb_remove(inter_party->db, party_id); + + return 1; +} + // Read party from mysql static struct party_data *inter_party_fromsql(int party_id) { @@ -469,8 +502,10 @@ static bool inter_party_add_member(int party_id, const struct party_member *memb struct party_data *p = inter_party->fromsql(party_id); - if (p == NULL) /// Party does not exist. + if (p == NULL) { /// Party does not exist. + inter_party->del_nonexistent_party(party_id); return false; + } int i; @@ -526,9 +561,7 @@ static bool inter_party_leave(int party_id, int account_id, int char_id) struct party_data *p = inter_party->fromsql(party_id); if (p == NULL) { /// Party does not exist. - if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", char_db, party_id)) - Sql_ShowDebug(inter->sql_handle); - + inter_party->del_nonexistent_party(party_id); return false; } @@ -573,8 +606,10 @@ static bool inter_party_change_map(int party_id, int account_id, int char_id, un struct party_data *p = inter_party->fromsql(party_id); - if (p == NULL) /// Party does not exist. + if (p == NULL) { /// Party does not exist. + inter_party->del_nonexistent_party(party_id); return false; + } int i; @@ -689,8 +724,10 @@ static int inter_party_CharOnline(int char_id, int party_id) struct party_data *p = inter_party->fromsql(party_id); - if (p == NULL) /// Party does not exist. + if (p == NULL) { /// Party does not exist. + inter_party->del_nonexistent_party(party_id); return 0; + } int i; @@ -736,8 +773,10 @@ static int inter_party_CharOffline(int char_id, int party_id) struct party_data *p = inter_party->fromsql(party_id); - if (p == NULL) /// Party does not exist. + if (p == NULL) { /// Party does not exist. + inter_party->del_nonexistent_party(party_id); return 0; + } int i; @@ -768,6 +807,7 @@ void inter_party_defaults(void) inter_party->is_family_party = inter_party_is_family_party; inter_party->calc_state = inter_party_calc_state; inter_party->tosql = inter_party_tosql; + inter_party->del_nonexistent_party = inter_party_del_nonexistent_party; inter_party->fromsql = inter_party_fromsql; inter_party->search_partyname = inter_party_search_partyname; inter_party->check_exp_share = inter_party_check_exp_share; diff --git a/src/char/int_party.h b/src/char/int_party.h index 99cf97e55..e3fdfb2f9 100644 --- a/src/char/int_party.h +++ b/src/char/int_party.h @@ -55,6 +55,7 @@ struct inter_party_interface { int (*is_family_party) (struct party_data *p); void (*calc_state) (struct party_data *p); int (*tosql) (struct party *p, int flag, int index); + int (*del_nonexistent_party) (int party_id); struct party_data* (*fromsql) (int party_id); int (*sql_init) (void); void (*sql_final) (void); -- cgit v1.2.3-60-g2f50