Restore aura visuals after loading a save

Saving marks effect objects dead, so after a load the Heldenmut /
Klingenblick buff was active but its aura effect (cObjectFX 842) was
gone. A few ticks after a save game has loaded, the effect is created
again for each such buff of a player hero (CreateAt + cEventFX 0x42,
as the art's cast effect does), with the buff's remaining time.

Shared game events (game/engine/events): engine tick and "save game
loaded" callbacks; the WASD mod uses the tick through it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
khallaandClaude Opus 5.5 committed 2026-10-15 01:27:56 +02:00
1 parent 30c93fc87e
commit f721d2a486
8 files changed
+217 -26

No files matched your search

+49
View File
@@ -0,0 +1,49 @@
#include "game/engine/events.h"
#include <vector>
#include "re/hook.h"
namespace game {
namespace {
std::vector<EngineTickFn>& TickCallbacks() {
static std::vector<EngineTickFn> callbacks;
return callbacks;
}
std::vector<SaveGameLoadedFn>& LoadedCallbacks() {
static std::vector<SaveGameLoadedFn> callbacks;
return callbacks;
}
} // namespace
void OnEngineTick(EngineTickFn callback) {
TickCallbacks().push_back(callback);
}
void OnSaveGameLoaded(SaveGameLoadedFn callback) {
LoadedCallbacks().push_back(callback);
}
void NotifySaveGameLoaded() {
for (SaveGameLoadedFn callback : LoadedCallbacks()) {
callback();
}
}
// cEngine::Tick (0x60f1d0, 10 Hz): processes queued events, then the mouse's
// hold-to-move re-aim orders.
void __fastcall Engine_Tick(void* self, void* edx, void* event);
RE_HOOK(0x0060f1d0, Engine_Tick);
void __fastcall Engine_Tick(void* self, void* edx, void* event) {
Engine_Tick_original(self, edx, event);
if (self) {
for (EngineTickFn callback : TickCallbacks()) {
callback(static_cast<uint8_t*>(self));
}
}
}
} // namespace game
+19
View File
@@ -0,0 +1,19 @@
#pragma once
// Game events several mods react to. The hooks behind them live in
// events.cpp; mods register callbacks at startup (static initialisation).
#include <cstdint>
namespace game {
// cEngine::Tick (0x60f1d0, 10 Hz), after the game's own handling.
using EngineTickFn = void (*)(uint8_t* engine);
void OnEngineTick(EngineTickFn callback);
// A save game finished loading its objects (cInventoryManager::Serialize
// read, the last part of the load); callbacks run on the loading thread.
using SaveGameLoadedFn = void (*)();
void OnSaveGameLoaded(SaveGameLoadedFn callback);
void NotifySaveGameLoaded();
} // namespace game