Skip to content

Commit

Permalink
Merge branch 'master' into rebalance
Browse files Browse the repository at this point in the history
Signed-off-by: Haru <[email protected]>
  • Loading branch information
MishimaHaruna committed Sep 30, 2024
2 parents 22e1480 + 84da0df commit e83b97c
Show file tree
Hide file tree
Showing 11 changed files with 219 additions and 14 deletions.
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -792,10 +792,20 @@ All these changes only affect Renewal. Pre-renewal is unchanged.

- The `is_quest` argument to `pc->gainexp()` has been changed to a `flags` bitmask enum, in order to allow expansion to different flags. (#3279)

## [v2024.08] `August 2024`
## [v2024.09] `September 2024`

### Added

- Implemented the script command `getunitparam()` to query values defined in `unit_parameters_db.conf`, and the related `UNIT_PARAM_*` constants. See the `script_commands.txt` documentation for usage details. (#3323)
- Added validation of the name length for configuration entries added through the HPM `addBattleConf()`, `addLoginConf()`, `addCharConf()`, `addCharInterConf()`, `addLogConf()`, `addScriptConf()` methods, to prevent silent truncation. (#3324)

### Fixed

- Fixed an issue causing item-granted skills that were overriding an existing skill level, not to be correctly cleared when unequipping the item. (#3322)
- Fixed previously plagiarized skills re-appearing on subsequent logins due to the related script variables not getting cleared properly. (#3325)

## [v2024.08] `August 2024`

### Changed

- Converted packets `CHARLOGIN_ONLINE_ACCOUNTS`, `MAPCHAR_AUTH_REQ`, `CHARLOGIN_SET_ACCOUNT_ONLINE` to the struct format. (#3304, #3312, #3314)
Expand Down Expand Up @@ -3930,6 +3940,7 @@ Note: everything included in this release is part of PR #3198 which consists of
- New versioning scheme and project changelogs/release notes (#1853)

[Unreleased]: https://github.com/HerculesWS/Hercules/compare/stable...master
[v2024.09]: https://github.com/HerculesWS/Hercules/compare/v2024.08...v2024.09
[v2024.08]: https://github.com/HerculesWS/Hercules/compare/v2024.06...v2024.08
[v2024.06]: https://github.com/HerculesWS/Hercules/compare/v2024.05...v2024.06
[v2024.05]: https://github.com/HerculesWS/Hercules/compare/v2024.04...v2024.05
Expand Down
10 changes: 9 additions & 1 deletion doc/constants_pre-re.md
Original file line number Diff line number Diff line change
Expand Up @@ -4880,7 +4880,7 @@
### Server defines

- `PACKETVER`: 20190530
- `HERCULES_VERSION`: 202408000
- `HERCULES_VERSION`: 202409000
- `MAX_LEVEL`: 175
- `MAX_STORAGE`: 600
- `MAX_GUILD_STORAGE`: 500
Expand Down Expand Up @@ -5870,6 +5870,14 @@
- `HOMINFO_RENAME`: 5
- `HOMINFO_LEVEL`: 6

### getunitparam param-types

- `UNIT_PARAM_NAME`: 0
- `UNIT_PARAM_NATHEAL_WEIGHT_RATE`: 1
- `UNIT_PARAM_MAX_ASPD`: 2
- `UNIT_PARAM_MAX_HP`: 3
- `UNIT_PARAM_MAX_STATS`: 4

### Renewal

- `RENEWAL`: 0
Expand Down
10 changes: 9 additions & 1 deletion doc/constants_re.md
Original file line number Diff line number Diff line change
Expand Up @@ -4878,7 +4878,7 @@
### Server defines

- `PACKETVER`: 20190530
- `HERCULES_VERSION`: 202408000
- `HERCULES_VERSION`: 202409000
- `MAX_LEVEL`: 175
- `MAX_STORAGE`: 600
- `MAX_GUILD_STORAGE`: 500
Expand Down Expand Up @@ -5868,6 +5868,14 @@
- `HOMINFO_RENAME`: 5
- `HOMINFO_LEVEL`: 6

### getunitparam param-types

- `UNIT_PARAM_NAME`: 0
- `UNIT_PARAM_NATHEAL_WEIGHT_RATE`: 1
- `UNIT_PARAM_MAX_ASPD`: 2
- `UNIT_PARAM_MAX_HP`: 3
- `UNIT_PARAM_MAX_STATS`: 4

### Renewal

- `RENEWAL`: 1
Expand Down
31 changes: 31 additions & 0 deletions doc/script_commands.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3101,6 +3101,37 @@ Examples:

---------------------------------------

*getunitparam(<param type>{, <class>{, <maxlv array>, <value array>}})

Thi will return the requested parameter's value or fill the required arrays in
the case of UNIT_PARAM_MAX_HP.

<param type>:
- 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

<class> can be -1 if attached players class is desired, such as in the case of UNIT_PARAM_MAX_HP,
where <class> 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({"<character name>"})
*stand({"<character name>"})

Expand Down
5 changes: 5 additions & 0 deletions src/common/HPM.c
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,11 @@ static bool hplugins_addconf(unsigned int pluginID, enum HPluginConfType type, c
return false;
}

if (strnlen(name, HPM_ADDCONF_LENGTH) >= HPM_ADDCONF_LENGTH) {
ShowError("HPM->addConf:%s: config '%s' name/path is too long. Maximum is %d characters (see #define HPM_ADDCONF_LENGTH). Skipping it.\n", HPM->pid2name(pluginID), name, HPM_ADDCONF_LENGTH - 1);
return false;
}

ARR_FIND(0, VECTOR_LENGTH(HPM->config_listeners[type]), i, strcmpi(name, VECTOR_INDEX(HPM->config_listeners[type], i).key) == 0);
if (i != VECTOR_LENGTH(HPM->config_listeners[type])) {
ShowError("HPM->addConf:%s: duplicate '%s', already in use by '%s'!",
Expand Down
2 changes: 2 additions & 0 deletions src/common/HPMi.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ struct map_session_data;
struct hplugin_data_store;

#define HPM_VERSION "1.2"

// Maximum length of the configuration path for configs added with add*Conf
#define HPM_ADDCONF_LENGTH 40

struct hplugin_info {
Expand Down
2 changes: 1 addition & 1 deletion src/config/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#define CONFIG_CORE_H

/// Hercules version. From tag vYYYY.MM(+PPP) -> YYYYMMPPP
#define HERCULES_VERSION 202408000
#define HERCULES_VERSION 202409000

/// Max number of items on @autolootid list
#define AUTOLOOTITEM_SIZE 10
Expand Down
16 changes: 12 additions & 4 deletions src/map/pc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1659,7 +1659,8 @@ static void pc_calc_skilltree_clear(struct map_session_data *sd)

for (i = 0; i < MAX_SKILL_DB; i++) {
if (sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED || sd->status.skill[i].flag == SKILL_FLAG_PERM_GRANTED
|| sd->status.skill[i].id == sd->cloneskill_id || sd->status.skill[i].id == sd->reproduceskill_id) //Don't touch these
|| (sd->cloneskill_id != 0 && sd->status.skill[i].id == sd->cloneskill_id)
|| (sd->reproduceskill_id != 0 && sd->status.skill[i].id == sd->reproduceskill_id)) //Don't touch these
continue;
sd->status.skill[i].id = 0; //First clear skills.
/* permanent skills that must be re-checked */
Expand Down Expand Up @@ -1695,10 +1696,17 @@ static int pc_calc_skilltree(struct map_session_data *sd)
pc->calc_skilltree_clear(sd);

for (int i = 0; i < MAX_SKILL_DB; i++) {
if ((sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0 && sd->status.skill[i].id != sd->cloneskill_id && sd->status.skill[i].id != sd->reproduceskill_id)
|| sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) {
if (sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0) {
bool is_cloneskill = sd->cloneskill_id != 0 && sd->status.skill[i].id == sd->cloneskill_id;
bool is_reproduceskill = sd->reproduceskill_id != 0 && sd->status.skill[i].id == sd->reproduceskill_id;
if (is_cloneskill || is_reproduceskill)
continue; // Plagiarized and Reproduce Skills are kept.

// Restore original level of skills after deleting earned skills.
sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0;
sd->status.skill[i].lv = sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0;
sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
} else if (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) {
sd->status.skill[i].lv = 0;
sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
}
}
Expand Down
122 changes: 122 additions & 0 deletions src/map/script.c
Original file line number Diff line number Diff line change
Expand Up @@ -28628,6 +28628,120 @@ static BUILDIN(mestipbox)
return true;
}


/**
* Returns a units <parameter>'s values
*
* NOTE: UNIT_PARAM_MAX_HP needs two arrays.
*
* getunitparam(<param>{, <class id>{, <maxlv array>, <value array>}})
*/
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: <param>, <class id>, <maxlv array>, <value array>\n");
st->state = END;
return false;
}

struct script_data *maxhp_maxlvls = script_getdata(st, 4);
struct script_data *maxhp_values = script_getdata(st, 5);
if (!data_isreference(maxhp_maxlvls) || reference_toconstant(maxhp_maxlvls)) {
ShowError("buildin_getunitparam: <maxlv array> argument must be reference and not a reference to constant\n");
script->reportdata(maxhp_maxlvls);
st->state = END;
return false;
}
if (!data_isreference(maxhp_values) || reference_toconstant(maxhp_values)) {
ShowError("buildin_getunitparam: <value array> argument must be reference and not a reference to constant\n");
script->reportdata(maxhp_values);
st->state = END;
return false;
}

const char *maxhp_maxlvls_varname = reference_getname(maxhp_maxlvls);
const char *maxhp_values_varname = reference_getname(maxhp_values);
if (!is_int_variable(maxhp_maxlvls_varname)) {
ShowError("buildin_getunitparam: <maxlv array> argument must be of integer type\n");
script->reportdata(maxhp_maxlvls);
st->state = END;
return false;
}
if (!is_int_variable(maxhp_values_varname)) {
ShowError("buildin_getunitparam: <value array> 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.
*
Expand Down Expand Up @@ -29507,6 +29621,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
Expand Down Expand Up @@ -30490,6 +30605,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("autospell db constants");
script->set_constant2("HALF_AUTOSPELL_LEVEL", HALF_AUTOSPELL_LEVEL, false, false);

Expand Down
14 changes: 8 additions & 6 deletions src/map/skill.c
Original file line number Diff line number Diff line change
Expand Up @@ -3704,12 +3704,13 @@ static int skill_attack(int attack_type, struct block_list *src, struct block_li
switch(can_copy(tsd, copy_skill)) {
case 1: // Plagiarism
{
pc->clear_existing_cloneskill(tsd, false);

lv = min(skill_lv, pc->checkskill(tsd, RG_PLAGIARISM));
if (learned_lv > lv)
if (learned_lv > lv) {
pc->clear_existing_cloneskill(tsd, true);
break; // [Aegis] can't overwrite skill of higher level, but will still remove previously copied skill.
}

pc->clear_existing_cloneskill(tsd, false);
tsd->cloneskill_id = copy_skill;
pc_setglobalreg(tsd, script->add_variable("CLONE_SKILL"), copy_skill);
pc_setglobalreg(tsd, script->add_variable("CLONE_SKILL_LV"), lv);
Expand All @@ -3726,12 +3727,13 @@ static int skill_attack(int attack_type, struct block_list *src, struct block_li
case 2: // Reproduce
{
lv = sc ? sc->data[SC__REPRODUCE]->val1 : 1;
pc->clear_existing_reproduceskill(tsd, false);

lv = min(lv, skill->get_max(copy_skill));
if (learned_lv > lv)
if (learned_lv > lv) {
pc->clear_existing_reproduceskill(tsd, true);
break; // unconfirmed, but probably the same behavior as for RG_PLAGIARISM
}

pc->clear_existing_reproduceskill(tsd, false);
tsd->reproduceskill_id = copy_skill;
pc_setglobalreg(tsd, script->add_variable("REPRODUCE_SKILL"), copy_skill);
pc_setglobalreg(tsd, script->add_variable("REPRODUCE_SKILL_LV"), lv);
Expand Down
8 changes: 8 additions & 0 deletions src/map/status.h
Original file line number Diff line number Diff line change
Expand Up @@ -1351,6 +1351,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

Expand Down

0 comments on commit e83b97c

Please sign in to comment.