feat(ui): complete retail item appraisal reports
Restore the authored examination geometry and top-origin item list, then port retail's ordered weapon, armor, magic, requirement, capacity, cooldown, use, and description branches into a dedicated formatter with DAT spell prose. Keep the remaining specialized display-name and preview gaps explicit in AP-110. Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
parent
d96ea2de98
commit
bc47bc4917
9 changed files with 1587 additions and 297 deletions
|
|
@ -329,6 +329,143 @@ this order:
|
|||
9. caster/boost/healer/capacity/lock/mana/uses/craftsman details;
|
||||
10. sale restriction, rare status, full magic, and description.
|
||||
|
||||
The individual branches are not a generic property dump. They project the
|
||||
wire profile into retail prose:
|
||||
|
||||
```text
|
||||
ShowWeaponAndArmor(validLocations, profile):
|
||||
ammoType = live PublicWeenieDesc ammo type
|
||||
if object is a hook:
|
||||
ammoType = HookProfile ammo type
|
||||
|
||||
if validLocations contains Shield:
|
||||
append "Base Shield Level: <ArmorLevel>"
|
||||
append the player-dependent effective Shield level when available
|
||||
|
||||
if validLocations contains a weapon location:
|
||||
weapon = profile.WeaponProfile
|
||||
append "Skill: <WeaponSkill>"
|
||||
if WeaponType exists:
|
||||
append the parenthesized weapon subtype
|
||||
|
||||
launcher = validLocations contains MissileWeapon and ammoType != None
|
||||
append launcher ? "Damage Bonus: " : "Damage: "
|
||||
minimum = (1 - DamageVariance) * Damage
|
||||
if Damage - minimum > 0.0002:
|
||||
append "<minimum> - <maximum>"
|
||||
else:
|
||||
append "<maximum>"
|
||||
append damage type for non-launchers
|
||||
|
||||
append Elemental Damage Bonus when present
|
||||
append launcher Damage Modifier when present
|
||||
|
||||
if validLocations contains MeleeWeapon, MissileWeapon, or TwoHanded:
|
||||
append "Speed: <category> (<raw weapon time>)"
|
||||
categories:
|
||||
raw < 11 -> Very Fast
|
||||
raw < 31 -> Fast
|
||||
raw < 50 -> Average
|
||||
raw < 80 -> Slow
|
||||
otherwise -> Very Slow
|
||||
|
||||
if launcher:
|
||||
rangeYards = min(
|
||||
85,
|
||||
2 * MaxVelocity^2 * (1 / 9.8) * 1.094)
|
||||
if rangeYards < 10:
|
||||
displayedRange = ceil(rangeYards)
|
||||
else:
|
||||
displayedRange = truncate down to a multiple of 5
|
||||
append "Range: <displayedRange> yds."
|
||||
if MaxVelocityEstimated:
|
||||
append " (based on STRENGTH 100)"
|
||||
|
||||
if WeaponOffense != 1 and this is not launcher damage:
|
||||
append "Bonus to Attack Skill: <signed percent>."
|
||||
|
||||
append the retail ammunition sentence:
|
||||
ammunition -> "Used as ammunition by bows/crossbows/atlatls."
|
||||
launcher -> "Uses arrows/quarrels/atlatl darts as ammunition."
|
||||
|
||||
ShowArmor(profile):
|
||||
append "Armor Level: <base AL>"
|
||||
for Slashing, Piercing, Bludgeoning, Fire, Cold, Acid, Electric, Nether:
|
||||
adjective from DamageResistanceToString:
|
||||
0.0 -> None
|
||||
(0.0, 0.4) -> Poor
|
||||
[0.4, 0.8) -> Below Average
|
||||
[0.8, 1.2) -> Average
|
||||
[1.2, 1.6) -> Above Average
|
||||
[1.6, 2.0) -> Excellent
|
||||
>= 2.0 -> Unparalleled
|
||||
append "<damage>: <adjective> (<base AL * modifier, rounded>)"
|
||||
|
||||
ShowMagic(profile):
|
||||
if the spellbook exists and appraisal failed:
|
||||
append "Spells: unknown."
|
||||
return
|
||||
|
||||
split spell ids by the high enchantment bit
|
||||
resolve every id with that bit masked through ClientMagicSystem
|
||||
|
||||
for ordinary spells:
|
||||
append Spellcraft, Mana, and Mana Cost when present
|
||||
append "Spell Descriptions:"
|
||||
append each spell name and its DAT description
|
||||
|
||||
for high-bit enchantments:
|
||||
append "Enchantments:"
|
||||
append each spell name and its DAT description
|
||||
|
||||
ShowSpecialProperties(profile):
|
||||
append carry limit and authored cooldown duration when present
|
||||
append cleave count
|
||||
build one "Properties: " line from:
|
||||
creature slayer, Multi-Strike, imbued-effect flags,
|
||||
Magic Absorbing, Unenchantable, Attuned/Bonded/death behavior,
|
||||
Retained, Crushing Blow, Biting Strike, Armor/Resistance Cleaving,
|
||||
Cast on Strike, Ivoryable, and Dyeable
|
||||
if an imbued-effect flag exists:
|
||||
append "This item cannot be further imbued."
|
||||
if AutowieldLeft:
|
||||
append the left-hand tether sentence
|
||||
|
||||
ShowRemainingItemFields(profile):
|
||||
append, in SetAppraiseInfo order:
|
||||
usage text
|
||||
level, direct heritage restriction, and wield requirements
|
||||
(up to four requirement triplets)
|
||||
use restrictions
|
||||
item level and item XP
|
||||
activation requirements
|
||||
caster, boost, healing, capacity, lock, and mana-stone data
|
||||
remaining key/charge counts
|
||||
creator, last tinkerer, and imbuer
|
||||
cannot-be-sold and rare notices
|
||||
short and long descriptions
|
||||
```
|
||||
|
||||
Sources:
|
||||
|
||||
- `ItemExamineUI::SetAppraiseInfo @ 0x004B72B0`
|
||||
- `ItemExamineUI::Appraisal_ShowWieldRequirements @ 0x004AF9A0`
|
||||
- `ItemExamineUI::Appraisal_ShowSpecialProperties @ 0x004B0140`
|
||||
- `ItemExamineUI::Appraisal_ShowWeaponAndArmorData @ 0x004B10E0`
|
||||
- `ItemExamineUI::Appraisal_ShowArmorModsData @ 0x004B1F60`
|
||||
- `ItemExamineUI::Appraisal_ShowMagicInfo @ 0x004B2E10`
|
||||
- `ItemExamineUI::Appraisal_ShowActivationRequirements @ 0x004B3270`
|
||||
- `AppraisalSystem::WeaponTimeToString @ 0x005B4970`
|
||||
- `AppraisalSystem::DamageResistanceToString @ 0x005B5490`
|
||||
- `AppraisalSystem::InqWorkmanshipAdjective @ 0x005B48E0`
|
||||
- `ClientUISystem::DeltaTimeToString @ 0x00565E10`
|
||||
|
||||
ACE's `AppraiseInfo` serializer and property enums were used to pin the
|
||||
typed-table IDs carried by the network profile. ACViewer's portal.dat
|
||||
SpellTable path was used as the second reference check that item spell names
|
||||
and descriptions come from DAT spell metadata rather than a hand-maintained
|
||||
client list. Retail's named functions remain the behavioral oracle.
|
||||
|
||||
The main text and inscription areas use their authored scrollbars. A newly
|
||||
selected object resets those scroll positions to the top; a refresh of the
|
||||
same object preserves the user's position.
|
||||
|
|
@ -344,6 +481,14 @@ Inventory/Skills/Spellbook panel.
|
|||
`gmFloatyExaminationUI::ResizeTo` delegates to ordinary `UIElement::ResizeTo`
|
||||
and persists width/height; it adds no special resize algorithm.
|
||||
|
||||
The authored root is exactly 310 by 400 pixels and has 310-by-400 minimum
|
||||
constraints. Its maximum constraints are 2000 by 2000, so 310 by 400 is the
|
||||
retail opening/default size, not a fixed-size panel. The main item report
|
||||
control is authored with bottom vertical justification, but
|
||||
`ItemExamineUI::AddItemInfo` appends rows from the start of the cleared text
|
||||
surface. The retained projection must therefore lay out that generated report
|
||||
from the top while leaving the separate authored inscription behavior intact.
|
||||
|
||||
## Inscription presentation and eligibility
|
||||
|
||||
```text
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue