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:
NovaRain
2019-11-11 10:00:22 +08:00
parent 227a062fa6
commit 534bc3e5cd
9 changed files with 113 additions and 9 deletions
+3
View File
@@ -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 -------
------------------------
+2 -2
View File
@@ -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
+3 -3
View File
@@ -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;
+70 -4
View File
@@ -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
+5
View File
@@ -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);
+12
View File
@@ -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);
}
+4
View File
@@ -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}},