Skip to content

feat(items): the tooltip's durability lines come from the data - #825

Open
ezequielzacca wants to merge 74 commits into
sven-n:mainfrom
ezequielzacca:feat/item-tooltip-durability
Open

ezequielzacca wants to merge 74 commits into
sven-n:mainfrom
ezequielzacca:feat/item-tooltip-durability

Conversation

@ezequielzacca

@ezequielzacca ezequielzacca commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

This step's own changes: compare with #824. The diff of this PR also holds every earlier step of #815, since a PR from a fork can only target this repository's branches.

Summary

Step 5b-3b of #815 (data-driven item tooltips; design). Stacked on #824 (→ #823 → … → #813): only the last three commits are this step.

The tooltip's durability block is data now. It was one condition with about 20 item exceptions, followed by a chain of 25 branches by item type, and it's down to one line of code: the Talisman of Mobility's saved location.

The commits

  1. test(items): the tooltip snapshot also records a count and a timed item, before anything moves. "Every item's tooltip is as recorded" only recorded full durability and items that aren't timed, which missed the branches this step moves. Potions have no durability in their data, so their count was never shown, and a pet's "Life" line is hidden when it's timed. This commit added two variants, count (durability 3) and timed (expired). After review, test(items): every item's tooltip in a test, against recorded hashes #822 records eleven variants that cover both (durability 1 and 0, and expired), so they're merged into those: the snapshot here is recorded with the eleven.
  2. feat(items): the tooltip's durability lines come from the data: the move. Against commit 1, every tooltip is unchanged except the 10 lucky item tickets (below). That was 91,104 tooltips per hero with the six variants of then, both in the test and in the game's tooltip-snapshot; with test(items): every item's tooltip in a test, against recorded hashes #822's eleven variants (160,336 per hero), the full tooltip text against feat(items): the tooltip's stat lines come from a tooltip layout #824 changes only for the 10 lucky item tickets and, from commit 3, the nine tickets with "usable 10 times".
  3. fix(items): "usable 10 times", with its space and translated: a text fix, re-recorded on its own.

How

  • The standard line is in the default layout:

    {"text": "@durability", "when": ["hasDurability", "!timed", "!tag:noDurabilityLine"]}

    hasDurability is the old rule as a state: groups 0–11 and 13 with a durability, plus the wings and capes 12/0–6, 12/36–43 and 12/49–50.

  • The other lines are in the items' own descriptions, which come right before the durability block. So each line keeps its place:

    Items Line
    24 potions and jewels {"text": "@numberOfItems", "when": ["durability"]}
    Arrows, bolts {"text": "@numberOfItems"}
    13 pets {"text": "@life", "when": ["!timed"]}
    7 tickets {"text": "@usableTimes"}; the Varka tickets add their weekday line
    Splinter of Armor, Bless of Guardian, Claw of Beast {"text": {"en": "{durability} / 20"}} (/ 10)
    Wizard's Ring {"text": "@durability", "when": ["!timed", "level!=1", "level!=2"]}
    Chaos Castle ticket @durability when !timed, @usableTimes when timed
    Rena @numberOfItems at levels: [3, 3]
    Talisman of Mobility its two texts, when: ["durability=2"] / ["durability=1"]
    Transformation Ring, Talisman of Luck, the 11 wing-mix charms, the 10 lucky item tickets their texts, with translations
  • noDurabilityLine: this tag replaces the old exception list. 57 items have a durability but not the standard line, and each one is now visible in its own data.

New in the data

  • Description lines take a shared text of Tooltip.json ("@life") and conditions ("when", as a layout line's).
    • A missing shared text, or one whose placeholders a description can't fill, is a load error, with a suggestion for a typo.
    • The "unused shared text" warning now counts descriptions too.
  • Comparisons in conditions: "durability=2", "level!=1", with =, !=, <, <=, >, >= against a whole number. Comparing a state, or a typo, is a load error.
  • States: hasDurability, timed.
  • Tag: noDurabilityLine.

Tooltips that changed, on purpose

The 10 lucky item tickets: after their blue text and blank line, the old code wrote one more line, left empty. The tooltip stops drawing at an empty line (RenderTipTextList(), and the modern theme too), and only blank lines came after it, so the tooltip looks the same; the recorded lines lose the empty one. (Corrected: this said "full height, half a line shorter" before; #830 found that the drawing stops there.) Recorded lines, <color> <text>:

 before                                       after
   1 You can achieve special items with ...     1 You can achieve special items with ...
   0 <blank>                                    0 <blank>
   0                                            (gone)

"usable %dtimes" (commit 3):

  • English and Spanish ran the number into the word ("usable 10times").
  • Russian and Tagalog ran it in too, and left "times" in English.
  • Polish already read "do użycia 10 razy" and doesn't change.
  • Indonesian read "time 10 that can be used".

They're fixed in Tooltip.json and in the .resx, which the Chaos Castle ticket and the Santa Village invitation still use.

Wrapping (commit 2): a description line wraps at the description's width, while the old code wrote each of these texts as one row. So a few long translations now take two rows, as every other description does:

  • the Talisman of Mobility's two texts in Polish, Russian, Tagalog and Ukrainian;
  • the Master Seal of Ascension's (13/93) text in Polish;
  • the lucky tickets' text in German.

English is short enough not to wrap, so the recorded snapshot (in English) doesn't show it.

Removed

  • The .resx texts only the durability block used:

    • Durability: [%d]
    • %d%% Combination success rate increase
    • the Varka tickets' two weekday texts
    • the Talisman of Mobility's two texts

    The rest stay: other code uses them, including the charms' numbered texts, which the second item chain also reads (feat(items): the second item chain's cases with values come from the data #829 moves that one).

  • IsCharacterCard(), which nothing calls now.

Not done

  • "usable 1 times": the singular could be a second text with "when": ["durability=1"], but each language needs its own form. That's for a separate change if wanted.
  • The design changed: layouts chosen by match rules, with a per-item "tooltip" override, aren't needed. A layout per item kind would have repeated the 36 stat lines, while per-item description lines with conditions cover every case. The design comment on [Architecture] Data-driven item tooltips: texts, placeholders and values from the item data (phase 8) #815 is updated.

Screenshots

Before (#824 plus the snapshot commit) and after this PR, for a level 400 Dark Knight. They look the same, except the Doppelganger ticket's text fix. The lucky item tickets, the one other visible change, aren't in OpenMU's Season 6 item data, so they're shown as their recorded lines below instead.

Large Healing Potion ×3

A stack's count, from its description (@numberOfItems, when: [durability]).

Legacy theme Modern theme
Before
After
The item's data (number, name, tags, description)
{
  "number": 3,
  "name": {
    "en": "Large Healing Potion"
  },
  "tags": [
    "healingPotion"
  ],
  "description": [
    {
      "text": "@numberOfItems",
      "when": [
        "durability"
      ]
    }
  ]
}

Its shared texts in Tooltip.json (English):

"numberOfItems": "Number of items: {durability}"

Guardian Angel

A pet's life after its step-4 lines (@life, when: [!timed]), with the tag noDurabilityLine.

Legacy theme Modern theme
Before
After
The item's data (number, name, tags, description)
{
  "number": 0,
  "name": {
    "en": "Guardian Angel"
  },
  "tags": [
    "noDurabilityLine"
  ],
  "description": [
    {
      "text": {
        "en": "Absorb 20% of Damage",
        "de": "Absorbiert 20% des Schadens",
        "es": "Absorber daño 20% of",
        "id": "Menyerap Kerusakan 20% of",
        "ja": "ダメージ 20%吸収",
        "pl": "Pochłania 20% obrażeń",
        "pt": "Absorver Dano 20% of",
        "ru": "Поглощение 20% of урона",
        "tl": "Isipsip ang 20% of Pinsala",
        "uk": "Поглинання шкоди 20% of",
        "zh-TW": "吸收20% of傷害"
      }
    },
    {
      "text": {
        "en": "Max HP +50 increased",
        "de": "Max. HP +50 erhöht",
        "es": "HP máximo +50 aumentado",
        "id": "HP Maks +50 meningkat",
        "ja": "最大生命力 +50増加",
        "pl": "Zwiększono maksymalne HP +50",
        "pt": "HP máximo +50 aumentado",
        "ru": "Макс. HP +50 увеличен.",
        "tl": "Tumaas ang Max HP +50",
        "uk": "Макс HP +50 збільшено",
        "zh-TW": "最大生命值+50增加"
      }
    },
    {
      "text": "@life",
      "when": [
        "!timed"
      ]
    }
  ]
}

Its shared texts in Tooltip.json (English):

"life": "Life: {durability}"

Splinter of Armor at 7

Pieces to collect, a text written in place: {durability} / 20.

Legacy theme Modern theme
Before
After
The item's data (number, name, tags, description)
{
  "number": 32,
  "name": {
    "en": "Splinter of Armor"
  },
  "tags": [
    "noDurabilityLine"
  ],
  "description": [
    {
      "text": {
        "en": "{durability} / 20"
      }
    }
  ]
}

Open Access Ticket to Doppelganger

@usableTimes, which reads "usable 1 times" now instead of "usable 1times" (the fix commit).

Legacy theme Modern theme
Before
After
The item's data (number, name, tags, description)
{
  "number": 125,
  "name": {
    "en": "Open Access Ticket to Doppelganger"
  },
  "tags": [
    "cashShop",
    "noDurabilityLine"
  ],
  "description": [
    {
      "text": "@usableTimes"
    }
  ]
}

Its shared texts in Tooltip.json (English):

"usableTimes": "usable {durability} times"

Related issues

Step 5b-3b of #815. Builds on #824, #823, #822, #821, #820, #819, #818, #817, #816 and #813.

Checklist

  • I have read and followed docs/CODING_RULES.md.
  • I have built the project locally (see docs/build/README.md).
    • Windows x64 Release: all 1004 tests pass.
    • New tests cover comparisons, the description text checks and the moved warning.
    • The recorded tooltip test changes only as described above.
    • Changed lines pass clang-format 21.1.8 as CI checks them.
    • In game: tooltip-snapshot of two heroes before and after, and the screenshots above in both themes.
  • Changes are focused on one concern; the diff is as small as it reasonably can be.

The tooltip's damage, defense, magic defense, defense rate, attack and
walk speed, resistance and requirement lines ("(lacking ...)" included),
and the staves', books' and magic swords' wizardry or curse damage
increase and the sceptres' pet attack increase, are data now:
Data/Items/Tooltips/Tooltip.json holds their texts with translations and
the layout "default", which every item uses. RenderItemInfo writes the
layout's lines between the parts that stay code: the name, the item's own
texts and durability, the classes, and the options.

A line shows when every entry of its "when" holds: a built-in value that
is not 0, a state (excellent, twoHanded, skillBook, ...), or an item tag
("tag:sceptre"); "!" turns an entry around. Its color is the first of its
color rules that holds, else its own; "values" binds a placeholder of the
text for the line, so one "(lacking {missing})" serves every requirement.
Unknown texts, conditions, tags, colors and placeholders, translations
with other placeholders, and misplaced sections are load errors, with the
name meant suggested for a typo.

Two item checks of the code are tags: noDamageLine (the Scrolls of
Teleport, Teleport Ally and Soul Barrier) and noLevelRequirement (Loch's
Feather).

The recorded tooltips change for 11 items, both from the old damage
block's TextNum-- when it skipped the line: the eight skill scrolls whose
skill has no damage keep the blank line under their name now, and the
excellent teleport scrolls no longer color that blank line.

The .resx texts only these lines used are gone; the ones other windows
use stay.
Every item's recorded tooltip was at full durability and not timed, so
the durability lines of a stack's count (potions and jewels have no
durability in their data) and the lines a timed item leaves out were
never recorded. Two more variants record them: "count", at a durability
of 3, and "timed", an expired timed item (one that is not expired shows
the time it expires, which depends on the clock).

The hashes are recorded again for the six variants; the tooltip code is
unchanged.
The standard durability line, "Durability: [{durability}/{maxDurability}]",
is a line of the default tooltip layout: shown for an item with a
durability (the old rule, now the state hasDurability) that is not timed
and has no tag noDurabilityLine. The other durability lines are lines of
the items' descriptions: a stack's "Number of items", a pet's "Life", a
ticket's "usable ... times", the Splinter of Armor's "{durability} / 20",
the Transformation Ring's, the Talisman of Luck's, the Varka tickets' and
the Talisman of Mobility's texts, the wing-mix charms' texts and the
lucky item tickets' text. The 57 items with a durability but not the
standard line have the tag noDurabilityLine; the condition with about 20
exceptions is gone.

Description lines take a shared text of the tooltip file ("@life") and
conditions ("when", as a layout line's). A condition can compare a value
with a whole number: "durability=2", "level!=1". A description's shared
text that the tooltip file does not have, or that has a placeholder a
description cannot fill, is a load error; a shared text that neither a
layout nor a description uses is a warning.

Only the Talisman of Mobility's saved location stays code, under its
description's line.

The recorded tooltips of every item, now also with a count and timed,
are unchanged except for the 10 lucky item tickets: the old code wrote an
empty full-height line after their blank line, and they end with the
blank line now.

The .resx texts only these lines used are gone, as is IsCharacterCard,
which nothing calls now.
The tickets' "usable %dtimes" ran the number into the word ("usable
10times") in English, Spanish and Polish, left "times" in English in
Russian and Tagalog, and read "time 10 that can be used" in Indonesian.
The shared text of the tooltip file and the .resx text, which the Chaos
Castle ticket and the Santa Village invitation still use, are fixed in
those languages.
…oltip-layouts

# Conflicts:
#	src/Localization/Game.pl.resx
…ooltip-durability

# Conflicts:
#	tests/data/item_tooltip_snapshot.txt
#	tests/data/test_item_tooltips.cpp
Main dropped the 38 "-J" items and renamed the elf (x,50) and Dark Lord lucky
(x,66) sets, so the snapshot records 911 items and their new tooltips.
…ooltip-durability

# Conflicts:
#	docs/control-socket.md
… line never writes an empty row

As the review of sven-n#813 asked for description texts:
- Tooltip.json's texts (shared texts and layout lines' own texts) get the checks item names get: the English text is
  required (a blank line has none), a language code has only letters, digits and "-", and a translation in a
  language the game has no texts in is a warning (ValidateTooltipTextLocales, when the item data loads).
- A layout line whose text comes out empty in the UI's language writes the tooltip's blank row ("\n"): an empty row
  ends the tooltip. Its row width comes from TextList instead of a literal 99.
…ooltip-durability

# Conflicts:
#	docs/item-data.md
#	src/source/Engine/Object/ZzzInventory.cpp
…names stay English

As for the description: sven-n#843 makes the item database's display locale the item names' language, so the stat and
requirement lines turned English with the names when "Translate item names" is off. They are read in the UI's
language now.
…ooltip-durability

# Conflicts:
#	docs/item-data.md
#	src/source/Engine/Object/ZzzInventory.cpp
@ezequielzacca

Copy link
Copy Markdown
Contributor Author

Thanks, fixed in 8a2fea0. ReadComparison now parses the number with std::from_chars into an int and requires the parse to use up the rest of the text, so every int can be written, from -2147483648 to 2147483647. The condition test adds both bounds, plus inputs that must fail: one past each bound, eleven digits, +2, --2, a lone -, an empty number, spaces before or after, 2x and 1.5. docs/item-data.md now states the range.

#822 now records eleven snapshot variants, after review there. They cover this PR's count and timed (expired) variants, so those two are gone and this PR's snapshot is re-recorded with the eleven. I diffed the full tooltip text against #824: the only changes are the 10 lucky item tickets and the "usable 10 times" fix on the nine tickets that show it, as described above. I've updated the description's first point to match.

…translation's placeholders and another layout
…ooltip-durability

# Conflicts:
#	docs/item-data.md
sven-n#824 merged as a rebuilt history, so the conflicts were resolved by applying this
PR's own changes to main: the layout states it moved to ItemTooltipConditions now
include sven-n#824's strengthRequired/dexterityRequired; the Talisman of Mobility line
it moved out of the durability block keeps main's IsPortalPositionSaved() guard;
the layout test keeps sven-n#824's sceptre tag case (noDamageLine is gone) next to this
PR's comparison checks; the item JSON layout keeps main's LayOutItemJsonText with
this PR's "when" lists.
@ezequielzacca

Copy link
Copy Markdown
Contributor Author

#824 is merged, so I merged main into this branch (a normal merge commit, no history rewrite, since this PR has a review).

#824 landed as a rebuilt history, so I resolved the conflicts by applying this PR's own changes onto main:

Checked: Windows x64 Release with the editor; all 1482 tests pass, and the tooltip snapshot is unchanged. test_item_database_files passes in three random orders, and the quality gate passes.

@Mosch0512 Mosch0512 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: changes requested for one item; the rest is non-blocking. Moving the durability block into data is right:

  • Each old branch has its replacement. I mapped every branch of the old block to the new data:

    • the standard line and its hasDurability state, which is the old bDurExist rule with the same precedence;
    • the 57 noDurabilityLine items;
    • the description lines of the potions, arrows, pets, tickets, charms and talismans.

    The exclusions without a tag (Loch's Feather, the fruits, the character cards, the elixirs) show no line either, since they have no durability in their data or are outside groups 0 to 11 and 13.

  • The Talisman of Mobility's saved location keeps its place. Nothing is written between the description and the new code for that item, and main's IsPortalPositionSaved() guard is kept.

  • The merge with main keeps #824's fixes. The Polish texts, the removed noDamageLine and locale helpers, strengthRequired/dexterityRequired and main's formatting of the #824 blocks are all still there.

  • The removed .resx ids are safe. Nothing else looks up 95, 2296, 2605, 2606, 3105 or 3106, by name or by a computed id.

Required

  • Three items lose their Japanese counter (inline, Group13_Helper.json:1434).

Non-blocking

  • Long translated lines now wrap (inline, Group13_Helper.json:2979).
  • Two comments say a condition can read a stat file table again (inline, ItemTooltipConditions.h:24).
  • Untouched blocks of ZzzInventory.cpp are reformatted, and its BOM is dropped (inline, ZzzInventory.cpp:3201).
  • The description reader copies the layout reader's condition loop (inline, ItemJsonFormat.cpp:464).
  • "@" alone is a silent blank line in a description (inline, ItemJsonFormat.cpp:430).
  • A table used only by a shared text isn't seen by the table checks (inline, ItemDataValidation.cpp:639).
  • The old-code comparison tests now skip every line with a condition (inline, test_item_database_files.cpp:547).

Before merging (not code)

  • The PR text says Polish ran the number into "times". Main's Polish .resx already reads "do użycia %d razy", and the Polish tooltips don't change here.

What I checked:

  • every branch of the old durability block against the new data and conditions;
  • the merge resolution against main's #824 (the files #824 touched and its review fixes);
  • every Lookup by number or computed id for the removed ids;
  • the editor code that reads or copies item descriptions (nothing drops textName or when).

I also compared every item's tooltips in all 11 languages: a local test (not pushed) wrote each item's tooltips in each language for the new Dark Wizard, 176 per item, built once on main and once on this branch. The full text of each differing item showed:

  • the "usable … times" fix in English, Spanish, Indonesian, Russian and Tagalog, and the lucky tickets, as described;
  • the two findings below on Japanese and on wrapping;
  • no other change in any language.

Built on Windows x64 Debug with the editor and the control socket: test_item_database_files passes whole, 222 of 222, in file order and three random orders, and so do test_item_database, test_control_tooltip_commands and test_control_protocol. I didn't run the game.

Comment thread src/bin/Data/Items/Group13_Helper.json Outdated
"description": [
{
"text": {
"en": "{durability} / 20"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Required. The Splinter of Armor, the Bless of Guardian (line 1464) and the Claw of Beast (line 1494) now have only an English text, "{durability} / 20" (/ 10). The old code printed I18N::Game::DD, which is "%d / %d" in every language but Japanese, where it's "%d個/ %d個". With the UI in Japanese, the tooltip changes:

main:  1個/ 20個
here:  1 / 20

Adding "ja": "{durability}個/ 20個" (and / 10個) to the three texts keeps it. The recorded snapshot runs in English, so no test sees it. These three are the only new in-place texts without translations; the other 23 have all 11 languages.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in c4b2e84: the three texts have "ja": "{durability}個/ 20個" (/ 10個 for the Claw of Beast), the old I18N::Game::DD's Japanese form. Other languages read the English text, which is the same %d / %d as before.

},
{
"text": {
"en": "Saves the location with the right-mouse-click.",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking. Description lines wrap at the description width, while the old code wrote each of these texts as one row. So long translations now take two rows:

  • the Talisman of Mobility's two texts in Polish, Russian, Tagalog and Ukrainian;
  • the Master Seal of Ascension's (13/93) text in Polish;
  • the lucky tickets' text in German.

From the language comparison, Polish:

main:  Zapisuje lokalizację po kliknięciu prawym przyciskiem myszy.
here:  Zapisuje lokalizację po kliknięciu prawym
       przyciskiem myszy.

English is short enough not to wrap, so the snapshot doesn't show it. Wrapping is how every other description behaves, so it's probably fine. But the PR says every other tooltip is unchanged, so it's worth listing.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Listed in the PR text now, under the tooltips that changed: the Talisman of Mobility in Polish, Russian, Tagalog and Ukrainian, the Master Seal of Ascension in Polish, and the lucky tickets in German. I kept the wrapping, since it's how every other description behaves.

{
enum class Kind : unsigned char
{
Value, // a built-in value (or {level}, or a table of the item stat file), compared with `number`

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking. This says a value condition can be "a table of the item stat file", and so does AreTooltipConditionsMet's comment (ItemTooltipValues.h:83). #824's review removed that claim, because a condition can't name a table. Here, ReadTooltipCondition stops the name at the : of "table:x", so it's refused with "compares no built-in value". The merge brought the old wording back.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in c4b2e84: both comments (TooltipCondition::Kind::Value and AreTooltipConditionsMet) say a built-in value or {level} again, as #824's review left them.

else
if (Level == 1)
TextListColor[TextNum] = TEXT_COLOR_RED;
else if (Level == 1)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking. Three blocks this PR doesn't otherwise change are reformatted:

  • the chocolate boxes (3198–3211);
  • the Box of Luck (3216–3229);
  • the Armor of Guardsman's Chaos Castle table (3278–3315).

Line 1 also loses the file's UTF-8 BOM. With /utf-8 on MuClient the Korean literals still compile the same, so it's harmless. But these blocks add unrelated lines to the diff, as the ones #824 reverted did.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in c4b2e84: the chocolate boxes, the Box of Luck and the Armor of Guardsman's Chaos Castle table are back to main's formatting, and the BOM is back, so the file's diff is only this PR's change.

}

// The conditions a description line is shown on, all of them: a list of texts such as "durability" or "!timed".
void ItemReader::ReadDescriptionConditions(const OrderedJson& json, const std::string& field, ItemDescriptionLine& line)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking. ReadDescriptionConditions is the same loop as ItemTooltipReader::ReadConditions: a list check, a string check per entry, ReadTooltipCondition, push. Only the error messages differ slightly. A shared ReadTooltipConditions(json, field, conditions, addError) next to ReadTooltipCondition would keep the two readers from drifting.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in c4b2e84: ReadTooltipConditions sits next to ReadTooltipCondition (in ItemTooltipConditions.cpp, declared in a small ItemTooltipConditionsJson.h so the headers that include the conditions don't take in the JSON library). Both readers call it; the error texts are unchanged.

[this](const std::string& errorField, const std::string& message)
{ AddIssue(ItemDataIssueSeverity::Error, errorField, message); });
bool read = true;
if (text->is_string() && text->get<std::string>().starts_with("@"))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking. A description text of just "@" gives an empty textName:

  • ValidateDescriptionTexts skips empty names;
  • the tooltip writes the line as a blank line.

So a typo like {"text": "@"} loads without a message. In a layout, the same text is an error ("@" is not a text of "texts"). An empty name after the @ could be the same error here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in c4b2e84: "@" alone is an error now ("names no text"), as in a layout. A test covers it and a named one.

const PlaceholderScan scan = ScanPlaceholders(text->GetNeutral());
for (const std::string& placeholder : scan.names)
{
if (!IsBuiltInPlaceholder(placeholder) && !GetPlaceholderValue(placeholder, 0, profiles))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking. A shared text used by a description may have a {table:…} placeholder; this check allows it. But the table checks only look at the descriptions' own texts:

  • ValidateTableUses warns about the table as unused;
  • the editor's table counts (DescriptionNamesTable, FindTableDescriptionUsers) don't count it, so the Formulas window offers to delete it;
  • RenameTableInDescriptions leaves the shared text with the old name, which makes the next load fail.

No shipped shared text uses a table today. Refusing tables in shared texts would keep that true until the table checks know about them.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in c4b2e84, as you suggest: a description's shared text takes built-in values only, with an error saying a table goes in the item's own text, where the table checks see it. ValidateDescriptionTexts doesn't need the stat profiles anymore, so it lost that parameter. The shared-text test checks a table.

Comment thread tests/data/test_item_database_files.cpp Outdated
{
if (line.IsShownAt(level))
// Not the durability lines, which came from another part of the old code.
if (line.IsShownAt(level) && line.textName.empty() && line.when.empty())

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking. Both old-code comparison tests now skip every description line with a when or a shared text (also line 409). Today those are exactly the durability lines. But a later non-durability line with a condition would drop out of the comparison silently. Skipping by what the line is (the shared texts and the durability conditions this PR adds) would keep the tests' reach.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in c4b2e84: both tests skip by what the line is: IsDurabilityLine is a shared text or a line shown by the item's durability (durability, durability=2, ...). A later line with another condition stays in the comparison.

- The Splinter of Armor, the Bless of Guardian and the Claw of Beast keep their
  Japanese counter ("{durability}個/ 20個"), as the old I18N::Game::DD had it.
- The condition comments no longer say a condition can name a stat file table.
- ZzzInventory.cpp's untouched blocks are back to main's formatting, with its
  BOM.
- The item and tooltip readers share ReadTooltipConditions
  (ItemTooltipConditionsJson.h).
- A description's "@" alone is an error, as in a layout, not a blank line.
- A description's shared text takes built-in values only: the table checks
  don't see a shared text, so a table there would go unseen by the unused-table
  warning and the editor's counts and renames. ValidateDescriptionTexts drops
  its stat profiles.
- The old-code comparison tests skip just the durability lines (a shared text,
  or a line shown by the item's durability), not every line with a condition.
@ezequielzacca

Copy link
Copy Markdown
Contributor Author

Thanks for the thorough review. Pushed c4b2e84 as a new commit on top (no history rewrite):

  • Required: the three texts keep their Japanese counter.
  • Non-blocking, done:
    • the wrapping is listed in the PR text;
    • the two comments no longer claim stat tables;
    • ZzzInventory.cpp's untouched blocks and its BOM are as on main;
    • both readers share ReadTooltipConditions;
    • "@" alone is an error;
    • shared texts take built-in values only;
    • the old-code tests skip just the durability lines.
  • PR text: the Polish claim is corrected (it already read "do użycia %d razy" and doesn't change), and the Russian and Tagalog line now says they also ran the number in.
  • Checked: Windows x64 Release with the editor and the control socket: all 1483 tests pass, test_item_database_files in three random orders, and the quality gate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants