Arts are objects (game::Art) built from the game's definitions: name, launch type, damage source, regeneration group and the skills' art lists. The tooltip gets one line per effect of a skill or attribute, sorted by size; unlearned class skills are greyed out at 0%. Weapon arts list only the damage types the held weapon deals and the held weapon's skill. Tooltip line wrap ignores colour codes; art tooltips wrap wider. Blitzschlag's tooltip rewrite becomes a tooltip filter. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
119 lines
6.8 KiB
Markdown
119 lines
6.8 KiB
Markdown
# What improves an art (mods/arttooltip.cpp)
|
||
|
||
Request of 2026-10-18: "edit ALL skill tooltips, to show which attributes and
|
||
abilities improve them in which way".
|
||
|
||
Follow-ups the same day: arts as objects carrying their effects, name and
|
||
tooltip, no art-id checks in code; a dense block, one line per Fertigkeit or
|
||
attribute ("Stärke -> Schaden +12%"); only skills and attributes that act on
|
||
the art; unlearned skills (of the hero's class) with 0% and greyed out;
|
||
lines sorted by impact. Then: only "Regenerationszeit" (faster
|
||
regeneration rates are shown as the time they save), no attribute flavor
|
||
texts; one line per effect (an attribute with two effects gets two lines,
|
||
each sorted by its own size); a wider tooltip so the lines don't wrap.
|
||
|
||
## Design
|
||
|
||
- `game::Art` (game/engine/art.{h,cpp}): built on demand by `FindArt(id)`
|
||
from the game's definitions (name text SpellDef / CombatMoveDef +4, launch
|
||
type, spell or weapon damage values, regeneration group).
|
||
`Improvements(creature)` gives every (skill or attribute, stat, percent)
|
||
acting on the art for that hero; `Tooltip` = the game's text, the mods'
|
||
filters (`AddTooltipFilter`, e.g. Blitzschlag's values), then the block.
|
||
- Art ids appear only in data: the game's per-skill art lists and three
|
||
exceptions (Energieblitze regenerates as magic; 0x3fa and 0x38 take weapon
|
||
damage factors), both in art.cpp.
|
||
- Weapon skills count only with their weapon in hand (the game's checks
|
||
0x54a3e0 / 0x54a220 / 0x54a2f0 / 0x54a2e0 / 0x54a110, weapon class); only
|
||
the skills of the weapon in hand are listed. Their second curve (SP) is the attack speed
|
||
(+0x3c; the skill text labels it with text 0x44c, the same "speed" text the
|
||
magic schools use for +0x3e).
|
||
- mods/arttooltip.cpp hooks ArtTooltip and hands the text to the art.
|
||
- Width: tooltips with flag 0x80 wrap in cUI_Tooltip::FormatText
|
||
(`0x6e6630`): the first space after 45 characters of a line becomes a line
|
||
break (`cmp ecx, 5Ah` on the line's bytes at `0x6e687d`); the layout
|
||
(`0x6e7730`) then sizes the window to the longest line + 8. Colour codes
|
||
(`\cAARRGGBB`, 10 characters) counted there; the mod replaces the check so
|
||
they don't, and texts containing "Verbessert durch:" wrap after 56.
|
||
|
||
|
||
## Sources
|
||
|
||
Texts: `scripts/us/global.res` holds the German texts (despite the folder):
|
||
`"SZ"`, then 16-byte entries {key hash, offset, 0, length}, the UTF-16 text at
|
||
offset + 4. Skill names are game text `0x24b7 + skill id` (character panel
|
||
`0x6abc8d`); attribute names `UI_ATTRIB_STRENGTH`, `_RESISTANCE`,
|
||
`_GESCHICK`, `_PHYREG`, `_MAGREG`, `_CHARISMA`.
|
||
|
||
Skill ids (0x565f30's switch, names in file order): 1 Himmelsmagie,
|
||
2 Waffenkunde, 3 Stangenwaffen, 4 Schwertkunde, 5 Axtkampf,
|
||
6 Zwei-Waffen-Kampf, 7 Fernkampf, 8 Wendigkeit, 9 Parade, 0xa Konstitution,
|
||
0xb Rüstung, 0xc Meditation, 0xd Klingenkampf, 0xe Magiekunde, 0xf
|
||
Feuermagie, 0x10 Wassermagie, 0x11 Erdmagie, 0x12 Luftmagie, 0x13 Mondmagie,
|
||
0x14 Vampirismus, 0x15 Handel, 0x16 Reiten, 0x17 Entwaffnung, 0x18
|
||
Faustkampf, 0x19 Konzentration, 0x1a Ballistik, 0x1b Fallenkunst, 0x1c
|
||
Blutrausch, 0x1d Waffentechnik, 0x1e Zweihandwaffen, 0x1f Zwergenkunde, 0x20
|
||
Höllenmacht, 0x21 Schmiedekunst.
|
||
|
||
Balance values (globals `0xad2400..`, parsed as `key=value` around `0x5eb4xx`;
|
||
no Balance.txt ships, so the defaults stand). Skill curves are 12-byte
|
||
{start `<k>off`, half `<k>_s`, limit `<k>_w`} at `0xad2450 + 12 n`: WK
|
||
Waffenkunde, MK Magiekunde, FK/SK/AK/KK/STK/BK/FEK weapon skills (AW / SP),
|
||
HM/FM/EM/WM/LM/MM schools, BA, BL, KO Konzentration, Med Meditation, W, HR,
|
||
HP, P, R (resistances), then the price tables; HOM `0xad368c`, WT `0xad3698`.
|
||
Value(level) = 0 below 1, else start + 2 (limit − start)(1 − 1/((level − 1)/half + 1))
|
||
percent (DiminishingCurve `0x565c30`).
|
||
|
||
## How the game applies them
|
||
|
||
cCreatureArts::Recalculate (`0x579560`), then ApplySkill (`0x565f30`) per
|
||
skill row with level = bought + item levels:
|
||
|
||
- Attributes (+0x10 u16[6]) = invested (+0x1c) + base (+0x4a) + base ×
|
||
(level − 1) / 10, plus items. Hero level +0x56.
|
||
- Damage factors, 4 types (physical, fire, magic, poison):
|
||
weapon / combat arts +0x96 + +0xa6, spells +0x96 + +0xb6 (ArtTooltip
|
||
multiplies spell values by these; arts 0x3fa and 0x38 by the combat ones).
|
||
+0x96 = 1 + items. Attribute shares with F = (156 − BalStatOff) × level / 156
|
||
+ BalStatOff + 9 and invested points p, base b, item points q:
|
||
- +0xa6 physical: (b F/10 + p + q) of Stärke, or Geschick when
|
||
HoldsRangedWeapon (`0x54a110`), / BalCharPD
|
||
- +0xaa fire: (2 p + b F/10 + q) of Stärke and Geschick / BalCharFD
|
||
- +0xae magic: (b F/10 + p + q) of Mentale Regeneration / BalCharMD
|
||
- +0xb2 poison: (2 p + b F/10 + q) of Widerstand and Charisma / BalCharGD
|
||
- +0xb6..+0xc2 spells: (b F/10 + p) of Mentale Regeneration / BalCharMD
|
||
- Waffenkunde adds its % to +0xa6..+0xb2, Magiekunde to +0xb6..+0xc2.
|
||
- Regeneration rates: +0xee magic = (1 + items + Meditation %) × (1 +
|
||
Mentale Regeneration / 100), +0xf2 combat = (1 + items) × (1 + Physische
|
||
Regeneration / 100). Creature type 8 (Zwerg) gets +0xee = +0xf2.
|
||
- Regeneration time: ApplySkillToArts (`0x565c80`) divides each listed art's
|
||
cooldown total by 1 + value / 100. With the attack flag it also adds curve
|
||
FEK..SP (`0xad2504`) to +0x3e while the art is the selected art slot. Lists
|
||
(art ids) per skill:
|
||
- Himmelsmagie (HM, attack): d f 11 12 13 14 15 16 3fb
|
||
- Feuermagie (FM, attack): 5 b 17 18; Wassermagie (WM): 1b 4 22 23;
|
||
Erdmagie (EM): 2 10 19 1a; Luftmagie (LM): 1 1c 1d 21;
|
||
Mondmagie (MM): 3 7 24..2a
|
||
- Vampirismus (KO): 3ff 401 403 405 40e..411 408 2b 406 407 409..40d
|
||
- Konzentration (KO): 3e8..3fa 3fc 421..434 41e 3fe 400 402 404 412..416
|
||
443 446 444 449 44e 44a 44d 44b 44f 44c 436 437 438 43a 43b 43c 441
|
||
- Ballistik (BA, attack) and Fallenkunst (KO): 417..41d
|
||
- Blutrausch (BL, attack): 3fe 2b 408 406 407 409..40d
|
||
- Waffentechnik (WT, attack) and Zwergenkunde (KO): 43f 43e 43d 37..3b
|
||
- Höllenmacht (HOM): 3c..43
|
||
- The weapon skills (Stangenwaffen, Schwertkunde, Axtkampf, ...) raise the
|
||
attack value (+0xe6, AW curve) and attack speed (+0x3c, SP curve) while
|
||
their weapon is held; listed for weapon arts with that weapon in hand.
|
||
- The held weapon's damage per type (physical, fire, magic, poison) is at
|
||
cCreatureArts +0x76 + 4 t (max) and +0x86 + 4 t (min); the damage range
|
||
functions (0x563e90 .. 0x564160) multiply them by +0x96 + +0xa6 + 4 t. The
|
||
attributes' damage lines are listed only for the types the weapon deals.
|
||
|
||
Measured 2026-10-18 (diag log): +0xa6..+0xb2 and +0xb6 equal the sums of the
|
||
listed shares exactly (e.g. 5.422 = Waffenkunde 300.96% + Stärke 241.21%),
|
||
Physische Regeneration matches +0xf2 / (1 + items).
|
||
|
||
Art definitions: ArtSpellDef (arts.h) as ArtTooltip finds the spell values
|
||
(own SpellDef, or the one CombatMoveDef::LinkedSpell `0x4d1c50` names);
|
||
damage values 4 × (base, per level) s16 at SpellDef +0x42.
|