Restore Vitae's omitted penalty paragraph, replace the invented character summary with gmCharacterInfoUI's ordered report and property meanings, preserve authored translucent body surfaces, and initialize the end-session button in its visible Normal DAT state. Release build and all 5,830 tests pass with five intentional skips. Connected visual gate pending. Co-authored-by: OpenAI Codex <codex@openai.com>
128 lines
4.3 KiB
Markdown
128 lines
4.3 KiB
Markdown
# Retail Vitae and Character Information pseudocode
|
|
|
|
Sources: Sept. 2013 named retail client, installed `local_English.dat`, and the
|
|
matching v11.4186 executable. String keys are resolved from StringTable
|
|
`0x23000001`; duration formatting is StringTable `0x23000006`.
|
|
|
|
## Vitae
|
|
|
|
`gmVitaeUI::Update @ 0x004A7400`
|
|
|
|
```text
|
|
vitae = current Vitae enchantment modifier, or 1.0
|
|
lost = 100 - trunc(vitae * 100)
|
|
|
|
if lost <= 0:
|
|
mainText = ID_Vitae_Text_Full
|
|
else:
|
|
mainText = ID_Vitae_Text_Vitae(lost)
|
|
mainText += ID_Vitae_Text_Skills(lost)
|
|
remaining = VitaeCPPoolThreshold(vitae, deathLevel) - currentPool
|
|
mainText += ID_Vitae_Text_Experience(remaining)
|
|
```
|
|
|
|
The skills paragraph is not optional. It explains that health, stamina, mana,
|
|
and skills are reduced by the same percentage and warns about penalties above
|
|
15 percent.
|
|
|
|
## Character Information
|
|
|
|
`gmCharacterInfoUI::Update @ 0x004BA790` clears `m_pMainText`, appends six
|
|
sections, and inserts one empty `StringInfo` between each section:
|
|
|
|
```text
|
|
UpdatePlayerBirthAgeDeaths
|
|
blank
|
|
UpdateEnduranceInfo
|
|
blank
|
|
UpdateInnateAttributeInfo
|
|
blank
|
|
UpdateFakeSkills
|
|
blank
|
|
UpdateAugmentations
|
|
blank
|
|
UpdateLoad
|
|
```
|
|
|
|
It does not prepend character name, level, race, title, current vitals, or
|
|
invented section headings.
|
|
|
|
### Birth, play time, and deaths
|
|
|
|
`gmCharacterInfoUI::UpdatePlayerBirthAgeDeaths @ 0x004B8CB0`
|
|
|
|
```text
|
|
if PropertyInt 0x62 exists:
|
|
append ID_CharacterInfo_Birth(strftime("%c", localtime(value)))
|
|
if PropertyInt 0x7D exists:
|
|
append ID_CharacterInfo_Played(TimeUtils::QueryDuration(value))
|
|
|
|
deaths = PropertyInt 0x2B, default 0
|
|
append the None / One / Two string for 0 / 1 / 2
|
|
otherwise append ID_CharacterInfo_Deaths_Many(deaths)
|
|
```
|
|
|
|
`TimeUtils::QueryDuration @ 0x00684170` divides seconds into 365-day years,
|
|
30-day months, seven-day weeks, days, hours, minutes, and seconds. Zero units
|
|
are omitted by `ID_DurationFormat`.
|
|
|
|
### Resistance grades
|
|
|
|
`gmCharacterInfoUI::UpdateEnduranceInfo @ 0x004B8EB0`
|
|
|
|
```text
|
|
strength = current Strength
|
|
endurance = current Endurance
|
|
|
|
resist = grade(strength + endurance,
|
|
[200, 260, 320, 380, 440])
|
|
regen = grade(strength + 2 * endurance,
|
|
[200, 346, 470, 580, 690])
|
|
|
|
grade values in ascending order:
|
|
None, Poor, Mediocre, Hardy, Resilient, Indomitable
|
|
|
|
append ID_CharacterInfo_Resists(RESIST=resist, REGEN=regen)
|
|
```
|
|
|
|
The localized template uses `RESIST` for both the Natural and Drain lines and
|
|
`REGEN` for the Regeneration Bonus line.
|
|
|
|
The literal grades and thresholds were verified from the matching executable
|
|
at `0x00794028` and `0x007B1EB8..0x007B1EE8`.
|
|
|
|
### Innates and fake skills
|
|
|
|
`UpdateInnateAttributeInfo @ 0x004B87E0` appends the six innate values in the
|
|
order Strength, Endurance, Coordination, Quickness, Focus, Self.
|
|
|
|
`UpdateFakeSkills @ 0x004B8930` appends PropertyInt `0xB5` as Chess Rank and
|
|
PropertyInt `0xC0` as Fishing Skill. These are not skill-credit counters.
|
|
|
|
### Augmentations and load
|
|
|
|
`UpdateAugmentations @ 0x004B9000` emits only earned mastery, luminance, and
|
|
augmentation lines. It emits no `Augmentations` heading and no `None` line.
|
|
The first three mastery properties are `0x162`, `0x163`, and `0x16A`; ordinary
|
|
augmentation counts are read from their individual PropertyInt qualities.
|
|
|
|
`UpdateLoad @ 0x004B8A20` computes retail encumbrance capacity from Strength
|
|
and PropertyInt `0xE6`. Below 100 percent load it appends the not-overburdened
|
|
sentence. At or above 100 percent it appends excess burden and the Run/Jump/
|
|
defense reduction. When `0xE6` is positive it also appends the Seventh Mule
|
|
augmentation sentence.
|
|
|
|
## Panel surface and quit button
|
|
|
|
The Character Information and Vitae child layouts author a full-height
|
|
`0x06004CC2` center surface beneath their text. The Positive Effects child does
|
|
not; it relies on its enclosing shared panel surface. When mounting those child
|
|
layouts in acdream's standalone shared window, the outer chrome must not paint
|
|
a second center surface over an already-authored one. Two translucent center
|
|
layers compound into the opaque-looking result reported in-client.
|
|
|
|
The quit control is the ordinary button `0x100000FA` in LayoutDesc
|
|
`0x21000071`. Its DAT default is state 1 (`Normal`) with RenderSurface
|
|
`0x06007BB1`; state 3 is the pressed surface. `gmIndicatorsUI` does not own a
|
|
hover-only visibility rule, so the retained button must enter Normal during
|
|
controller initialization, before pointer input.
|