Compare commits

...

3 Commits

Author SHA1 Message Date
aleos
65ee8d78fb Merge branch 'master' into feature/adoption_system_update 2021-04-28 08:50:08 -04:00
aleos
e1193118cb Merge branch 'master' into feature/adoption_system_update 2020-03-19 12:47:58 -04:00
Aleos
dc587df982 Updates to the Adoption System
* Part of #3074.
* Adds script command unadopt and atcommand unadopt to allow babies to leave their parents.
* Includes an independence flag which converts the baby to a normal class.
* Adds support for any class base level 50 or less to be adopted (in renewal mode).
2020-03-06 09:16:18 -05:00
7 changed files with 243 additions and 24 deletions

View File

@ -964,6 +964,12 @@ Body:
- Command: reloadnpcfile - Command: reloadnpcfile
Aliases: Aliases:
- reloadnpc - reloadnpc
- Command: adopt
Help: |
Adopt a character.
- Command: unadopt
Help: |
Disown a character. Independence flag will make the baby a normal class.
Footer: Footer:
Imports: Imports:

View File

@ -1729,5 +1729,12 @@
// @hatereset // @hatereset
1515: Reset 'Hatred' monsters. 1515: Reset 'Hatred' monsters.
// More Adoption
1516: The Baby is not level 50 or lower.
1517: Baby has been disowned.
1518: Baby is not adopted.
1519: A Parent is not the father or mother of the Baby.
1520: Usage: <char name> <independent_baby>
//Custom translations //Custom translations
import: conf/msg_conf/import/map_msg_eng_conf.txt import: conf/msg_conf/import/map_msg_eng_conf.txt

View File

@ -6202,12 +6202,30 @@ Return values:
ADOPT_ALREADY_ADOPTED - Character is already adopted. ADOPT_ALREADY_ADOPTED - Character is already adopted.
ADOPT_MARRIED_AND_PARTY - Parents need to be married and in a party with the baby. 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_EQUIP_RINGS - Parents need wedding rings equipped.
ADOPT_NOT_NOVICE - Baby is not a Novice. ADOPT_NOT_NOVICE - Baby is not a Novice. In RENEWAL this has been changed to any class less that is base level 50 or lower.
ADOPT_CHARACTER_NOT_FOUND - A parent or Baby was not found. ADOPT_CHARACTER_NOT_FOUND - A parent or Baby was not found.
ADOPT_MORE_CHILDREN - You cannot adopt more than 1 child. (client message) 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_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) ADOPT_MARRIED - You cannot adopt a married person. (client message)
---------------------------------------
*unadopt("<parent_name>","<baby_name>"{,<independent_baby>});
*unadopt(<parent_id>,<baby_id>{,<independent_baby>});
This function will remove an adoption 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 removal to work.
The <independent_baby> option allows the baby to be converted to a normal class. This option
is false by default.
Return values:
UNADOPT_ALLOWED - Baby is no longer adopted.
UNADOPT_CHARACTER_NOT_FOUND - A parent or Baby was not found.
UNADOPT_NOT_ADOPTED - The Baby is not adopted.
UNADOPT_NOT_CHILD - A Parent is not the father or mother of the Baby.
--------------------------------------- ---------------------------------------
// //
4,3.- End of marriage-related commands 4,3.- End of marriage-related commands

View File

@ -10202,7 +10202,6 @@ ACMD_FUNC(clonestat) {
ACMD_FUNC(adopt) ACMD_FUNC(adopt)
{ {
TBL_PC *b_sd; TBL_PC *b_sd;
enum adopt_responses response;
nullpo_retr(-1, sd); nullpo_retr(-1, sd);
@ -10215,12 +10214,12 @@ ACMD_FUNC(adopt)
return -1; return -1;
} }
if ((b_sd = map_nick2sd(atcmd_player_name,false)) == NULL) { if ((b_sd = map_nick2sd(atcmd_player_name,false)) == nullptr) {
clif_displaymessage(fd, msg_txt(sd, 3)); // Character not found. clif_displaymessage(fd, msg_txt(sd, 3)); // Character not found.
return -1; return -1;
} }
response = pc_try_adopt(sd, map_charid2sd(sd->status.partner_id), b_sd); e_adopt_responses response = pc_try_adopt(sd, map_charid2sd(sd->status.partner_id), b_sd);
if (response == ADOPT_ALLOWED) { if (response == ADOPT_ALLOWED) {
TBL_PC *p_sd = map_charid2sd(sd->status.partner_id); TBL_PC *p_sd = map_charid2sd(sd->status.partner_id);
@ -10230,8 +10229,54 @@ ACMD_FUNC(adopt)
return 0; return 0;
} }
if (response < ADOPT_MORE_CHILDREN) // No displaymessage for client-type responses if (response < ADOPT_MORE_CHILDREN) { // No displaymessage for client-type responses
#ifdef RENEWAL
if (response == ADOPT_NOT_NOVICE)
clif_displaymessage(fd, msg_txt(sd, 1513));
else
#endif
clif_displaymessage(fd, msg_txt(sd, 744 + response - 1)); clif_displaymessage(fd, msg_txt(sd, 744 + response - 1));
}
return -1;
}
/**
* Remove an adopted character.
* Usage: @unadopt <char name> <independent_baby>
*/
ACMD_FUNC(unadopt)
{
TBL_PC *b_sd;
nullpo_retr(-1, sd);
memset(atcmd_output, '\0', sizeof(atcmd_output));
memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
uint8 independent_baby = 0;
if (!message || !*message || sscanf(message, "%23s %1hhu", atcmd_player_name, &independent_baby) < 1) {
sprintf(atcmd_output, msg_txt(sd, 1520), command); // Usage: <char name> <independent_baby>
clif_displaymessage(fd, atcmd_output);
return -1;
}
if ((b_sd = map_nick2sd(atcmd_player_name,false)) == nullptr) {
clif_displaymessage(fd, msg_txt(sd, 3)); // Character not found.
return -1;
}
e_unadopt_responses response = pc_unadopt(sd, map_charid2sd(sd->status.partner_id), b_sd, independent_baby != 0);
if (response == UNADOPT_ALLOWED) {
clif_displaymessage(fd, msg_txt(sd, 1517)); // Baby has been disowned.
return 0;
}
if (response == UNADOPT_CHARACTER_NOT_FOUND)
clif_displaymessage(fd, msg_txt(sd, 748)); // A Parent or Baby was not found.
else
clif_displaymessage(fd, msg_txt(sd, 1518 + response - 1));
return -1; return -1;
} }
@ -10667,6 +10712,7 @@ void atcommand_basecommands(void) {
ACMD_DEF(clonestat), ACMD_DEF(clonestat),
ACMD_DEF(bodystyle), ACMD_DEF(bodystyle),
ACMD_DEF(adopt), ACMD_DEF(adopt),
ACMD_DEF2("unadopt", adopt),
ACMD_DEF(agitstart3), ACMD_DEF(agitstart3),
ACMD_DEF(agitend3), ACMD_DEF(agitend3),
ACMD_DEFR(limitedsale, ATCMD_NOCONSOLE|ATCMD_NOAUTOTRADE), ACMD_DEFR(limitedsale, ATCMD_NOCONSOLE|ATCMD_NOAUTOTRADE),

View File

@ -1268,7 +1268,7 @@ bool pc_isequipped(struct map_session_data *sd, t_itemid nameid)
* ADOPT_LEVEL_70 - Parents need to be level 70+ (client message) * ADOPT_LEVEL_70 - Parents need to be level 70+ (client message)
* ADOPT_MARRIED - Cannot adopt a married person (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) e_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 ) if( !p1_sd || !p2_sd || !b_sd )
return ADOPT_CHARACTER_NOT_FOUND; return ADOPT_CHARACTER_NOT_FOUND;
@ -1309,7 +1309,11 @@ enum adopt_responses pc_try_adopt(struct map_session_data *p1_sd, struct map_ses
return ADOPT_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 ) ) #ifdef RENEWAL
if (b_sd->status.base_level < 51)
#else
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))
#endif
return ADOPT_NOT_NOVICE; return ADOPT_NOT_NOVICE;
return ADOPT_ALLOWED; return ADOPT_ALLOWED;
@ -1367,6 +1371,78 @@ bool pc_adoption(struct map_session_data *p1_sd, struct map_session_data *p2_sd,
return false; // Job Change Fail return false; // Job Change Fail
} }
/**
* Check unadoption rules and remove adoption
* @param p1_sd: Player 1
* @param p2_sd: Player 2
* @param b_sd: Player that will be unadopted
* @param independent_baby: If the baby becomes a normal class
* @return see pc.hpp::e_unadopt_responses
*/
e_unadopt_responses pc_unadopt(struct map_session_data *p1_sd, struct map_session_data *p2_sd, struct map_session_data *b_sd, bool independent_baby) {
if (!p1_sd || !p2_sd || !b_sd)
return UNADOPT_CHARACTER_NOT_FOUND;
if (!b_sd->status.father || !b_sd->status.mother)
return UNADOPT_NOT_ADOPTED;
if (p1_sd->status.child != b_sd->status.char_id && p2_sd->status.child != b_sd->status.char_id)
return UNADOPT_NOT_CHILD;
// Baby is separated from parents by independence option (Becomes a normal class)
if (independent_baby) {
int32 job = pc_mapid2jobid(b_sd->class_ | ~JOBL_BABY, b_sd->status.sex);
if (job == -1 || !pc_jobchange(b_sd, job, 0))
return UNADOPT_CHARACTER_NOT_FOUND;
}
// Remove Baby/Parent status
p1_sd->status.child = 0;
p2_sd->status.child = 0;
b_sd->status.father = 0;
b_sd->status.mother = 0;
uint16 sk_idx;
// Remove Baby Skills
if ((sk_idx = skill_get_index(WE_BABY)) > 0 && pc_checkskill(b_sd, WE_BABY) > 0) {
b_sd->status.skill[sk_idx].lv = 0;
b_sd->status.skill[sk_idx].flag = SKILL_FLAG_TEMPORARY;
clif_deleteskill(b_sd, WE_BABY);
}
if ((sk_idx = skill_get_index(WE_CALLPARENT)) > 0 && pc_checkskill(b_sd, WE_CALLPARENT) > 0) {
b_sd->status.skill[sk_idx].lv = 0;
b_sd->status.skill[sk_idx].flag = SKILL_FLAG_TEMPORARY;
clif_deleteskill(b_sd, WE_CALLPARENT);
}
if ((sk_idx = skill_get_index(WE_CHEERUP)) > 0 && pc_checkskill(b_sd, WE_CHEERUP) > 0) {
b_sd->status.skill[sk_idx].lv = 0;
b_sd->status.skill[sk_idx].flag = SKILL_FLAG_TEMPORARY;
clif_deleteskill(b_sd, WE_CHEERUP);
}
// Remove Parents Skills
if ((sk_idx = skill_get_index(WE_CALLBABY)) > 0) {
if (pc_checkskill(p1_sd, WE_CALLBABY) > 0) {
p1_sd->status.skill[sk_idx].lv = 0;
p1_sd->status.skill[sk_idx].flag = SKILL_FLAG_TEMPORARY;
clif_deleteskill(b_sd, WE_CALLBABY);
}
if (pc_checkskill(p2_sd, WE_CALLBABY) > 0) {
p1_sd->status.skill[sk_idx].lv = 0;
p1_sd->status.skill[sk_idx].flag = SKILL_FLAG_TEMPORARY;
clif_deleteskill(b_sd, WE_CALLBABY);
}
}
chrif_save(p1_sd, CSAVE_NORMAL);
chrif_save(p2_sd, CSAVE_NORMAL);
chrif_save(b_sd, CSAVE_NORMAL);
return UNADOPT_ALLOWED;
}
static bool pc_job_can_use_item( struct map_session_data* sd, struct item_data* item ){ static bool pc_job_can_use_item( struct map_session_data* sd, struct item_data* item ){
nullpo_retr( false, sd ); nullpo_retr( false, sd );
nullpo_retr( false, item ); nullpo_retr( false, item );

View File

@ -887,16 +887,23 @@ enum idletime_option {
IDLE_NPC_PROGRESS = 0x4000, IDLE_NPC_PROGRESS = 0x4000,
}; };
enum adopt_responses { enum e_adopt_responses : uint8 {
ADOPT_ALLOWED = 0, ADOPT_ALLOWED = 0, ///< Baby can be adopted
ADOPT_ALREADY_ADOPTED, ADOPT_ALREADY_ADOPTED, ///< Player is already adopted
ADOPT_MARRIED_AND_PARTY, ADOPT_MARRIED_AND_PARTY, ///< Parents need to be married and in a party
ADOPT_EQUIP_RINGS, ADOPT_EQUIP_RINGS, ///< Parents need their wedding rings equipped
ADOPT_NOT_NOVICE, ADOPT_NOT_NOVICE, ///< Baby is not a Novice
ADOPT_CHARACTER_NOT_FOUND, ADOPT_CHARACTER_NOT_FOUND, ///< Baby or Parent not found
ADOPT_MORE_CHILDREN, ADOPT_MORE_CHILDREN, ///< Cannot adopt more than 1 baby (client message)
ADOPT_LEVEL_70, ADOPT_LEVEL_70, ///< Parents need to be level 70 or higher (client message)
ADOPT_MARRIED, ADOPT_MARRIED, ///< Parents need to be married (client message)
};
enum e_unadopt_responses : uint8 {
UNADOPT_ALLOWED = 0, ///< Baby can be unadopted
UNADOPT_CHARACTER_NOT_FOUND, ///< Baby or Parent not found
UNADOPT_NOT_ADOPTED, ///< Baby is not adopted
UNADOPT_NOT_CHILD, ///< Neither parent is the father/mother
}; };
enum item_check { enum item_check {
@ -1212,8 +1219,9 @@ 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_dropitem(struct map_session_data *sd,int n,int amount);
bool pc_isequipped(struct map_session_data *sd, t_itemid nameid); bool pc_isequipped(struct map_session_data *sd, t_itemid nameid);
enum adopt_responses pc_try_adopt(struct map_session_data *p1_sd, struct map_session_data *p2_sd, struct map_session_data *b_sd); e_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); bool pc_adoption(struct map_session_data *p1_sd, struct map_session_data *p2_sd, struct map_session_data *b_sd);
e_unadopt_responses pc_unadopt(struct map_session_data *p1_sd, struct map_session_data *p2_sd, struct map_session_data *b_sd, bool independent_baby);
void pc_updateweightstatus(struct map_session_data *sd); void pc_updateweightstatus(struct map_session_data *sd);

View File

@ -23097,13 +23097,12 @@ BUILDIN_FUNC(navigateto){
BUILDIN_FUNC(adopt) BUILDIN_FUNC(adopt)
{ {
TBL_PC *sd, *b_sd; TBL_PC *sd, *b_sd;
enum adopt_responses response;
if (script_isstring(st, 2)) { if (script_isstring(st, 2)) {
const char *name = script_getstr(st, 2); const char *name = script_getstr(st, 2);
sd = map_nick2sd(name,false); sd = map_nick2sd(name,false);
if (sd == NULL) { if (sd == nullptr) {
ShowError("buildin_adopt: Non-existant parent character %s requested.\n", name); ShowError("buildin_adopt: Non-existant parent character %s requested.\n", name);
return SCRIPT_CMD_FAILURE; return SCRIPT_CMD_FAILURE;
} }
@ -23111,7 +23110,7 @@ BUILDIN_FUNC(adopt)
uint32 char_id = script_getnum(st, 2); uint32 char_id = script_getnum(st, 2);
sd = map_charid2sd(char_id); sd = map_charid2sd(char_id);
if (sd == NULL) { if (sd == nullptr) {
ShowError("buildin_adopt: Non-existant parent character %d requested.\n", char_id); ShowError("buildin_adopt: Non-existant parent character %d requested.\n", char_id);
return SCRIPT_CMD_FAILURE; return SCRIPT_CMD_FAILURE;
} }
@ -23121,7 +23120,7 @@ BUILDIN_FUNC(adopt)
const char *name = script_getstr(st, 3); const char *name = script_getstr(st, 3);
b_sd = map_nick2sd(name,false); b_sd = map_nick2sd(name,false);
if (b_sd == NULL) { if (b_sd == nullptr) {
ShowError("buildin_adopt: Non-existant baby character %s requested.\n", name); ShowError("buildin_adopt: Non-existant baby character %s requested.\n", name);
return SCRIPT_CMD_FAILURE; return SCRIPT_CMD_FAILURE;
} }
@ -23129,13 +23128,13 @@ BUILDIN_FUNC(adopt)
uint32 char_id = script_getnum(st, 3); uint32 char_id = script_getnum(st, 3);
b_sd = map_charid2sd(char_id); b_sd = map_charid2sd(char_id);
if (b_sd == NULL) { if (b_sd == nullptr) {
ShowError("buildin_adopt: Non-existant baby character %d requested.\n", char_id); ShowError("buildin_adopt: Non-existant baby character %d requested.\n", char_id);
return SCRIPT_CMD_FAILURE; return SCRIPT_CMD_FAILURE;
} }
} }
response = pc_try_adopt(sd, map_charid2sd(sd->status.partner_id), b_sd); e_adopt_responses response = pc_try_adopt(sd, map_charid2sd(sd->status.partner_id), b_sd);
if (response == ADOPT_ALLOWED) { if (response == ADOPT_ALLOWED) {
TBL_PC *p_sd = map_charid2sd(sd->status.partner_id); TBL_PC *p_sd = map_charid2sd(sd->status.partner_id);
@ -23150,6 +23149,64 @@ BUILDIN_FUNC(adopt)
return SCRIPT_CMD_FAILURE; return SCRIPT_CMD_FAILURE;
} }
/**
* unadopt("<parent_name>","<baby_name>"{,<independent_baby>});
* unadopt(<parent_id>,<baby_id>{,<independent_baby>});
*/
BUILDIN_FUNC(unadopt)
{
TBL_PC *sd, *b_sd;
if (script_isstring(st, 2)) {
const char *name = script_getstr(st, 2);
sd = map_nick2sd(name,false);
if (sd == nullptr) {
ShowError("buildin_unadopt: Non-existant parent character %s requested.\n", name);
return SCRIPT_CMD_FAILURE;
}
} else {
uint32 char_id = script_getnum(st, 2);
sd = map_charid2sd(char_id);
if (sd == nullptr) {
ShowError("buildin_unadopt: Non-existant parent character %d requested.\n", char_id);
return SCRIPT_CMD_FAILURE;
}
}
if (script_isstring(st, 3)) {
const char *name = script_getstr(st, 3);
b_sd = map_nick2sd(name,false);
if (b_sd == nullptr) {
ShowError("buildin_unadopt: Non-existant baby character %s requested.\n", name);
return SCRIPT_CMD_FAILURE;
}
} else {
uint32 char_id = script_getnum(st, 3);
b_sd = map_charid2sd(char_id);
if (b_sd == nullptr) {
ShowError("buildin_unadopt: Non-existant baby character %d requested.\n", char_id);
return SCRIPT_CMD_FAILURE;
}
}
bool independent_baby = false;
if (script_hasdata(st, 4))
independent_baby = script_getnum(st, 4) != 0;
e_unadopt_responses response = pc_unadopt(sd, map_charid2sd(sd->status.partner_id), b_sd, independent_baby);
script_pushint(st, response);
if (response == UNADOPT_ALLOWED)
return SCRIPT_CMD_SUCCESS;
else
return SCRIPT_CMD_FAILURE;
}
/** /**
* Returns the minimum or maximum of all the given parameters for integer variables. * Returns the minimum or maximum of all the given parameters for integer variables.
* *
@ -25665,6 +25722,7 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(navigateto,"s???????"), BUILDIN_DEF(navigateto,"s???????"),
BUILDIN_DEF(getguildalliance,"ii"), BUILDIN_DEF(getguildalliance,"ii"),
BUILDIN_DEF(adopt,"vv"), BUILDIN_DEF(adopt,"vv"),
BUILDIN_DEF(unadopt, "vv?"),
BUILDIN_DEF(getexp2,"ii?"), BUILDIN_DEF(getexp2,"ii?"),
BUILDIN_DEF(recalculatestat,""), BUILDIN_DEF(recalculatestat,""),
BUILDIN_DEF(hateffect,"ii"), BUILDIN_DEF(hateffect,"ii"),