diff --git a/conf/map/battle/party.conf b/conf/map/battle/party.conf index 621ec50f477..8f815ebabe4 100644 --- a/conf/map/battle/party.conf +++ b/conf/map/battle/party.conf @@ -80,3 +80,8 @@ party_even_share_bonus: 0 // Display party name regardless if player is in a guild. // Official servers do not display party name unless the user is in a guild. (Note 1) display_party_name: false + +// What should happen when the party leader leaves the party? +// 0: Leadership is passed to another party member (official) +// 1: Party disbands (eAthena) +party_leader_leave: 0 diff --git a/src/char/char.c b/src/char/char.c index 34a3ea7a887..995bd306566 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -1903,7 +1903,7 @@ static int char_delete_char_sql(int 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, 0); /* 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 8ee03ecc592..06c2879f498 100644 --- a/src/char/int_party.c +++ b/src/char/int_party.c @@ -447,42 +447,54 @@ static bool inter_party_change_option(int party_id, int account_id, int exp, int } //Request leave party -static bool inter_party_leave(int party_id, int account_id, int char_id) +static bool inter_party_leave(int party_id, int account_id, int char_id, int option) { - struct party_data *p; - int i,j; + struct party_data *p = inter_party->fromsql(party_id); - 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) ) + 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)) Sql_ShowDebug(inter->sql_handle); return false; } + int i, j; for (i = 0; i < MAX_PARTY; i++) { - if(p->party.member[i].account_id == account_id && - p->party.member[i].char_id == char_id) { + 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? mapif->party_withdraw(party_id, account_id, char_id); - j = p->party.member[i].lv; - if (p->party.member[i].online > 0) - p->party.count--; - 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); + if (p->party.member[i].leader && option == 1) { + 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); + p->party.member[j].account_id = 0; + } + //Party gets deleted on the check_empty call below. + } else { + if (option == 1) + inter_party->tosql(&p->party, PS_DELMEMBER, i); + j = p->party.member[i].lv; + if (p->party.member[i].online > 0) + p->party.count--; + 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); + } } if (inter_party->check_empty(p) == 0) { - inter_party->tosql(&p->party, PS_DELMEMBER, i); + if (option == 0) + inter_party->tosql(&p->party, PS_DELMEMBER, i); mapif->party_info(-1, &p->party, 0); } return true; diff --git a/src/char/int_party.h b/src/char/int_party.h index b9a888cca45..7cb55f490dc 100644 --- a/src/char/int_party.h +++ b/src/char/int_party.h @@ -60,7 +60,7 @@ struct inter_party_interface { int (*check_exp_share) (struct party_data *p); int (*check_empty) (struct party_data *p); int (*parse_frommap) (int fd); - bool (*leave) (int party_id,int account_id, int char_id); + bool (*leave) (int party_id, int account_id, int char_id, int option); int (*CharOnline) (int char_id, int party_id); int (*CharOffline) (int char_id, int party_id); struct party_data *(*create) (const char *name, int item, int item2, const struct party_member *leader); diff --git a/src/char/mapif.c b/src/char/mapif.c index fb904a46d07..29d45e43ff6 100644 --- a/src/char/mapif.c +++ b/src/char/mapif.c @@ -1390,7 +1390,7 @@ static int mapif_parse_PartyChangeOption(int fd, int party_id, int account_id, i //Request leave party static int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id) { - inter_party->leave(party_id, account_id, char_id); + inter_party->leave(party_id, account_id, char_id, 0); return 0; } diff --git a/src/map/battle.c b/src/map/battle.c index 6fa46a7c711..114792785c2 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -7413,6 +7413,7 @@ static const struct battle_data { { "min_item_buy_price", &battle_config.min_item_buy_price, 1, 0, INT_MAX, }, { "min_item_sell_price", &battle_config.min_item_sell_price, 0, 0, INT_MAX, }, { "display_fake_hp_when_dead", &battle_config.display_fake_hp_when_dead, 1, 0, 1, }, + { "party_leader_leave", &battle_config.party_leader_leave, 0, 0, 1, }, }; static bool battle_set_value_sub(int index, int value) diff --git a/src/map/battle.h b/src/map/battle.h index d2fd92450e6..e15cf1f8dc8 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -576,6 +576,8 @@ struct Battle_Config { int min_item_sell_price; int display_fake_hp_when_dead; + + int party_leader_leave; }; /* criteria for battle_config.idletime_critera */ diff --git a/src/map/intif.c b/src/map/intif.c index 8028d44742d..f51ec01f11d 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -662,7 +662,7 @@ static int intif_party_changeoption(int party_id, int account_id, int exp, int i } // Request to leave party -static int intif_party_leave(int party_id, int account_id, int char_id) +static int intif_party_leave(int party_id, int account_id, int char_id, int option) { if (intif->CheckForCharServer()) return 0; diff --git a/src/map/intif.h b/src/map/intif.h index 425ab1d18a2..7781a99ed8a 100644 --- a/src/map/intif.h +++ b/src/map/intif.h @@ -75,7 +75,7 @@ struct intif_interface { int (*request_partyinfo) (int party_id, int char_id); int (*party_addmember) (int party_id,struct party_member *member); int (*party_changeoption) (int party_id, int account_id, int exp, int item); - int (*party_leave) (int party_id,int account_id, int char_id); + int (*party_leave) (int party_id, int account_id, int char_id, int option); int (*party_changemap) (struct map_session_data *sd, int online); int (*break_party) (int party_id); int (*party_message) (int party_id, int account_id, const char *mes,int len); diff --git a/src/map/party.c b/src/map/party.c index e4fb18c23ba..edd0b298414 100644 --- a/src/map/party.c +++ b/src/map/party.c @@ -122,7 +122,7 @@ static struct map_session_data *party_sd_check(int party_id, int account_id, int 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, battle->bc->party_leader_leave); return NULL; } @@ -204,7 +204,7 @@ static void party_created(int account_id, int char_id, int fail, int party_id, c 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, battle->bc->party_leader_leave); return; } @@ -502,7 +502,7 @@ static int party_member_added(int party_id, int account_id, int char_id, int fla 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, battle->bc->party_leader_leave); return 0; } @@ -514,7 +514,7 @@ static int party_member_added(int party_id, int account_id, int char_id, int fla 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, battle->bc->party_leader_leave); return 0; } @@ -576,7 +576,7 @@ static int party_removemember(struct map_session_data *sd, int account_id, const if( i == MAX_PARTY ) return 0; // no such char in party - 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, battle->bc->party_leader_leave); return 1; } @@ -595,7 +595,7 @@ static int party_leave(struct map_session_data *sd) if( i == MAX_PARTY ) return 0; - 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, battle->bc->party_leader_leave); return 1; } diff --git a/src/plugins/HPMHooking/HPMHooking.Defs.inc b/src/plugins/HPMHooking/HPMHooking.Defs.inc index 7cc5ef2b113..db7de66b952 100644 --- a/src/plugins/HPMHooking/HPMHooking.Defs.inc +++ b/src/plugins/HPMHooking/HPMHooking.Defs.inc @@ -3468,8 +3468,8 @@ typedef int (*HPMHOOK_pre_inter_party_check_empty) (struct party_data **p); typedef int (*HPMHOOK_post_inter_party_check_empty) (int retVal___, struct party_data *p); typedef int (*HPMHOOK_pre_inter_party_parse_frommap) (int *fd); typedef int (*HPMHOOK_post_inter_party_parse_frommap) (int retVal___, int fd); -typedef bool (*HPMHOOK_pre_inter_party_leave) (int *party_id, int *account_id, int *char_id); -typedef bool (*HPMHOOK_post_inter_party_leave) (bool retVal___, int party_id, int account_id, int char_id); +typedef bool (*HPMHOOK_pre_inter_party_leave) (int *party_id, int *account_id, int *char_id, int *option); +typedef bool (*HPMHOOK_post_inter_party_leave) (bool retVal___, int party_id, int account_id, int char_id, int option); typedef int (*HPMHOOK_pre_inter_party_CharOnline) (int *char_id, int *party_id); typedef int (*HPMHOOK_post_inter_party_CharOnline) (int retVal___, int char_id, int party_id); typedef int (*HPMHOOK_pre_inter_party_CharOffline) (int *char_id, int *party_id); @@ -3594,8 +3594,8 @@ typedef int (*HPMHOOK_pre_intif_party_addmember) (int *party_id, struct party_me typedef int (*HPMHOOK_post_intif_party_addmember) (int retVal___, int party_id, struct party_member *member); typedef int (*HPMHOOK_pre_intif_party_changeoption) (int *party_id, int *account_id, int *exp, int *item); typedef int (*HPMHOOK_post_intif_party_changeoption) (int retVal___, int party_id, int account_id, int exp, int item); -typedef int (*HPMHOOK_pre_intif_party_leave) (int *party_id, int *account_id, int *char_id); -typedef int (*HPMHOOK_post_intif_party_leave) (int retVal___, int party_id, int account_id, int char_id); +typedef int (*HPMHOOK_pre_intif_party_leave) (int *party_id, int *account_id, int *char_id, int *option); +typedef int (*HPMHOOK_post_intif_party_leave) (int retVal___, int party_id, int account_id, int char_id, int option); typedef int (*HPMHOOK_pre_intif_party_changemap) (struct map_session_data **sd, int *online); typedef int (*HPMHOOK_post_intif_party_changemap) (int retVal___, struct map_session_data *sd, int online); typedef int (*HPMHOOK_pre_intif_break_party) (int *party_id); diff --git a/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc index 0bd61ba1575..17f2668e6e6 100644 --- a/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc +++ b/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc @@ -9093,15 +9093,15 @@ int HP_inter_party_parse_frommap(int fd) { } return retVal___; } -bool HP_inter_party_leave(int party_id, int account_id, int char_id) { +bool HP_inter_party_leave(int party_id, int account_id, int char_id, int option) { int hIndex = 0; bool retVal___ = false; if (HPMHooks.count.HP_inter_party_leave_pre > 0) { - bool (*preHookFunc) (int *party_id, int *account_id, int *char_id); + bool (*preHookFunc) (int *party_id, int *account_id, int *char_id, int *option); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_inter_party_leave_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_inter_party_leave_pre[hIndex].func; - retVal___ = preHookFunc(&party_id, &account_id, &char_id); + retVal___ = preHookFunc(&party_id, &account_id, &char_id, &option); } if (*HPMforce_return) { *HPMforce_return = false; @@ -9109,13 +9109,13 @@ bool HP_inter_party_leave(int party_id, int account_id, int char_id) { } } { - retVal___ = HPMHooks.source.inter_party.leave(party_id, account_id, char_id); + retVal___ = HPMHooks.source.inter_party.leave(party_id, account_id, char_id, option); } if (HPMHooks.count.HP_inter_party_leave_post > 0) { - bool (*postHookFunc) (bool retVal___, int party_id, int account_id, int char_id); + bool (*postHookFunc) (bool retVal___, int party_id, int account_id, int char_id, int option); for (hIndex = 0; hIndex < HPMHooks.count.HP_inter_party_leave_post; hIndex++) { postHookFunc = HPMHooks.list.HP_inter_party_leave_post[hIndex].func; - retVal___ = postHookFunc(retVal___, party_id, account_id, char_id); + retVal___ = postHookFunc(retVal___, party_id, account_id, char_id, option); } } return retVal___; diff --git a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc index 8242b979798..755f8a13102 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc @@ -36612,15 +36612,15 @@ int HP_intif_party_changeoption(int party_id, int account_id, int exp, int item) } return retVal___; } -int HP_intif_party_leave(int party_id, int account_id, int char_id) { +int HP_intif_party_leave(int party_id, int account_id, int char_id, int option) { int hIndex = 0; int retVal___ = 0; if (HPMHooks.count.HP_intif_party_leave_pre > 0) { - int (*preHookFunc) (int *party_id, int *account_id, int *char_id); + int (*preHookFunc) (int *party_id, int *account_id, int *char_id, int *option); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_intif_party_leave_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_intif_party_leave_pre[hIndex].func; - retVal___ = preHookFunc(&party_id, &account_id, &char_id); + retVal___ = preHookFunc(&party_id, &account_id, &char_id, &option); } if (*HPMforce_return) { *HPMforce_return = false; @@ -36628,13 +36628,13 @@ int HP_intif_party_leave(int party_id, int account_id, int char_id) { } } { - retVal___ = HPMHooks.source.intif.party_leave(party_id, account_id, char_id); + retVal___ = HPMHooks.source.intif.party_leave(party_id, account_id, char_id, option); } if (HPMHooks.count.HP_intif_party_leave_post > 0) { - int (*postHookFunc) (int retVal___, int party_id, int account_id, int char_id); + int (*postHookFunc) (int retVal___, int party_id, int account_id, int char_id, int option); for (hIndex = 0; hIndex < HPMHooks.count.HP_intif_party_leave_post; hIndex++) { postHookFunc = HPMHooks.list.HP_intif_party_leave_post[hIndex].func; - retVal___ = postHookFunc(retVal___, party_id, account_id, char_id); + retVal___ = postHookFunc(retVal___, party_id, account_id, char_id, option); } } return retVal___;