mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Implemented executing timed_event_p_proc in sfall global scripts
Added "add_g_timer_event" and "remove_timer_event" script functions for timed_event_p_proc in global scripts. Fixed the check on the 'hidden' flag for previous commit.
This commit is contained in:
@@ -224,6 +224,7 @@
|
||||
#define ADD_PERK_MODE_REMOVE (4) // remove from the list of selectable perks
|
||||
|
||||
// sfall_funcX macros
|
||||
#define add_global_timer_event(time, param) sfall_func2("add_g_timer_event", time, param)
|
||||
#define add_iface_tag sfall_func0("add_iface_tag")
|
||||
#define add_trait(traitId) sfall_func1("add_trait", traitId)
|
||||
#define art_cache_clear sfall_func0("art_cache_clear")
|
||||
@@ -256,6 +257,8 @@
|
||||
#define obj_under_cursor(crSwitch, inclDude) sfall_func2("obj_under_cursor", crSwitch, inclDude)
|
||||
#define outlined_object sfall_func0("outlined_object")
|
||||
#define real_dude_obj sfall_func0("real_dude_obj")
|
||||
#define remove_all_timer_events sfall_func0("remove_timer_event")
|
||||
#define remove_timer_event(param) sfall_func1("remove_timer_event", param)
|
||||
#define set_cursor_mode(mode) sfall_func1("set_cursor_mode", mode)
|
||||
#define set_flags(obj, flags) sfall_func2("set_flags", obj, flags)
|
||||
#define set_iface_tag_text(tag, text, color) sfall_func3("set_iface_tag_text", tag, text, color)
|
||||
|
||||
@@ -528,6 +528,17 @@ Some utility/math functions are available:
|
||||
> int sfall_func0("get_inven_ap_cost")
|
||||
- returns the current AP cost to access the inventory in combat
|
||||
|
||||
> void sfall_func2("add_g_timer_event", int time, int param)
|
||||
- adds a timer event that calls the timed_event_p_proc procedure in the current global script
|
||||
- time: the number of ticks after which the event timer is triggered
|
||||
- param: the value that is passed to the timed_event_p_proc procedure for the fixed_param function
|
||||
|
||||
> void sfall_func0("remove_timer_event")
|
||||
- clears all set timer events for the current global script
|
||||
|
||||
> void sfall_func1("remove_timer_event", int param)
|
||||
- removes all timer events with the specified 'param' value for the current global script
|
||||
|
||||
------------------------
|
||||
------ MORE INFO -------
|
||||
------------------------
|
||||
|
||||
+10
-6
@@ -720,6 +720,14 @@ const DWORD xvfprintf_ = 0x4DF1AC;
|
||||
// WRAPPERS
|
||||
// please, use CamelCase for those
|
||||
|
||||
// Prints debug message to debug.log file for develop build
|
||||
#ifndef NDEBUG
|
||||
void __declspec(naked) DevPrintf(const char* fmt, ...) {
|
||||
__asm jmp debug_printf_;
|
||||
}
|
||||
#else
|
||||
void DevPrintf(const char* fmt, ...) {}
|
||||
#endif
|
||||
|
||||
long __stdcall ItemGetType(TGameObj* item) {
|
||||
__asm {
|
||||
@@ -923,15 +931,11 @@ const char* __stdcall InterpretGetString(TProgram* scriptPtr, DWORD strId, DWORD
|
||||
}
|
||||
|
||||
void __declspec(naked) InterpretError(const char* fmt, ...) {
|
||||
__asm {
|
||||
jmp interpretError_;
|
||||
}
|
||||
__asm jmp interpretError_;
|
||||
}
|
||||
|
||||
void __declspec(naked) DebugPrintf(const char* fmt, ...) {
|
||||
__asm {
|
||||
jmp debug_printf_;
|
||||
}
|
||||
__asm jmp debug_printf_;
|
||||
}
|
||||
|
||||
const char* __stdcall FindCurrentProc(TProgram* program) {
|
||||
|
||||
@@ -993,6 +993,10 @@ extern const DWORD xvfprintf_;
|
||||
|
||||
// WRAPPERS:
|
||||
// TODO: move these to different namespace
|
||||
|
||||
// Prints debug message to debug.log file for develop build
|
||||
void DevPrintf(const char* fmt, ...);
|
||||
|
||||
long __stdcall ItemGetType(TGameObj* item);
|
||||
long __stdcall ItemSize(TGameObj* item);
|
||||
|
||||
|
||||
@@ -22,8 +22,7 @@
|
||||
|
||||
#include "FalloutEngine.h"
|
||||
#include "FileSystem.h"
|
||||
|
||||
extern void GetSavePath(char* buf, char* ftype);
|
||||
#include "LoadGameHook.h"
|
||||
|
||||
#define MAX_FILE_SIZE 0xA00000
|
||||
|
||||
|
||||
+4
-4
@@ -206,7 +206,7 @@ static void SpeedInterfaceCounterAnimsPatch() {
|
||||
}
|
||||
|
||||
static bool IFACE_BAR_MODE = false;
|
||||
static long gmouse_handle_event_hook() {
|
||||
static long __stdcall gmouse_handle_event_hook() {
|
||||
long countWin = *(DWORD*)_num_windows;
|
||||
long ifaceWin = *ptr_interfaceWindow;
|
||||
WINinfo* win = nullptr;
|
||||
@@ -234,8 +234,8 @@ static void __declspec(naked) gmouse_bk_process_hook() {
|
||||
retn;
|
||||
checkFlag:
|
||||
call GNW_find_;
|
||||
cmp [eax + 4], WIN_Hidden; // window flags
|
||||
jnz skip;
|
||||
test [eax + 4], WIN_Hidden; // window flags
|
||||
jz skip;
|
||||
mov eax, ds:[_display_win]; // window is hidden, so return the number of the display_win
|
||||
skip:
|
||||
retn;
|
||||
@@ -254,7 +254,7 @@ void InterfaceInit() {
|
||||
|
||||
// Fix for interface windows with 'Hidden' and 'ScriptWindow' flags
|
||||
// Hidden - will not toggle the mouse cursor when the cursor hovers over a hidden window
|
||||
// ScriptWindow - prevents player's movement when clicking on the window if the 'Transparent' flag is not set
|
||||
// ScriptWindow - prevents the player from moving when clicking on the window if the 'Transparent' flag is not set
|
||||
HookCall(0x44B737, gmouse_bk_process_hook);
|
||||
// InterfaceGmouseHandleHook will be run before game initialization
|
||||
}
|
||||
|
||||
@@ -60,3 +60,5 @@ void SetLoopFlag(LoopFlag flag);
|
||||
|
||||
// unset the given flag
|
||||
void ClearLoopFlag(LoopFlag flag);
|
||||
|
||||
void GetSavePath(char* buf, char* ftype);
|
||||
|
||||
@@ -18,10 +18,8 @@
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <hash_map>
|
||||
//#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "Arrays.h"
|
||||
#include "BarBoxes.h"
|
||||
@@ -37,6 +35,11 @@
|
||||
#include "version.h"
|
||||
|
||||
static DWORD _stdcall HandleMapUpdateForScripts(const DWORD procId);
|
||||
static long _stdcall HandleTimedEventScripts();
|
||||
|
||||
static void RunGlobalScripts1();
|
||||
static void sf_add_g_timer_event();
|
||||
static void sf_remove_timer_event();
|
||||
|
||||
// variables for new opcodes
|
||||
#define OP_MAX_ARGUMENTS (8)
|
||||
@@ -390,6 +393,7 @@ static void OpcodeInvalidArgs(const char* opcodeName) {
|
||||
If you don't include opcode in this array, you should take care of all argument validation inside handler itself.
|
||||
*/
|
||||
static const SfallOpcodeMetadata opcodeMetaArray[] = {
|
||||
{sf_add_g_timer_event, "add_g_timer_event", {DATATYPE_MASK_INT, DATATYPE_MASK_INT}},
|
||||
{sf_add_trait, "add_trait", {DATATYPE_MASK_INT}},
|
||||
{sf_create_win, "create_win", {DATATYPE_MASK_STR, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT}},
|
||||
{sf_critter_inven_obj2, "critter_inven_obj2", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}},
|
||||
@@ -401,6 +405,7 @@ static const SfallOpcodeMetadata opcodeMetaArray[] = {
|
||||
{sf_item_weight, "item_weight", {DATATYPE_MASK_VALID_OBJ}},
|
||||
{sf_lock_is_jammed, "lock_is_jammed", {DATATYPE_MASK_VALID_OBJ}},
|
||||
{sf_get_obj_under_cursor, "obj_under_cursor", {DATATYPE_MASK_INT, DATATYPE_MASK_INT}},
|
||||
{sf_remove_timer_event, "remove_timer_event", {DATATYPE_MASK_INT}},
|
||||
{sf_set_cursor_mode, "set_cursor_mode", {DATATYPE_MASK_INT}},
|
||||
{sf_set_flags, "set_flags", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}},
|
||||
{sf_set_iface_tag_text, "set_iface_tag_text", {DATATYPE_MASK_INT, DATATYPE_MASK_STR, DATATYPE_MASK_INT}},
|
||||
@@ -464,6 +469,18 @@ struct SelfOverrideObj {
|
||||
}
|
||||
};
|
||||
|
||||
struct TimedEvent {
|
||||
sScriptProgram* script;
|
||||
long time;
|
||||
long fixed_param;
|
||||
|
||||
bool operator() (const TimedEvent &a, const TimedEvent &b) {
|
||||
return a.time < b.time;
|
||||
}
|
||||
} *timedEvent = nullptr;
|
||||
|
||||
static std::list<TimedEvent> timerEventScripts;
|
||||
|
||||
static std::vector<DWORD> checkedScripts;
|
||||
static std::vector<sGlobalScript> globalScripts;
|
||||
|
||||
@@ -835,6 +852,18 @@ static void __declspec(naked) register_hook_proc_spec() {
|
||||
_WRAP_OPCODE(register_hook_proc_spec2, 2, 0)
|
||||
}
|
||||
|
||||
static void sf_add_g_timer_event() {
|
||||
AddTimerEventScripts((DWORD)opHandler.program(), opHandler.arg(0).rawValue(), opHandler.arg(1).rawValue());
|
||||
}
|
||||
|
||||
static void sf_remove_timer_event() {
|
||||
if (opHandler.numArgs() > 0) {
|
||||
RemoveTimerEventScripts((DWORD)opHandler.program(), opHandler.arg(0).rawValue());
|
||||
} else {
|
||||
RemoveTimerEventScripts((DWORD)opHandler.program()); // remove all
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) sfall_ver_major() {
|
||||
_OP_BEGIN(ebp)
|
||||
__asm {
|
||||
@@ -884,6 +913,11 @@ static DWORD _stdcall FindSid(DWORD script) {
|
||||
}
|
||||
// this will allow to use functions like roll_vs_skill, etc without calling set_self (they don't really need self object)
|
||||
if (sfallProgsMap.find(script) != sfallProgsMap.end()) {
|
||||
if (timedEvent && timedEvent->script->ptr == script) {
|
||||
OverrideScriptStruct.fixed_param = timedEvent->fixed_param;
|
||||
} else {
|
||||
OverrideScriptStruct.fixed_param = 0;
|
||||
}
|
||||
OverrideScriptStruct.target_obj = OverrideScriptStruct.self_obj = 0;
|
||||
return -2; // override struct
|
||||
}
|
||||
@@ -1232,13 +1266,13 @@ void ScriptExtenderInit() {
|
||||
dlogr("New arrays behavior enabled.", DL_SCRIPT);
|
||||
} else dlogr("Arrays in backward-compatiblity mode.", DL_SCRIPT);
|
||||
|
||||
HookCall(0x480E7B, MainGameLoopHook); //hook the main game loop
|
||||
HookCall(0x422845, CombatLoopHook); //hook the combat loop
|
||||
|
||||
MakeJump(0x4A390C, FindSidHack);
|
||||
MakeJump(0x4A5E34, ScrPtrHack);
|
||||
|
||||
HookCall(0x480E7B, MainGameLoopHook); // hook the main game loop
|
||||
HookCall(0x422845, CombatLoopHook); // hook the combat loop
|
||||
MakeCall(0x4230D5, AfterCombatAttackHook);
|
||||
|
||||
MakeJump(0x4A390C, FindSidHack); // scr_find_sid_from_program_
|
||||
MakeJump(0x4A5E34, ScrPtrHack);
|
||||
HookCall(0x4A26D6, HandleTimedEventScripts); // queue_process_
|
||||
MakeJump(0x4A67F0, ExecMapScriptsHack);
|
||||
|
||||
// this patch makes it possible to export variables from sfall global scripts
|
||||
@@ -1705,6 +1739,7 @@ void ClearGlobalScripts() {
|
||||
globalScripts.clear();
|
||||
selfOverrideMap.clear();
|
||||
globalExportedVars.clear();
|
||||
timerEventScripts.clear();
|
||||
HookScriptClear();
|
||||
}
|
||||
|
||||
@@ -1855,6 +1890,54 @@ static DWORD _stdcall HandleMapUpdateForScripts(const DWORD procId) {
|
||||
return procId; // restore eax (don't delete)
|
||||
}
|
||||
|
||||
static long _stdcall HandleTimedEventScripts() {
|
||||
long currentTime = *ptr_fallout_game_time;
|
||||
bool wereRunning = false;
|
||||
auto timerIt = timerEventScripts.cbegin();
|
||||
for (; timerIt != timerEventScripts.cend(); timerIt++) {
|
||||
if (currentTime >= timerIt->time) {
|
||||
timedEvent = const_cast<TimedEvent*>(&(*timerIt));
|
||||
DevPrintf("\n[TimedEventScripts] run event: %d", timerIt->time);
|
||||
RunScriptProc(timerIt->script, timed_event_p_proc);
|
||||
wereRunning = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (wereRunning) {
|
||||
for (auto _it = timerEventScripts.cbegin(); _it != timerIt; _it++) {
|
||||
DevPrintf("\n[TimedEventScripts] delete events: %d", _it->time);
|
||||
}
|
||||
timerEventScripts.erase(timerEventScripts.cbegin(), timerIt);
|
||||
}
|
||||
timedEvent = nullptr;
|
||||
return currentTime;
|
||||
}
|
||||
|
||||
void _stdcall AddTimerEventScripts(DWORD script, long time, long param) {
|
||||
sScriptProgram* scriptProg = &(sfallProgsMap.find(script)->second);
|
||||
TimedEvent timer;
|
||||
timer.script = scriptProg;
|
||||
timer.fixed_param = param;
|
||||
timer.time = *ptr_fallout_game_time + time;
|
||||
timerEventScripts.push_back(std::move(timer));
|
||||
timerEventScripts.sort(TimedEvent());
|
||||
}
|
||||
|
||||
void _stdcall RemoveTimerEventScripts(DWORD script, long param) {
|
||||
sScriptProgram* scriptProg = &(sfallProgsMap.find(script)->second);
|
||||
timerEventScripts.remove_if([scriptProg, param] (TimedEvent timer) {
|
||||
return timer.script == scriptProg && timer.fixed_param == param;
|
||||
});
|
||||
}
|
||||
|
||||
void _stdcall RemoveTimerEventScripts(DWORD script) {
|
||||
sScriptProgram* scriptProg = &(sfallProgsMap.find(script)->second);
|
||||
timerEventScripts.remove_if([scriptProg] (TimedEvent timer) {
|
||||
return timer.script == scriptProg;
|
||||
});
|
||||
}
|
||||
|
||||
// run all global scripts of types 0 and 3 at specific procedure (if exist)
|
||||
void _stdcall RunGlobalScriptsAtProc(DWORD procId) {
|
||||
for (DWORD d = 0; d < globalScripts.size(); d++) {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "main.h"
|
||||
#include "FalloutStructs.h"
|
||||
|
||||
@@ -48,12 +49,15 @@ bool _stdcall IsGameScript(const char* filename);
|
||||
void LoadGlobalScripts();
|
||||
void ClearGlobalScripts();
|
||||
|
||||
void RunGlobalScripts1();
|
||||
void RunGlobalScripts2();
|
||||
void RunGlobalScripts3();
|
||||
void _stdcall RunGlobalScriptsAtProc(DWORD procId);
|
||||
void AfterAttackCleanup();
|
||||
|
||||
void _stdcall AddTimerEventScripts(DWORD script, long time, long param);
|
||||
void _stdcall RemoveTimerEventScripts(DWORD script, long param);
|
||||
void _stdcall RemoveTimerEventScripts(DWORD script);
|
||||
|
||||
bool LoadGlobals(HANDLE h);
|
||||
void SaveGlobals(HANDLE h);
|
||||
void ClearGlobals();
|
||||
|
||||
@@ -119,6 +119,7 @@ static void sf_metarule_exist() {
|
||||
*/
|
||||
static const SfallMetarule metaruleArray[] = {
|
||||
{"add_iface_tag", sf_add_iface_tag, 0, 0},
|
||||
{"add_g_timer_event", sf_add_g_timer_event, 2, 2},
|
||||
{"add_trait", sf_add_trait, 1, 1},
|
||||
{"art_cache_clear", sf_art_cache_flush, 0, 0},
|
||||
{"attack_is_aimed", sf_attack_is_aimed, 0, 0},
|
||||
@@ -149,6 +150,7 @@ static const SfallMetarule metaruleArray[] = {
|
||||
{"obj_under_cursor", sf_get_obj_under_cursor, 2, 2},
|
||||
{"outlined_object", sf_outlined_object, 0, 0},
|
||||
{"real_dude_obj", sf_real_dude_obj, 0, 0},
|
||||
{"remove_timer_event", sf_remove_timer_event, 0, 1},
|
||||
{"set_cursor_mode", sf_set_cursor_mode, 1, 1},
|
||||
{"set_flags", sf_set_flags, 2, 2},
|
||||
{"set_iface_tag_text", sf_set_iface_tag_text, 3, 3},
|
||||
|
||||
Reference in New Issue
Block a user