HOOK_EXPLOSIVETIMER (#423)

This commit is contained in:
Mike Klaas
2026-04-29 20:37:43 -07:00
committed by GitHub
parent 4382ec3305
commit 2f491fa6d5
4 changed files with 51 additions and 2 deletions
+1 -1
View File
@@ -111,7 +111,7 @@ See [`https://sfall-team.github.io/sfall/`](https://sfall-team.github.io/sfall/)
| RestTimer | `HOOK_RESTTIMER` | ✅ | CE is slightly more strict: only `ret0 == 1` interrupts. Ticks wrap every 6.8y; do not rely on them for absolute game time. |
| GameModeChange | `HOOK_GAMEMODECHANGE` | ✅ | - |
| UseAnimObj | `HOOK_USEANIMOBJ` | 🚫 | Et tu; (maybe) |
| ExplosiveTimer | `HOOK_EXPLOSIVETIMER` | 🚫 | - |
| ExplosiveTimer | `HOOK_EXPLOSIVETIMER` | | - |
| DescriptionObj | `HOOK_DESCRIPTIONOBJ` | 🚫 | Et tu |
| UseSkillOn | `HOOK_USESKILLON` | 🚫 | Et tu |
| OnExplosion | `HOOK_ONEXPLOSION` | 🚫 | (maybe) |
+3 -1
View File
@@ -919,7 +919,9 @@ static UseItemResultCode _obj_use_explosive(Object* explosive)
break;
}
queueAddEvent(delay, explosive, nullptr, eventType);
if (scriptHooks_ExplosiveTimer(explosive, 10 * seconds, eventType) == -1) {
queueAddEvent(delay, explosive, nullptr, eventType);
}
}
}
+46
View File
@@ -9,6 +9,7 @@
#include "db.h"
#include "debug.h"
#include "queue.h"
#include "random.h"
#include "scripts.h"
@@ -248,6 +249,51 @@ bool scriptHooks_RestTimer(unsigned int gameTime, RestEventType eventType, int h
return false;
}
/*
Runs after Fallout has decided how long an explosive timer should run and whether setting it was a success or failure.
The hook can override both the queued delay and the coarse outcome. Critical success/failure collapse to success/failure,
matching sfall's queue event rewrite semantics.
int arg0 - The explosive delay in ticks before any failure penalty is applied
Obj arg1 - The explosive object
int arg2 - The result of engine calculation: 1 - failure, 2 - success
int ret0 - The new delay in ticks (maximum 18000). Negative values use engine behavior.
int ret1 - The new result: 0/1 - failure, 2/3 - success. Other values use engine behavior.
*/
int scriptHooks_ExplosiveTimer(Object* explosive, int delay, int eventType)
{
assert(explosive != nullptr);
assert(delay >= 0);
assert(eventType == EVENT_TYPE_EXPLOSION || eventType == EVENT_TYPE_EXPLOSION_FAILURE);
int hookResult = eventType == EVENT_TYPE_EXPLOSION_FAILURE ? ROLL_FAILURE : ROLL_SUCCESS;
ScriptHookCall hook(HOOK_EXPLOSIVETIMER, 2, { delay, explosive, hookResult });
hook.call();
if (hook.numReturnValues() <= 0) {
return -1;
}
int overrideDelay = hook.getReturnValueAt(0).asInt();
if (overrideDelay < 0) {
return -1;
}
delay = std::min(overrideDelay, 18000);
if (hook.numReturnValues() > 1) {
int overrideResult = hook.getReturnValueAt(1).asInt();
if (overrideResult >= ROLL_CRITICAL_FAILURE && overrideResult <= ROLL_FAILURE) {
eventType = EVENT_TYPE_EXPLOSION_FAILURE;
} else if (overrideResult >= ROLL_SUCCESS && overrideResult <= ROLL_CRITICAL_SUCCESS) {
eventType = EVENT_TYPE_EXPLOSION;
}
}
return queueAddEvent(delay, explosive, nullptr, eventType);
}
/*
Runs when calculating ammo cost for a weapon.
+1
View File
@@ -274,6 +274,7 @@ void scriptHooksExit();
void scriptHooks_GameModeChange(int exit, int previousGameMode);
bool scriptHooks_RestTimer(unsigned int gameTime, RestEventType eventType, int hours, int minutes);
void scriptHooks_OnDeath(Object* critter);
int scriptHooks_ExplosiveTimer(Object* explosive, int delay, int eventType);
bool scriptHooks_InventoryMove(HookInventoryMoveType actionType, Object* item, Object* targetItem);
bool scriptHooks_CombatTurnStart(Object* critter, bool reloadedDuringCombat);
bool scriptHooks_CombatTurnEnd(Object* critter, int turnResult, bool reloadedDuringCombat);