// Escorted NPCs stay on the hero's follower list (2026-10-26, docs/quests.md). // "Furchtbares Verbrechen" (quest 9008) did not go on at its target point: // the NPC walked after the hero, but the script's test there ("@npc", 0x498aa0 // case 0x40) looks the NPC up in the hero's follower list (hero +0x39c), and // that list was empty (measured on Borf's save: NPC 0x1fa with leader 1 and // the follow bit, no followers on the hero). The NPC keeps its side of the // escort (leader +0x251, status bit 4) across a load; the hero's list does // not come back. The mod adds every NPC that follows a hero but is missing // from its list back with the game's own AddFollower (0x54b070), with the // entry the follow order uses ({id, 1, 1}), once after loading. #include #include "game/engine/events.h" #include "game/engine/objects.h" #include "game/engine/orders.h" #include "re/log.h" namespace mods::followers { namespace { constexpr int kTicksAfterStart = 30; // Small town NPCs run after the hero for a few seconds (status 0x404, leader // the hero) without joining his list (measured 2026-10-26: types 0x2be, // 0x2c0); they are not escorts. constexpr int32_t kStatusTagAlong = 0x400; int g_ticksToCheck = -1; int32_t Field(const void* creature, size_t offset) { return *reinterpret_cast(static_cast(creature) + offset); } void RepairFollowers() { for (uint32_t id = 1; id < game::ObjectIdEnd(); ++id) { if (game::IsPlayerHeroId(id) || !game::GetObjectById(id)) { continue; } void* creature = game::GetCreature(id); const int32_t status = creature ? Field(creature, game::kCreatureStatus) : 0; if (!(status & game::kStatusFollowing) || (status & kStatusTagAlong)) { continue; } const auto leaderId = static_cast(Field(creature, game::kCreatureLeader)); void* leader = game::IsPlayerHeroId(leaderId) ? game::GetCreature(leaderId) : nullptr; if (!leader || game::HasFollower(leader, id)) { continue; } game::AddFollower(leader, {id, 1, 1}); re::Log("followers: %x back on the follower list of hero %x", id, leaderId); } } void OnTick(uint8_t*) { if (g_ticksToCheck > 0 && --g_ticksToCheck == 0) { RepairFollowers(); } } void OnStart() { g_ticksToCheck = kTicksAfterStart; } struct Registration { Registration() { game::OnEngineTick(&OnTick); game::OnGameStart(&OnStart); } } g_registration; } // namespace } // namespace mods::followers