From 0f5b6db8139d78da17587406d1cee45c7954b2ab Mon Sep 17 00:00:00 2001 From: aleos89 Date: Fri, 11 Mar 2016 13:45:17 -0500 Subject: [PATCH] Implemented new adoption methods * Implemented atcommand adopt. * Implemented script command adopt. * Circumvents adoption issues with 2013-08+ clients (Related to #768). * Suggested from https://rathena.org/board/topic/104014-suggestion-add-adopt-or-etc/ --- conf/msg_conf/map_msg.conf | 10 ++++- doc/script_commands.txt | 20 ++++++++++ src/map/atcommand.c | 44 ++++++++++++++++++++++ src/map/clif.c | 8 ++-- src/map/clif.h | 7 ++++ src/map/pc.c | 55 ++++++++++++++++------------ src/map/pc.h | 14 ++++++- src/map/script.c | 75 ++++++++++++++++++++++++++++++++++++++ src/map/script_constants.h | 10 +++++ 9 files changed, 214 insertions(+), 29 deletions(-) diff --git a/conf/msg_conf/map_msg.conf b/conf/msg_conf/map_msg.conf index a778f7f16e..9966b79de1 100644 --- a/conf/msg_conf/map_msg.conf +++ b/conf/msg_conf/map_msg.conf @@ -785,7 +785,15 @@ 741: Gained 742: Lost 743: Experience %s Base:%ld (%0.2f%%) Job:%ld (%0.2f%%) -//744-899 free + +// @adopt +744: Baby already adopted or is in the process of being adopted. +745: You need to be married and in a party with your partner and the Baby to adopt. +746: Both parents need to have their wedding rings equipped. +747: The Baby is not a Novice. +748: A parent or Baby was not found. + +//749-899 free //------------------------------------ // More atcommands message diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 20eea4a81f..7788ef560f 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -5536,6 +5536,26 @@ current SVN, which prevents the cases of multi-spouse problems). It will return This function will also destroy both wedding rings and send a message to both players, telling them they are now divorced. +--------------------------------------- + +*adopt("",""); +*adopt(,); + +This function will send the client adoption request to the specified baby +character. The parent value can be either parent. Both parents and the baby +need to be online in order for adoption to work. + +Return values: + ADOPT_ALLOWED - Sent message to Baby to accept or deny. + ADOPT_ALREADY_ADOPTED - Character is already adopted. + ADOPT_MARRIED_AND_PARTY - Parents need to be married and in a party with the baby. + ADOPT_EQUIP_RINGS - Parents need wedding rings equipped. + ADOPT_NOT_NOVICE - Baby is not a Novice. + ADOPT_CHARACTER_NOT_FOUND - A parent or Baby was not found. + ADOPT_MORE_CHILDREN - You cannot adopt more than 1 child. (client message) + ADOPT_LEVEL_70 - Parents need to be at least level 70 in order to adopt someone. (client message) + ADOPT_MARRIED - You cannot adopt a married person. (client message) + --------------------------------------- // 4,3.- End of marriage-related commands diff --git a/src/map/atcommand.c b/src/map/atcommand.c index dddcdf7134..1895f3165a 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -9783,6 +9783,49 @@ ACMD_FUNC(clonestat) { return 0; } +/** + * Adopt a character. + * Usage: @adopt + * https://rathena.org/board/topic/104014-suggestion-add-adopt-or-etc/ + */ +ACMD_FUNC(adopt) +{ + TBL_PC *b_sd; + enum adopt_responses response; + + nullpo_retr(-1, sd); + + memset(atcmd_output, '\0', sizeof(atcmd_output)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); + + if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { + sprintf(atcmd_output, msg_txt(sd, 435), command); // Please enter a player name (usage: %s ). + clif_displaymessage(fd, atcmd_output); + return -1; + } + + if ((b_sd = map_nick2sd((char *)atcmd_player_name)) == NULL) { + clif_displaymessage(fd, msg_txt(sd, 3)); // Character not found. + return -1; + } + + response = pc_try_adopt(sd, map_charid2sd(sd->status.partner_id), b_sd); + + if (response == ADOPT_ALLOWED) { + TBL_PC *p_sd = map_charid2sd(sd->status.partner_id); + + b_sd->adopt_invite = sd->status.account_id; + clif_Adopt_request(b_sd, sd, p_sd->status.account_id); + return 0; + } + + if (response < ADOPT_MORE_CHILDREN) { // No displaymessage for client-type responses + sprintf(atcmd_output, msg_txt(sd, 744 + response - 1)); + clif_displaymessage(fd, atcmd_output); + } + return -1; +} + #include "../custom/atcommand.inc" /** @@ -10075,6 +10118,7 @@ void atcommand_basecommands(void) { ACMD_DEF(cloneequip), ACMD_DEF(clonestat), ACMD_DEF(bodystyle), + ACMD_DEF(adopt), }; AtCommandInfo* atcommand; int i; diff --git a/src/map/clif.c b/src/map/clif.c index 3a378ff6cc..5b5fa00a5f 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -15755,9 +15755,9 @@ void clif_parse_cashshop_buy(int fd, struct map_session_data *sd){ /// Adoption message (ZC_BABYMSG). /// 0216 .L /// msg: -/// 0 = "You cannot adopt more than 1 child." -/// 1 = "You must be at least character level 70 in order to adopt someone." -/// 2 = "You cannot adopt a married person." +/// ADOPT_REPLY_MORE_CHILDREN = "You cannot adopt more than 1 child." +/// ADOPT_REPLY_LEVEL_70 = "You must be at least character level 70 in order to adopt someone." +/// ADOPT_REPLY_MARRIED = "You cannot adopt a married person." void clif_Adopt_reply(struct map_session_data *sd, int type) { int fd = sd->fd; @@ -15791,7 +15791,7 @@ void clif_parse_Adopt_request(int fd, struct map_session_data *sd) TBL_PC *tsd = map_id2sd(RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0])); TBL_PC *p_sd = map_charid2sd(sd->status.partner_id); - if( pc_can_Adopt(sd, p_sd, tsd) ) + if( pc_try_adopt(sd, p_sd, tsd) == ADOPT_ALLOWED ) { tsd->adopt_invite = sd->status.account_id; clif_Adopt_request(tsd, sd, p_sd->status.account_id); diff --git a/src/map/clif.h b/src/map/clif.h index a3aa6e897d..77035f68ef 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -136,6 +136,12 @@ enum BROADCASTING_SPECIAL_ITEM_OBTAIN { ITEMOBTAIN_TYPE_NPC = 0x2, }; +enum e_adopt_reply { + ADOPT_REPLY_MORE_CHILDREN = 0, + ADOPT_REPLY_LEVEL_70, + ADOPT_REPLY_MARRIED, +}; + // packet_db[SERVER] is reserved for server use #define SERVER 0 #define packet_len(cmd) packet_db[SERVER][cmd].len @@ -855,6 +861,7 @@ void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd); // ADOPTION void clif_Adopt_reply(struct map_session_data *sd, int type); +void clif_Adopt_request(struct map_session_data *sd, struct map_session_data *src, int p_id); // MERCENARIES void clif_mercenary_info(struct map_session_data *sd); diff --git a/src/map/pc.c b/src/map/pc.c index eed61e1ad3..1b028d7f9a 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -868,57 +868,66 @@ bool pc_isequipped(struct map_session_data *sd, unsigned short nameid) return false; } -/** Check adopt rule -* @param p1_sd Player 1 -* @param p2_sd Player 2 -* @param b_sd Player that will be adopted -* @return True - if can be adopted, False otherwise -*/ -bool pc_can_Adopt(struct map_session_data *p1_sd, struct map_session_data *p2_sd, struct map_session_data *b_sd ) +/** + * Check adoption rules + * @param p1_sd: Player 1 + * @param p2_sd: Player 2 + * @param b_sd: Player that will be adopted + * @return ADOPT_ALLOWED - Sent message to Baby to accept or deny + * ADOPT_ALREADY_ADOPTED - Already adopted + * ADOPT_MARRIED_AND_PARTY - Need to be married and in the same party + * ADOPT_EQUIP_RINGS - Need wedding rings equipped + * ADOPT_NOT_NOVICE - Adoptee is not a Novice + * ADOPT_CHARACTER_NOT_FOUND - Parent or Baby not found + * ADOPT_MORE_CHILDREN - Cannot adopt more than 1 Baby (client message) + * ADOPT_LEVEL_70 - Parents need to be level 70+ (client message) + * ADOPT_MARRIED - Cannot adopt a married person (client message) + */ +enum adopt_responses pc_try_adopt(struct map_session_data *p1_sd, struct map_session_data *p2_sd, struct map_session_data *b_sd) { if( !p1_sd || !p2_sd || !b_sd ) - return false; + return ADOPT_CHARACTER_NOT_FOUND; if( b_sd->status.father || b_sd->status.mother || b_sd->adopt_invite ) - return false; // already adopted baby / in adopt request + return ADOPT_ALREADY_ADOPTED; // already adopted baby / in adopt request if( !p1_sd->status.partner_id || !p1_sd->status.party_id || p1_sd->status.party_id != b_sd->status.party_id ) - return false; // You need to be married and in party with baby to adopt + return ADOPT_MARRIED_AND_PARTY; // You need to be married and in party with baby to adopt if( p1_sd->status.partner_id != p2_sd->status.char_id || p2_sd->status.partner_id != p1_sd->status.char_id ) - return false; // Not married, wrong married + return ADOPT_MARRIED_AND_PARTY; // Not married, wrong married if( p2_sd->status.party_id != p1_sd->status.party_id ) - return false; // Both parents need to be in the same party + return ADOPT_MARRIED_AND_PARTY; // Both parents need to be in the same party // Parents need to have their ring equipped if( !pc_isequipped(p1_sd, WEDDING_RING_M) && !pc_isequipped(p1_sd, WEDDING_RING_F) ) - return false; + return ADOPT_EQUIP_RINGS; if( !pc_isequipped(p2_sd, WEDDING_RING_M) && !pc_isequipped(p2_sd, WEDDING_RING_F) ) - return false; + return ADOPT_EQUIP_RINGS; // Already adopted a baby if( p1_sd->status.child || p2_sd->status.child ) { - clif_Adopt_reply(p1_sd, 0); - return false; + clif_Adopt_reply(p1_sd, ADOPT_REPLY_MORE_CHILDREN); + return ADOPT_MORE_CHILDREN; } // Parents need at least lvl 70 to adopt if( p1_sd->status.base_level < 70 || p2_sd->status.base_level < 70 ) { - clif_Adopt_reply(p1_sd, 1); - return false; + clif_Adopt_reply(p1_sd, ADOPT_REPLY_LEVEL_70); + return ADOPT_LEVEL_70; } if( b_sd->status.partner_id ) { - clif_Adopt_reply(p1_sd, 2); - return false; + clif_Adopt_reply(p1_sd, ADOPT_REPLY_MARRIED); + return ADOPT_MARRIED; } if( !( ( b_sd->status.class_ >= JOB_NOVICE && b_sd->status.class_ <= JOB_THIEF ) || b_sd->status.class_ == JOB_SUPER_NOVICE || b_sd->status.class_ == JOB_SUPER_NOVICE_E ) ) - return false; + return ADOPT_NOT_NOVICE; - return true; + return ADOPT_ALLOWED; } /*========================================== @@ -929,7 +938,7 @@ bool pc_adoption(struct map_session_data *p1_sd, struct map_session_data *p2_sd, int job, joblevel; unsigned int jobexp; - if( !pc_can_Adopt(p1_sd, p2_sd, b_sd) ) + if( pc_try_adopt(p1_sd, p2_sd, b_sd) != ADOPT_ALLOWED ) return false; // Preserve current job levels and progress diff --git a/src/map/pc.h b/src/map/pc.h index 1ed2069cfd..637ec30802 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -749,6 +749,18 @@ enum idletime_option { IDLE_ATCOMMAND = 0x200, }; +enum adopt_responses { + ADOPT_ALLOWED = 0, + ADOPT_ALREADY_ADOPTED, + ADOPT_MARRIED_AND_PARTY, + ADOPT_EQUIP_RINGS, + ADOPT_NOT_NOVICE, + ADOPT_CHARACTER_NOT_FOUND, + ADOPT_MORE_CHILDREN, + ADOPT_LEVEL_70, + ADOPT_MARRIED, +}; + struct { unsigned int base_hp[MAX_LEVEL], base_sp[MAX_LEVEL]; //Storage for the first calculation with hp/sp factor and multiplicator int hp_factor, hp_multiplicator, sp_factor; @@ -966,7 +978,7 @@ bool pc_takeitem(struct map_session_data *sd,struct flooritem_data *fitem); bool pc_dropitem(struct map_session_data *sd,int n,int amount); bool pc_isequipped(struct map_session_data *sd, unsigned short nameid); -bool pc_can_Adopt(struct map_session_data *p1_sd, struct map_session_data *p2_sd, struct map_session_data *b_sd ); +enum adopt_responses pc_try_adopt(struct map_session_data *p1_sd, struct map_session_data *p2_sd, struct map_session_data *b_sd); bool pc_adoption(struct map_session_data *p1_sd, struct map_session_data *p2_sd, struct map_session_data *b_sd); void pc_updateweightstatus(struct map_session_data *sd); diff --git a/src/map/script.c b/src/map/script.c index 29ead848f1..43392ad594 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -21095,6 +21095,80 @@ BUILDIN_FUNC(navigateto){ #endif } +/** + * adopt("",""); + * adopt(,); + * https://rathena.org/board/topic/104014-suggestion-add-adopt-or-etc/ + */ +BUILDIN_FUNC(adopt) +{ + TBL_PC *sd, *b_sd; + struct script_data *data; + enum adopt_responses response; + + data = script_getdata(st, 2); + get_val(st, data); + + if (data_isstring(data)) { + const char *name = conv_str(st, data); + + sd = map_nick2sd(name); + if (sd == NULL) { + ShowError("buildin_adopt: Non-existant parent character %s requested.\n", name); + return SCRIPT_CMD_FAILURE; + } + } else if (data_isint(data)) { + uint32 char_id = conv_num(st, data); + + sd = map_charid2sd(char_id); + if (sd == NULL) { + ShowError("buildin_adopt: Non-existant parent character %d requested.\n", char_id); + return SCRIPT_CMD_FAILURE; + } + } else { + ShowError("buildin_adopt: Invalid data type for argument #1 (%d).", data->type); + return SCRIPT_CMD_FAILURE; + } + + data = script_getdata(st, 3); + get_val(st, data); + + if (data_isstring(data)) { + const char *name = conv_str(st, data); + + b_sd = map_nick2sd(name); + if (b_sd == NULL) { + ShowError("buildin_adopt: Non-existant baby character %s requested.\n", name); + return SCRIPT_CMD_FAILURE; + } + } else if (data_isint(data)) { + uint32 char_id = conv_num(st, data); + + b_sd = map_charid2sd(char_id); + if (b_sd == NULL) { + ShowError("buildin_adopt: Non-existant baby character %d requested.\n", char_id); + return SCRIPT_CMD_FAILURE; + } + } else { + ShowError("buildin_adopt: Invalid data type for argument #2 (%d).", data->type); + return SCRIPT_CMD_FAILURE; + } + + response = pc_try_adopt(sd, map_charid2sd(sd->status.partner_id), b_sd); + + if (response == ADOPT_ALLOWED) { + TBL_PC *p_sd = map_charid2sd(sd->status.partner_id); + + b_sd->adopt_invite = sd->status.account_id; + clif_Adopt_request(b_sd, sd, p_sd->status.account_id); + script_pushint(st, ADOPT_ALLOWED); + return SCRIPT_CMD_SUCCESS; + } + + script_pushint(st, response); + return SCRIPT_CMD_FAILURE; +} + #include "../custom/script.inc" // declarations that were supposed to be exported from npc_chat.c @@ -21662,6 +21736,7 @@ struct script_function buildin_func[] = { BUILDIN_DEF(setquestinfo_job,"ii*"), BUILDIN_DEF(opendressroom,"i?"), BUILDIN_DEF(navigateto,"s???????"), + BUILDIN_DEF(adopt,"vv"), #include "../custom/script_def.inc" diff --git a/src/map/script_constants.h b/src/map/script_constants.h index d2ff1c43ea..fe6688f304 100644 --- a/src/map/script_constants.h +++ b/src/map/script_constants.h @@ -3004,6 +3004,16 @@ export_constant(NAV_KAFRA_AND_SCROLL); export_constant(NAV_ALL); + export_constant(ADOPT_ALLOWED); + export_constant(ADOPT_ALREADY_ADOPTED); + export_constant(ADOPT_MARRIED_AND_PARTY); + export_constant(ADOPT_EQUIP_RINGS); + export_constant(ADOPT_NOT_NOVICE); + export_constant(ADOPT_CHARACTER_NOT_FOUND); + export_constant(ADOPT_MORE_CHILDREN); + export_constant(ADOPT_LEVEL_70); + export_constant(ADOPT_MARRIED); + #undef export_constant #endif /* _SCRIPT_CONSTANTS_H_ */