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:
@@ -249,6 +249,7 @@
|
||||
|
||||
// sfall_funcX macros
|
||||
#define add_extra_msg_file(name) sfall_func1("add_extra_msg_file", name)
|
||||
#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")
|
||||
@@ -293,6 +294,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_can_rest_on_map(map, elev, value) sfall_func3("set_can_rest_on_map", map, elev, value)
|
||||
#define set_car_intface_art(artIndex) sfall_func1("set_car_intface_art", artIndex)
|
||||
#define set_cursor_mode(mode) sfall_func1("set_cursor_mode", mode)
|
||||
|
||||
@@ -633,6 +633,17 @@ optional argument:
|
||||
> 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 -------
|
||||
------------------------
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace fo
|
||||
namespace func
|
||||
{
|
||||
|
||||
// prints debug message to debug.log file for develop build
|
||||
// Prints debug message to debug.log file for develop build
|
||||
#ifndef NDEBUG
|
||||
void __declspec(naked) dev_printf(const char* fmt, ...) {
|
||||
__asm jmp fo::funcoffs::debug_printf_;
|
||||
@@ -181,7 +181,7 @@ long __stdcall db_dir_entry(const char *fileName, DWORD *sizeOut) {
|
||||
|
||||
// prints message to debug.log file
|
||||
void __declspec(naked) debug_printf(const char* fmt, ...) {
|
||||
__asm jmp fo::funcoffs::debug_printf_
|
||||
__asm jmp fo::funcoffs::debug_printf_;
|
||||
}
|
||||
|
||||
// Displays message in main UI console window
|
||||
|
||||
@@ -591,8 +591,8 @@ static void __declspec(naked) gmouse_bk_process_hook() {
|
||||
retn;
|
||||
checkFlag:
|
||||
call fo::funcoffs::GNW_find_;
|
||||
cmp [eax + 4], Hidden; // window flags
|
||||
jnz skip;
|
||||
test [eax + 4], Hidden; // window flags
|
||||
jz skip;
|
||||
mov eax, ds:[FO_VAR_display_win]; // window is hidden, so return the number of the display_win
|
||||
skip:
|
||||
retn;
|
||||
@@ -609,7 +609,7 @@ void Interface::init() {
|
||||
|
||||
// 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);
|
||||
LoadGameHook::OnBeforeGameInit() += []() {
|
||||
if (hrpVersionValid) IFACE_BAR_MODE = *(BYTE*)HRPAddress(0x1006EB0C) != 0;
|
||||
|
||||
@@ -16,9 +16,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
//#include <unordered_set>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
|
||||
@@ -84,6 +82,18 @@ struct SelfOverrideObj {
|
||||
}
|
||||
};
|
||||
|
||||
struct TimedEvent {
|
||||
ScriptProgram* 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<std::string> globalScriptPathList;
|
||||
static std::map<std::string, std::string> globalScriptFilesList;
|
||||
|
||||
@@ -132,6 +142,11 @@ static DWORD _stdcall FindSid(fo::Program* 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.fixedParam = timedEvent->fixed_param;
|
||||
} else {
|
||||
overrideScriptStruct.fixedParam = 0;
|
||||
}
|
||||
overrideScriptStruct.targetObject = overrideScriptStruct.selfObject = 0;
|
||||
return -2; // override struct
|
||||
}
|
||||
@@ -499,7 +514,9 @@ static void PrepareGlobalScriptsListByMask() {
|
||||
static void LoadGlobalScripts() {
|
||||
static bool listIsPrepared = false;
|
||||
isGameLoading = false;
|
||||
|
||||
LoadHookScripts();
|
||||
|
||||
dlogr("Loading global scripts:", DL_SCRIPT|DL_INIT);
|
||||
if (!listIsPrepared) { // only once
|
||||
PrepareGlobalScriptsListByMask();
|
||||
@@ -528,6 +545,7 @@ static void ClearGlobalScripts() {
|
||||
globalScripts.clear();
|
||||
selfOverrideMap.clear();
|
||||
globalExportedVars.clear();
|
||||
timerEventScripts.clear();
|
||||
HookScriptClear();
|
||||
}
|
||||
|
||||
@@ -617,6 +635,54 @@ static DWORD _stdcall HandleMapUpdateForScripts(const DWORD procId) {
|
||||
return procId; // restore eax (don't delete)
|
||||
}
|
||||
|
||||
static long HandleTimedEventScripts() {
|
||||
long currentTime = fo::var::fallout_game_time;
|
||||
bool wereRunning = false;
|
||||
auto timerIt = timerEventScripts.cbegin();
|
||||
for (; timerIt != timerEventScripts.cend(); timerIt++) {
|
||||
if (currentTime >= timerIt->time) {
|
||||
timedEvent = const_cast<TimedEvent*>(&(*timerIt));
|
||||
fo::func::dev_printf("\n[TimedEventScripts] run event: %d", timerIt->time);
|
||||
RunScriptProc(timerIt->script, fo::ScriptProc::timed_event_p_proc);
|
||||
wereRunning = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (wereRunning) {
|
||||
for (auto _it = timerEventScripts.cbegin(); _it != timerIt; _it++) {
|
||||
fo::func::dev_printf("\n[TimedEventScripts] delete events: %d", _it->time);
|
||||
}
|
||||
timerEventScripts.erase(timerEventScripts.cbegin(), timerIt);
|
||||
}
|
||||
timedEvent = nullptr;
|
||||
return currentTime;
|
||||
}
|
||||
|
||||
void ScriptExtender::AddTimerEventScripts(fo::Program* script, long time, long param) {
|
||||
ScriptProgram* scriptProg = &(sfallProgsMap.find(script)->second);
|
||||
TimedEvent timer;
|
||||
timer.script = scriptProg;
|
||||
timer.fixed_param = param;
|
||||
timer.time = fo::var::fallout_game_time + time;
|
||||
timerEventScripts.push_back(std::move(timer));
|
||||
timerEventScripts.sort(TimedEvent());
|
||||
}
|
||||
|
||||
void ScriptExtender::RemoveTimerEventScripts(fo::Program* script, long param) {
|
||||
ScriptProgram* scriptProg = &(sfallProgsMap.find(script)->second);
|
||||
timerEventScripts.remove_if([scriptProg, param] (TimedEvent timer) {
|
||||
return timer.script == scriptProg && timer.fixed_param == param;
|
||||
});
|
||||
}
|
||||
|
||||
void ScriptExtender::RemoveTimerEventScripts(fo::Program* script) {
|
||||
ScriptProgram* 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 RunGlobalScriptsAtProc(DWORD procId) {
|
||||
for (DWORD d = 0; d < globalScripts.size(); d++) {
|
||||
@@ -754,9 +820,9 @@ void ScriptExtender::init() {
|
||||
alwaysFindScripts = isDebug && (iniGetInt("Debugging", "AlwaysFindScripts", 0, ::sfall::ddrawIni) != 0);
|
||||
if (alwaysFindScripts) dlogr("Always searching for global scripts behavior enabled.", DL_SCRIPT);
|
||||
|
||||
MakeJump(0x4A390C, FindSidHack);
|
||||
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
|
||||
|
||||
@@ -34,6 +34,10 @@ public:
|
||||
|
||||
static std::string iniConfigFolder;
|
||||
|
||||
static void AddTimerEventScripts(fo::Program* script, long time, long param);
|
||||
static void RemoveTimerEventScripts(fo::Program* script, long param);
|
||||
static void RemoveTimerEventScripts(fo::Program* script);
|
||||
|
||||
// Called before map exit (before map_exit_p_proc handlers in normal scripts)
|
||||
static Delegate<>& OnMapExit();
|
||||
};
|
||||
@@ -67,6 +71,7 @@ void SetGlobals(GlobalVar* globals);
|
||||
|
||||
long SetGlobalVar(const char* var, int val);
|
||||
void SetGlobalVarInt(DWORD var, int val);
|
||||
|
||||
long GetGlobalVar(const char* var);
|
||||
long GetGlobalVarInt(DWORD var);
|
||||
long GetGlobalVarInternal(__int64 val);
|
||||
|
||||
@@ -184,6 +184,18 @@ void sf_register_hook(OpcodeContext& ctx) {
|
||||
RegisterHook(ctx.program(), ctx.arg(0).rawValue(), proc, specReg);
|
||||
}
|
||||
|
||||
void sf_add_g_timer_event(OpcodeContext& ctx) {
|
||||
ScriptExtender::AddTimerEventScripts(ctx.program(), ctx.arg(0).rawValue(), ctx.arg(1).rawValue());
|
||||
}
|
||||
|
||||
void sf_remove_timer_event(OpcodeContext& ctx) {
|
||||
if (ctx.numArgs() > 0) {
|
||||
ScriptExtender::RemoveTimerEventScripts(ctx.program(), ctx.arg(0).rawValue());
|
||||
} else {
|
||||
ScriptExtender::RemoveTimerEventScripts(ctx.program()); // remove all
|
||||
}
|
||||
}
|
||||
|
||||
void sf_sfall_ver_major(OpcodeContext& ctx) {
|
||||
ctx.setReturn(VERSION_MAJOR);
|
||||
}
|
||||
|
||||
@@ -54,6 +54,10 @@ void __declspec() op_set_self();
|
||||
// used for both register_hook and register_hook_proc
|
||||
void sf_register_hook(OpcodeContext&);
|
||||
|
||||
void sf_add_g_timer_event(OpcodeContext&);
|
||||
|
||||
void sf_remove_timer_event(OpcodeContext&);
|
||||
|
||||
void sf_sfall_ver_major(OpcodeContext&);
|
||||
|
||||
void sf_sfall_ver_minor(OpcodeContext&);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "..\Arrays.h"
|
||||
#include "..\OpcodeContext.h"
|
||||
#include "Anims.h"
|
||||
#include "Core.h"
|
||||
#include "Interface.h"
|
||||
#include "Misc.h"
|
||||
#include "Objects.h"
|
||||
@@ -61,6 +62,7 @@ static MetaruleTableType metaruleTable;
|
||||
static const SfallMetarule metarules[] = {
|
||||
{"add_extra_msg_file", sf_add_extra_msg_file, 1, 2, {ARG_STRING, ARG_INT}},
|
||||
{"add_iface_tag", sf_add_iface_tag, 0, 0},
|
||||
{"add_g_timer_event", sf_add_g_timer_event, 2, 2, {ARG_INT, ARG_INT}},
|
||||
{"add_trait", sf_add_trait, 1, 1, {ARG_INT}},
|
||||
{"art_cache_clear", sf_art_cache_flush, 0, 0},
|
||||
{"attack_is_aimed", sf_attack_is_aimed, 0, 0},
|
||||
@@ -103,6 +105,7 @@ static const SfallMetarule metarules[] = {
|
||||
{"obj_under_cursor", sf_get_obj_under_cursor, 2, 2, {ARG_INT, ARG_INT}},
|
||||
{"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, {ARG_INT}},
|
||||
{"set_can_rest_on_map", sf_set_rest_on_map, 3, 3, {ARG_INT, ARG_INT, ARG_INT}},
|
||||
{"set_car_intface_art", sf_set_car_intface_art, 1, 1, {ARG_INT}},
|
||||
{"set_cursor_mode", sf_set_cursor_mode, 1, 1, {ARG_INT}},
|
||||
|
||||
Reference in New Issue
Block a user