# Anti-cheat off ## Request (2026-10-25) The Gladiator (Character03, level 106) "randomly exploded" fighting an underleveled dragon on Silber. The user: the cheater detection is not necessary, remove it. ## Measured A temporary damage log showed the hero at full health (17200) going to 0 in one tick, with the game logging `cheat statBonus 0/3`, `cheat SkillLevel 0..7`, `Hase!` and `cObjectManager::destroy: tried to delete local hero #1!`; the hero came back with 1199 health and died to the next hit. - The game mirrors the local hero's fields on a protected page (pointers `0x182cddc`, second copy `0x182cde0`): +0 hero +0x3b4, +4 hero +0x3ee (gold), +8 hero +0x3fe (u16), xor-ed with the hero's key byte (+0x38) repeated four times (the second copy: key << 1); +0xc a raw copy of hero +0x3b0..+0x49d (attributes, skill levels). Writer: `0x603d9c` and other places after legitimate changes, all starting with `VirtualProtect(page, 0x1000, PAGE_READWRITE)` and ending with `0x201`. - Checks: `cCreature::Think` about once in 101 ticks (`rand() % 101 == 10`, `0x5389b5`), `VerifyHeroMirror` `0x5905f0` (callers `0x57fc71`, `0x580001`, `0x580331`, `0x61ce22`), inline copies at `0x4659f6`, `0x564c6f`, `0x57e09c`, `0x585bd0`, `0x619d33`, and a trap in Think (`0x5385a6`: a creature whose level exceeds its experience by more than 3 gets fields raised behind the mirror's back). A mismatch resets the field (attributes 1, skill levels 0); any mismatch, or no hero at all, kills the hero ("*** Cheater detected! ***", health 0, action dying) and sets the cheater flag `0x182cdd0`, saved in the hero file (record +0xf3, `0x604409`) and read back by loadHero (`0x6066eb`). - Stream checks in the quest manager's hero data (`0x465980`): a marker `0xfea4fea4` (`0x467782`) and three stored values compared with the hero (`0x46a60b`, `0x46a64e`, `0x46a696`). - In the failing log every skill level mismatched: the mirror was stale (changes outside the game's mirror writers, e.g. the shared hero loaded into another world). ## Mod (`src/mods/anticheat.cpp`) - `VirtualProtect` hook: when the mirror page is made writable, the mirror is rewritten from the current hero first. Checks then compare the hero with itself; writers overwrite it as before. The game's control flow is unchanged (skipping the inline checks would not be safe: code after some of them uses registers they set). - Patches: the stream checks' jumps past the punishment are unconditional; loadHero never sets the cheater flag (a flagged character is clean after its next save). Confirmed by the user 2026-10-25 (attributes fine, no more exploding).