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.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src/char/int_party.h') diff --git a/src/char/int_party.h b/src/char/int_party.h index b9a888cca..317e901ac 100644 --- a/src/char/int_party.h +++ b/src/char/int_party.h @@ -38,10 +38,11 @@ enum { }; struct party_data { - struct party party; - unsigned int min_lv, max_lv; - int family; //Is this party a family? if so, this holds the child id. - unsigned char size; //Total size of party. + struct party party; // Party data. + int min_lv; // The lowest base level of all party members. + int max_lv; // The highest base level of all party members. + int family; // Is this party a family? If so, this holds the child's char ID. + int size; // Amount of party members, including offline members. }; /** @@ -66,7 +67,7 @@ struct inter_party_interface { struct party_data *(*create) (const char *name, int item, int item2, const struct party_member *leader); bool (*add_member) (int party_id, const struct party_member *member); bool (*change_option) (int party_id, int account_id, int exp, int item, int map_fd); - bool (*change_map) (int party_id, int account_id, int char_id, unsigned short map, int online, unsigned int lv); + bool (*change_map) (int party_id, int account_id, int char_id, unsigned short map, int online, int lv); bool (*disband) (int party_id); bool (*change_leader) (int party_id, int account_id, int char_id); }; -- cgit v1.2.3-70-g09d2 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.h') 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-70-g09d2 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.h') 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-70-g09d2