mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Fixed and improved the behavior of nested timer events in global scripts
Added a fix to prevent the execution of critter_p_proc and game events when playing movies. Added a debug message about a corrupted proto file. Some minor code/document edits.
This commit is contained in:
@@ -253,7 +253,7 @@
|
||||
/* sfall metarule3 function macros */
|
||||
// sets the number of days (range 1...127) for the Frank Horrigan encounter, or disable the encounter if days is set to 0
|
||||
#define set_horrigan_days(day) metarule3(200, day, 0, 0)
|
||||
// clears the keyboard input buffer, use it in the HOOK_KEYPRESS hook to clear keyboard events before calling script functions that accept key input
|
||||
// clears the keyboard input buffer, use it in the HOOK_KEYPRESS hook to clear keyboard events before calling functions that are waiting for keyboard input
|
||||
#define clear_keyboard_buffer metarule3(201, 0, 0, 0)
|
||||
|
||||
|
||||
|
||||
@@ -2749,6 +2749,17 @@ checkTiles:
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) doBkProcesses_hook() {
|
||||
__asm {
|
||||
call gdialogActive_;
|
||||
test eax, eax;
|
||||
jz skip;
|
||||
retn;
|
||||
skip:
|
||||
jmp gmovieIsPlaying_;
|
||||
}
|
||||
}
|
||||
|
||||
void BugFixesInit()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
@@ -3480,4 +3491,7 @@ void BugFixesInit()
|
||||
};
|
||||
SafeWriteBytes(0x42A0F4, codeData1, 18); // ai_move_steps_closer_
|
||||
HookCall(0x42A0F8, (void*)obj_dist_);
|
||||
|
||||
// Fix to prevent the execution of critter_p_proc and game events when playing movies (same as when the dialog is active)
|
||||
HookCall(0x4A3C89, doBkProcesses_hook);
|
||||
}
|
||||
|
||||
+18
-1
@@ -335,6 +335,20 @@ display:
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) proto_load_pid_hack() {
|
||||
static char* proDbgMsg = "\nERROR reading prototype file: %s\n";
|
||||
__asm {
|
||||
mov dword ptr [esp + 0x120 - 0x1C + 4], -1;
|
||||
lea eax, [esp + 0x120 - 0x120 + 4]; // pro file
|
||||
push eax;
|
||||
push proDbgMsg;
|
||||
call debug_printf_;
|
||||
add esp, 8;
|
||||
mov eax, 0x500494; // 'iisxxxx1'
|
||||
jmp gsound_play_sfx_file_;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) win_debug_hook() {
|
||||
__asm {
|
||||
call debug_log_;
|
||||
@@ -381,7 +395,7 @@ static void DebugModePatch() {
|
||||
if (iniGetInt("Debugging", "HideObjIsNullMsg", 0, ddrawIniDef)) {
|
||||
MakeJump(0x453FD2, dbg_error_hack);
|
||||
}
|
||||
// prints a debug message about missing art file for critters to both debug.log and the message window in sfall debugging mode
|
||||
// prints a debug message about a missing critter art file to both debug.log and the message window in sfall debugging mode
|
||||
HookCall(0x419B65, art_data_size_hook);
|
||||
|
||||
// Fix to prevent crashes when there is a '%' character in the printed message
|
||||
@@ -408,6 +422,9 @@ static void DontDeleteProtosPatch() {
|
||||
void DebugEditorInit() {
|
||||
DebugModePatch();
|
||||
|
||||
// Notifies and prints a debug message about a corrupted proto file to debug.log
|
||||
MakeCall(0x4A1D73, proto_load_pid_hack, 6);
|
||||
|
||||
if (!isDebug) return;
|
||||
DontDeleteProtosPatch();
|
||||
|
||||
|
||||
@@ -534,7 +534,7 @@ void ExtraSaveSlotsInit() {
|
||||
dlogr(" Done", DL_INIT);
|
||||
}
|
||||
|
||||
// Adds the city name in the description of a save slot
|
||||
// Adds the city name in the description for empty save slots
|
||||
MakeJump(0x47F02C, GetComment_hack);
|
||||
}
|
||||
|
||||
|
||||
@@ -433,6 +433,7 @@ const DWORD gmouse_3d_set_mode_ = 0x44CA18;
|
||||
const DWORD gmouse_is_scrolling_ = 0x44B54C;
|
||||
const DWORD gmouse_set_cursor_ = 0x44C840;
|
||||
const DWORD gmovie_play_ = 0x44E690;
|
||||
const DWORD gmovieIsPlaying_ = 0x44EB14;
|
||||
const DWORD GNW_do_bk_process_ = 0x4C8D1C;
|
||||
const DWORD GNW_find_ = 0x4D7888;
|
||||
const DWORD GNW_win_refresh_ = 0x4D6FD8;
|
||||
|
||||
@@ -712,6 +712,7 @@ extern const DWORD gmouse_3d_set_mode_;
|
||||
extern const DWORD gmouse_is_scrolling_;
|
||||
extern const DWORD gmouse_set_cursor_;
|
||||
extern const DWORD gmovie_play_;
|
||||
extern const DWORD gmovieIsPlaying_;
|
||||
extern const DWORD GNW_do_bk_process_;
|
||||
extern const DWORD GNW_find_;
|
||||
extern const DWORD GNW_win_refresh_;
|
||||
|
||||
+2
-4
@@ -460,8 +460,7 @@ static void Present() {
|
||||
DWORD move = r.right - r2.right;
|
||||
windowLeft -= move;
|
||||
r.right -= move;
|
||||
}
|
||||
else if (r.left < r2.left) {
|
||||
} else if (r.left < r2.left) {
|
||||
DWORD move = r2.left - r.left;
|
||||
windowLeft += move;
|
||||
r.right += move;
|
||||
@@ -470,8 +469,7 @@ static void Present() {
|
||||
DWORD move = r.bottom - r2.bottom;
|
||||
windowTop -= move;
|
||||
r.bottom -= move;
|
||||
}
|
||||
else if (r.top < r2.top) {
|
||||
} else if (r.top < r2.top) {
|
||||
DWORD move = r2.top - r.top;
|
||||
windowTop += move;
|
||||
r.bottom += move;
|
||||
|
||||
+45
-11
@@ -18,6 +18,7 @@
|
||||
|
||||
//#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
#include <stack>
|
||||
|
||||
#include "main.h"
|
||||
#include "FalloutEngine.h"
|
||||
@@ -398,16 +399,20 @@ struct SelfOverrideObj {
|
||||
}
|
||||
};
|
||||
|
||||
// Events in global scripts cannot be saved because the scripts don't have a binding object
|
||||
struct TimedEvent {
|
||||
sScriptProgram* script;
|
||||
unsigned long time;
|
||||
long fixed_param;
|
||||
bool isActive;
|
||||
|
||||
bool operator() (const TimedEvent &a, const TimedEvent &b) {
|
||||
return a.time < b.time;
|
||||
}
|
||||
} *timedEvent = nullptr;
|
||||
|
||||
static long executeTimedEventDepth = 0;
|
||||
static std::stack<TimedEvent*> executeTimedEvents;
|
||||
static std::list<TimedEvent> timerEventScripts;
|
||||
|
||||
static std::vector<DWORD> checkedScripts;
|
||||
@@ -1372,6 +1377,9 @@ static void ClearGlobalScripts() {
|
||||
selfOverrideMap.clear();
|
||||
globalExportedVars.clear();
|
||||
timerEventScripts.clear();
|
||||
timedEvent = nullptr;
|
||||
executeTimedEventDepth = 0;
|
||||
while (!executeTimedEvents.empty()) executeTimedEvents.pop();
|
||||
HookScriptClear();
|
||||
}
|
||||
|
||||
@@ -1523,25 +1531,50 @@ static DWORD __stdcall HandleMapUpdateForScripts(const DWORD procId) {
|
||||
|
||||
static DWORD HandleTimedEventScripts() {
|
||||
DWORD currentTime = *ptr_fallout_game_time;
|
||||
bool wasRunning = false;
|
||||
std::list<TimedEvent>::const_iterator timerIt = timerEventScripts.cbegin();
|
||||
for (; timerIt != timerEventScripts.cend(); ++timerIt) {
|
||||
if (timerEventScripts.empty()) return currentTime;
|
||||
|
||||
executeTimedEventDepth++;
|
||||
|
||||
DevPrintf("\n[TimedEventScripts] Time: %d / Depth: %d", currentTime, executeTimedEventDepth);
|
||||
|
||||
bool eventsWereRunning = false;
|
||||
for (std::list<TimedEvent>::const_iterator timerIt = timerEventScripts.cbegin(); timerIt != timerEventScripts.cend(); ++timerIt) {
|
||||
DevPrintf("\n[TimedEventScripts] Event: %d", timerIt->time);
|
||||
if (timerIt->isActive == false) continue;
|
||||
if (currentTime >= timerIt->time) {
|
||||
if (timedEvent) executeTimedEvents.push(timedEvent); // store a pointer to the currently running event
|
||||
|
||||
timedEvent = const_cast<TimedEvent*>(&(*timerIt));
|
||||
DevPrintf("\n[TimedEventScripts] run event: %d", timerIt->time);
|
||||
timedEvent->isActive = false;
|
||||
|
||||
DevPrintf("\n[TimedEventScripts] Run event: %d", timerIt->time);
|
||||
RunScriptProc(timerIt->script, Scripts::timed_event_p_proc);
|
||||
wasRunning = true;
|
||||
DevPrintf("\n[TimedEventScripts] Event done: %d", timerIt->time);
|
||||
|
||||
timedEvent = nullptr;
|
||||
if (!executeTimedEvents.empty()) {
|
||||
timedEvent = executeTimedEvents.top(); // restore a pointer to a previously running event
|
||||
executeTimedEvents.pop();
|
||||
}
|
||||
eventsWereRunning = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (wasRunning) {
|
||||
for (std::list<TimedEvent>::const_iterator _it = timerEventScripts.cbegin(); _it != timerIt; ++_it) {
|
||||
DevPrintf("\n[TimedEventScripts] delete event: %d", _it->time);
|
||||
executeTimedEventDepth--;
|
||||
|
||||
if (eventsWereRunning && executeTimedEventDepth == 0) {
|
||||
timedEvent = nullptr;
|
||||
// delete all previously executed events
|
||||
for (std::list<TimedEvent>::const_iterator it = timerEventScripts.cbegin(); it != timerEventScripts.cend();) {
|
||||
if (it->isActive == false) {
|
||||
DevPrintf("\n[TimedEventScripts] Remove event: %d", it->time);
|
||||
it = timerEventScripts.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
timerEventScripts.erase(timerEventScripts.cbegin(), timerIt);
|
||||
}
|
||||
timedEvent = nullptr;
|
||||
return currentTime;
|
||||
}
|
||||
|
||||
@@ -1553,7 +1586,7 @@ static DWORD TimedEventNextTime() {
|
||||
mov nextTime, eax;
|
||||
push edx;
|
||||
}
|
||||
if (!timerEventScripts.empty()) {
|
||||
if (!timerEventScripts.empty() && timerEventScripts.front().isActive) {
|
||||
DWORD time = timerEventScripts.front().time;
|
||||
if (!nextTime || time < nextTime) nextTime = time;
|
||||
}
|
||||
@@ -1569,6 +1602,7 @@ static DWORD script_chk_timed_events_hook() {
|
||||
void __stdcall AddTimerEventScripts(DWORD script, long time, long param) {
|
||||
sScriptProgram* scriptProg = &(sfallProgsMap.find(script)->second);
|
||||
TimedEvent timer;
|
||||
timer.isActive = true;
|
||||
timer.script = scriptProg;
|
||||
timer.fixed_param = param;
|
||||
timer.time = *ptr_fallout_game_time + time;
|
||||
|
||||
Reference in New Issue
Block a user