From 7b6437fc65e0329a2e48828912e90439670537eb Mon Sep 17 00:00:00 2001 From: skyleo Date: Fri, 20 Sep 2024 08:22:40 +0200 Subject: [PATCH] Add *getunitparam to obtain values set via unit_parameters_db.conf in scripts --- doc/script_commands.txt | 31 ++++++++++++ src/map/script.c | 109 ++++++++++++++++++++++++++++++++++++++++ src/map/status.h | 8 +++ 3 files changed, 148 insertions(+) diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 1c4bb8aa3ab..939ea863f4f 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -3101,6 +3101,37 @@ Examples: --------------------------------------- +*getunitparam({, {, , }}) + +Thi will return the requested parameter's value or fill the required arrays in +the case of UNIT_PARAM_MAX_HP. + +: +- UNIT_PARAM_NAME ^= name of unit_parameters_db.conf entry used by class. +- UNIT_PARAM_NATHEAL_WEIGHT_RATE ^= NaturalHealWeightRate value +- UNIT_PARAM_MAX_ASPD ^= MaxASPD +- UNIT_PARAM_MAX_HP ^= MaxHP +- UNIT_PARAM_MAX_STATS ^= MaxStats + + can be -1 if attached players class is desired, such as in the case of UNIT_PARAM_MAX_HP, +where is mandatory. + +Examples: + +// Outputs the possible maximum ASPD of attached player. + mesf("MAX_ASPD: %d", getunitparam(UNIT_PARAM_MAX_ASPD)); + +// Outputs the possible maximum stats of Job_Baby. + mesf("MAX_STATS: %d", getunitparam(UNIT_PARAM_MAX_STATS, Job_Baby)); + +// Saves the entries for MAXHP per level ranges of JOB_SUPER_NOVICE into the given arrays and prints them. + .@count = getunitparam(UNIT_PARAM_MAX_ASPD, JOB_SUPER_NOVICE, .@max_lv, .@max_hp); + for (.@i = 0; .@i < .@count; ++.@i) { + mesf("max_lv: %d, max_hp: %d", .@max_lv[.@i], .@max_hp[.@i]); + } + +--------------------------------------- + *sit({""}) *stand({""}) diff --git a/src/map/script.c b/src/map/script.c index 8ecddd7fc43..85fdd5d77ca 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -28628,6 +28628,107 @@ static BUILDIN(mestipbox) return true; } + +/** + * Returns a units 's values + * + * NOTE: UNIT_PARAM_MAX_HP needs two arrays. + * + * getunitparam({, {, , }}) + */ +static BUILDIN(getunitparam) +{ + int class = -1; + if (script_hasdata(st, 3)) { + class = script_getnum(st, 3); + if (class != -1) { + if (!pc->db_checkid(class)) { + ShowError("buildin_getunitparam: invalid class (%d)\n", class); + st->state = END; + return false; + } + class = pc->class2idx(class); + } + } + + struct map_session_data *sd = NULL; + if (class == -1) { + sd = script_rid2sd(st); + if (sd == NULL) { + ShowError("buildin_getunitparam: No player attached, but class == -1.\n"); + return false; + } + class = pc->class2idx(sd->status.class); + } + + struct s_unit_params *entry = status->dbs->unit_params[class]; + int param = script_getnum(st, 2); + switch (param) { + case UNIT_PARAM_NAME: + script_pushconststr(st, entry->name); + break; + case UNIT_PARAM_NATHEAL_WEIGHT_RATE: + script_pushint(st, entry->natural_heal_weight_rate); + break; + case UNIT_PARAM_MAX_ASPD: + script_pushint(st, (2000 - entry->max_aspd) / 10); // max_aspd is actually min_amotion :) + break; + case UNIT_PARAM_MAX_HP: { + if (!script_hasdata(st, 4) || !script_hasdata(st, 5)) { + ShowError("buildin_getunitparam: UNIT_PARAM_MAXP_HP requires 4 parameters: , , , \n"); + st->state = END; + return false; + } + struct script_data *maxhp_maxlvls = script_getdata(st, 4); + struct script_data *maxhp_values = script_getdata(st, 5); + const char *maxhp_maxlvls_varname = reference_getname(maxhp_maxlvls); + const char *maxhp_values_varname = reference_getname(maxhp_values); + + if (!data_isreference(maxhp_maxlvls) || reference_toconstant(maxhp_maxlvls) || !is_int_variable(maxhp_maxlvls_varname)) { + ShowError("buildin_getunitparam: argument must be of integer type\n"); + script->reportdata(maxhp_maxlvls); + st->state = END; + return false; + } + if (!data_isreference(maxhp_values) || reference_toconstant(maxhp_values) || !is_int_variable(maxhp_values_varname)) { + ShowError("buildin_getunitparam: argument must be of integer type\n"); + script->reportdata(maxhp_values); + st->state = END; + return false; + } + + if (not_server_variable(*maxhp_maxlvls_varname) || not_server_variable(*maxhp_values_varname)) { + if (sd == NULL) { + sd = script->rid2sd(st); + if (sd == NULL) + return false; // player variable but no player attached + } + } + + int varid1 = reference_getid(maxhp_maxlvls); + int varid2 = reference_getid(maxhp_values); + int count = entry->maxhp_size; + for (int i = 0; i < count; i++) { + script->set_reg(st, sd, reference_uid(varid1, i), maxhp_maxlvls_varname, (const void *)h64BPTRSIZE(entry->maxhp[i].max_level), + reference_getref(maxhp_maxlvls)); + script->set_reg(st, sd, reference_uid(varid2, i), maxhp_values_varname, (const void *)h64BPTRSIZE(entry->maxhp[i].value), + reference_getref(maxhp_values)); + } + script_pushint(st, count); + break; + } + case UNIT_PARAM_MAX_STATS: + script_pushint(st, entry->max_stats); + break; + default: + ShowError("buildin_getunitparam: Received invalid param: %d\n", param); + st->state = END; + return false; + } + + return true; +} + /** * Adds a built-in script function. * @@ -29507,6 +29608,7 @@ static void script_parse_builtin(void) BUILDIN_DEF(mesurl, "ss??"), BUILDIN_DEF(mestipbox, "si"), + BUILDIN_DEF(getunitparam, "i???"), }; int i, len = ARRAYLENGTH(BUILDIN); RECREATE(script->buildin, char *, script->buildin_count + len); // Pre-alloc to speed up @@ -30490,6 +30592,13 @@ static void script_hardcoded_constants(void) script->set_constant("HOMINFO_RENAME", HOMINFO_RENAME, false, false); script->set_constant("HOMINFO_LEVEL", HOMINFO_LEVEL, false, false); + script->constdb_comment("getunitparam param-types"); + script->set_constant("UNIT_PARAM_NAME", UNIT_PARAM_NAME, false, false); + script->set_constant("UNIT_PARAM_NATHEAL_WEIGHT_RATE", UNIT_PARAM_NATHEAL_WEIGHT_RATE, false, false); + script->set_constant("UNIT_PARAM_MAX_ASPD", UNIT_PARAM_MAX_ASPD, false, false); + script->set_constant("UNIT_PARAM_MAX_HP", UNIT_PARAM_MAX_HP, false, false); + script->set_constant("UNIT_PARAM_MAX_STATS", UNIT_PARAM_MAX_STATS, false, false); + script->constdb_comment("Renewal"); #ifdef RENEWAL script->set_constant("RENEWAL", 1, false, false); diff --git a/src/map/status.h b/src/map/status.h index a426a71d765..6f6712f060a 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -1323,6 +1323,14 @@ struct s_maxhp_entry { int value; ///< The actual max hp value }; +enum e_unit_params { + UNIT_PARAM_NAME, + UNIT_PARAM_NATHEAL_WEIGHT_RATE, + UNIT_PARAM_MAX_ASPD, + UNIT_PARAM_MAX_HP, + UNIT_PARAM_MAX_STATS, +}; + struct s_unit_params { char name[SCRIPT_VARNAME_LENGTH]; ///< group name as defined in conf