void setuphooks(bool newStatus) {
static kthook::kthook_signal<void(CCDECL *)(void)> gameLoop_Hook(0x53BFC7, false);
static decltype(gameLoop_Hook.before)::ktsignal_connection gameloop_Before = {[](){}};
static decltype(gameLoop_Hook.after)::ktsignal_connection gameloop_After = {[](){}};
static kthook::kthook_signal<bool(CTHISCALL *)(CPed *thisPtr)> uponFiringEvent_Hook(0x7427C9, false);
static decltype(uponFiringEvent_Hook.before)::ktsignal_connection uponFiringEvent_Before = {[](){}};
static decltype(uponFiringEvent_Hook.after)::ktsignal_connection uponFiringEvent_After = {[](){}};
static bool currentStatus;
if (currentStatus == newStatus) {
return; // no change
}
currentStatus = newStatus;
if (!newStatus) {
gameloop_Before.disconnect(); // works if outside its own callback
gameloop_After.disconnect(); // works if outside its own callback
uponFiringEvent_Before.disconnect(); // works if outside its own callback
uponFiringEvent_After.disconnect(); // works if outside its own callback
printf("Works\n");
return;
}
gameloop_Before = gameLoop_Hook.before.connect([](const auto &whichHook) {
gameloop_Before.disconnect(); // crashes the program
printf("gameloop_Before will crash the program\n");
return true;
});
gameloop_After = gameLoop_Hook.after.connect([](const auto &whichHook) {
gameloop_After.disconnect(); // crashes the program
printf("gameloop_After will crash the program\n");
});
uponFiringEvent_Before = uponFiringEvent_Hook.before.connect([](const auto &whichHook, CPed *thisPtr) -> std::optional<bool> {
uponFiringEvent_Before.disconnect(); // crashes the program
printf("uponFiringEvent_Before will crash the program\n");
return std::nullopt;
});
uponFiringEvent_After = uponFiringEvent_Hook.after.connect([](const auto &whichHook, bool &retVal, CPed *thisPtr) {
uponFiringEvent_After.disconnect(); // crashes the program
printf("uponFiringEvent_After will crash the program\n");
});
}
I'm fully aware that kthook_simple is the best choice for the code above. But this is just a mock test to get the idea of what I'm talking about.
kthook_simple does not have any issue disconnecting itself while its own callback is executing:
void setupsimplehooks(bool newStatus) {
using gameLoop_SimpleHookType = kthook::kthook_simple<void(CCDECL *)(void)>;
static gameLoop_SimpleHookType gameLoop_SimpleHook(
0x53BFC7,
[](const gameLoop_SimpleHookType &whichHook) {
auto &nonConstHook = const_cast<gameLoop_SimpleHookType&>(whichHook);
nonConstHook.remove(); // disconnect hook
printf("gameLoop_SimpleHook disconnect Works inside its own callback");
whichHook.call_trampoline(); // call original
}, false);
using uponFiringEvent_SimpleHookType = kthook::kthook_simple<bool(CTHISCALL *)(CPed *thisPtr)>;
static uponFiringEvent_SimpleHookType uponFiringEvent_SimpleHook(
0x7427C9,
[](const uponFiringEvent_SimpleHookType &whichHook, CPed *thisPtr) -> bool {
auto &nonConstHook = const_cast<uponFiringEvent_SimpleHookType&>(whichHook);
nonConstHook.remove(); // disconnect hook
printf("uponFiringEvent_SimpleHook disconnect Works inside its own callback");
return whichHook.call_trampoline(thisPtr); // call original
}, false);
static bool currentStatus;
if (currentStatus == newStatus) {
return; // no change
}
if (!newStatus) {
gameLoop_SimpleHook.remove();
uponFiringEvent_SimpleHook.remove();
printf("simplehook disconnect outside its own callback Works\n");
return;
}
gameLoop_SimpleHook.install();
uponFiringEvent_SimpleHook.install();
}
I'm fully aware that kthook_simple is the best choice for the code above. But this is just a mock test to get the idea of what I'm talking about.
kthook_simpledoes not have any issue disconnecting itself while its own callback is executing: