Files
sacred_k/docs/survival-bonus.md
2026-10-18 03:26:10 +02:00

51 lines
2.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Survival bonus (Überlebensbonus)
Request (2026-10-18): "how is survival bonus calculated? please reset the
death counter on battlemage savegame and restore the survivability bonus".
## Where it shows
The tooltip of the Waffe / Kampfkunst / Resistenz block in the character
window (`cUI_StatisticsChar::Render` 0x6a9be0), only while the bonus is above
0. Text key "1159" (id 0x4407730). Text keys are numbers or names hashed by
`TextKeyHash` 0x80e010: `h = (h * 113 + toupper(c)) % 999999991`, then
`& 0x7fffffff`. `TextManager::GetTextByKey` 0x672fd0 looks them up.
## Formula
`cStatsManager` (one record at 0xaa3518, `cStatsManager::Instance` 0x425160)
keeps the time survived in ms at +0x570c. With m = whole minutes survived:
bonus % = 0 for m < 1
= 100 * (1 - 1 / ((m - 1) / 120 + 1)) otherwise
That is `DiminishingCurve` 0x565c30 (min 0, half 120, max 50, doubled). It
gives 50 % after 2 h and 75 % after 6 h, approaching 100 %. The experience for
a kill uses the same curve (0x534454), scaled by a global factor at 0xad362c.
The window adds 10 × a difficulty factor (1.34 / 1.67 / 2 / 2.34) when a hero
byte (+0x4f8 array, index 0x1c) is at least 6; what that byte means is not
known yet.
Measured: the survival time only grows in combat. `cStatsManager::AddTime`
(0x424930, (float s, alive), ret 8) is called from the engine tick (0x60e732)
with alive = hero +0x200 bit 0x8000. 0x547ce6 sets that bit while 0xad1c64 is
below 350 (or 1000), and 0x547ed8 clears it otherwise. 0xad1c64 is most
likely the distance to the nearest enemy. The play time (+0x56f8 h, +0x56fc
min, +0x5700 ms) always grows.
A death (`cStatsManager::OnHeroDeath` 0x4245a0, called from
`cCreature::ReceiveOrder`) counts one at +0x56f4 and zeroes the survival time.
## In the save game (GAME0x.PAK, uncompressed)
- Header ("AMS", version 0x1b) at the start: survival time in seconds at
0x44, loaded by `cEngine::load` 0x61b790 through
`cStatsManager::SetSurvivalSeconds` 0x424540.
- The statistics block (`cStatsManager::Serialize` 0x424ce0) ends with the
magic 0xF00DF00D. The deaths are 26 bytes before the magic, the play
hours 22, the minutes 18 and the ms 14.
- `ItemDataMgr::saveHero` 0x6046f0 appends a 0x22c-byte hero header (name in
UTF-16 at +0x48) and a 0x40-byte block (deaths, survival seconds, spawn
counter). The block is all zeros in single-player saves and is not where
the survival time is loaded from.