L2JMobius

High Five Skill parser ignores <value> child of <effect> (5 effects broken)

Altur · 3 · 21

Online Altur

  • Heir
  • **
    • Posts: 34
Chronicle: CT 2.6 HighFive

Affected file:
 - L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/gameserver/util/DocumentBase.java

Problem:
Several skill effects that read a "value" parameter from a bare <value> child of <effect> always receive the handler default (0) instead of the value written in the XML. Player-facing impact:
 - VitalityPointUp: vitality/XP-rate rewards grant 0 vitality. This is visible in the Pailaka quests (128/129/144) and on every vitality food/potion/reward skill (e.g. skills 2586, 2899). The reward silently does nothing.
 - RefuelAirship: airship refuel adds 0 fuel.
 - ChangeFace / ChangeHairColor / ChangeHairStyle: barber face/hair changes are forced to 0 instead of the selected style/color (Facelifting/Dye/Hair Style Change potions, skills 2123/2126/2130 and 2292/2295/2299).

These are the only 5 effect handlers in HighFive that read a parameter literally named "value":

  ChangeFace.java:38        _value = params.getInt("value", 0);
  ChangeHairColor.java:38   _value = params.getInt("value", 0);
  ChangeHairStyle.java:38   _value = params.getInt("value", 0);
  RefuelAirship.java:39     _value = params.getInt("value", 0);
  VitalityPointUp.java:38   _value = params.getFloat("value", 0);

Example XML (value IS a direct child of <effect>):

  <effect name="VitalityPointUp"><value>#value</value></effect>
  <effect name="ChangeHairStyle"><value>1</value></effect>
  <effect name="RefuelAirship"><value>25</value></effect>

Root cause:
DocumentBase.java declares "value" in IGNORED_ELEMENTS (line 148):

  private static final Set<String> IGNORED_ELEMENTS = Set.of("param", "conditions", "effect", "add", "sub", "mul", "div", "set", "share", "enchant", "enchanthp", "value");

This Set is referenced in exactly one place: the parseParameters() second pass, which walks the effect node's DIRECT children and turns each named element into a parameter (line 633):

  if ((n.getNodeType() == Node.ELEMENT_NODE) && !IGNORED_ELEMENTS.contains(n.getNodeName().toLowerCase()))

Because "value" is in the ignore set, a direct <value> child of <effect> is skipped and never becomes a "value" parameter. The first pass only reads <param> attribute tags, and a grep over the whole skills tree confirms the parameter is never supplied as <param name="value" .../> (zero matches) - it is always a bare <value> child. So params.getX("value", default) always returns the default.

The <value> entry in IGNORED_ELEMENTS is unnecessary here: the <value> nodes that legitimately appear inside Func templates (<mul>/<add>/<sub>/<div>/<set>/<share>/<enchant>/<enchanthp>) are children of those Func elements (which are themselves in IGNORED_ELEMENTS) and are consumed by the separate attachFunc()/template path, never by parseParameters' direct-child loop. Removing "value" from the set therefore does not touch Func parsing.

Fix:
Remove "value" from IGNORED_ELEMENTS (one-line change).

Before:
  private static final Set<String> IGNORED_ELEMENTS = Set.of("param", "conditions", "effect", "add", "sub", "mul", "div", "set", "share", "enchant", "enchanthp", "value");

After:
  private static final Set<String> IGNORED_ELEMENTS = Set.of("param", "conditions", "effect", "add", "sub", "mul", "div", "set", "share", "enchant", "enchanthp");

Verified:
Deployed to a HighFive test server. 65965 skill templates parsed with 0 errors and the server boots clean. In-game, the Pailaka vitality reward now applies (vitality is actually granted), and the barber face/hair-color/hair-style and airship refuel effects now use the value from the XML instead of 0. No Func/stat regressions: a full XML parse of all 90 HighFive skill files finds <value> as a direct child of <effect> exactly 45 times (the only direct <value> children, all belonging to those 5 effects); every other <value> is a child of a Func node and is unaffected.

This is still present in the current master (checked against an upstream-clean fork of master; the file still lists "value" in IGNORED_ELEMENTS at line 148).

Scope across chronicles:
The same refactored parser with "value" in IGNORED_ELEMENTS exists, byte-identical, in 5 legacy chronicles: C1 HarbingersOfWar, C4 ScionsOfDestiny, CT 0 Interlude, CT 2.4 Epilogue, CT 2.6 HighFive. All carry the bug. Effects that actually use a bare <value> param are present in each: VitalityPointUp / ChangeFace / ChangeHairColor / ChangeHairStyle in all five, plus RefuelAirship in CT 2.4 and CT 2.6 (airships don't exist in the earlier datapacks). The same one-line removal applies to each. Modern chronicles are NOT affected: they use a different parser (parseElementValue) with no IGNORED_ELEMENTS guard, so <value> is captured normally there.

Diff (CT 2.6 HighFive):
L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/gameserver/util/DocumentBase.java
Code: [Select]
diff --git a/L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/gameserver/util/DocumentBase.java b/L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/gameserver/util/DocumentBase.java
index 6aa1c64127..58795d3743 100644
--- a/L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/gameserver/util/DocumentBase.java
+++ b/L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/gameserver/util/DocumentBase.java
@@ -145,7 +145,7 @@ public abstract class DocumentBase
 {
  protected final Logger LOGGER = Logger.getLogger(getClass().getName());

- private static final Set<String> IGNORED_ELEMENTS = Set.of("param", "conditions", "effect", "add", "sub", "mul", "div", "set", "share", "enchant", "enchanthp", "value");
+ private static final Set<String> IGNORED_ELEMENTS = Set.of("param", "conditions", "effect", "add", "sub", "mul", "div", "set", "share", "enchant", "enchanthp");

  private final File _file;
  protected final Map<String, String[]> _tables = new HashMap<>();


Online Mobius

  • Distinguished King
  • *****
    • Posts: 19715

Online Altur

  • Heir
  • **
    • Posts: 34
Are we sure this does not break something else?

Fair concern — I checked that specifically before posting.

The change is contained and additive: IGNORED_ELEMENTS is used in only one place (the parseParameters direct-child loop, line 633). Removing "value" just lets a direct <value> child of <effect> become a parameter instead of being dropped — it never removes or changes an existing parameter, so anything that already works is unaffected.

The only nodes this touches are the direct <value> children of <effect>. In the whole skill tree there are 45 of them, and all 45 belong to the 5 effects that read a "value" param (the ones currently getting 0). The many <value> inside Func templates (<mul>/<add>/<set>/...) are children of those Func nodes, never of <effect>, so they're left alone; item data has no <value> at all.

Tested on a live HighFive server: all 65965 skills parse with 0 errors, clean boot, the 5 effects now apply the XML value and nothing else changed.