# 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. Every integer above is inserted with `StringInfo::AddVariable_Int`. Its `LInt_StringInfoData::ToString @ 0x0042F7E0` calls `NumToString` with grouping enabled, so recovery XP is rendered with the client language's thousands separator (for English, `61,000,000`, never `61000000`). ## 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.