mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Separated the loading and initialization of global scripts
* now the loading occurs before the start of a new game.
This commit is contained in:
@@ -138,7 +138,7 @@ void HookScripts::RegisterHook(fo::Program* script, int id, int procNum, bool sp
|
||||
|
||||
ScriptProgram *prog = ScriptExtender::GetGlobalScriptProgram(script);
|
||||
if (prog) {
|
||||
dlog_f("Global script: %08x registered as hook ID %d\n", DL_HOOK, script, id);
|
||||
dlog_f("Script: %s registered as hook ID %d\n", DL_HOOK, script->fileName, id);
|
||||
HookScript hook;
|
||||
hook.prog = *prog;
|
||||
hook.callback = procNum;
|
||||
@@ -165,13 +165,15 @@ void HookScripts::RunHookScriptsAtProc(DWORD procId) {
|
||||
}
|
||||
|
||||
void HookScripts::LoadHookScript(const char* name, int id) {
|
||||
//if (id >= numHooks || IsGameScript(name)) return;
|
||||
char filePath[MAX_PATH];
|
||||
|
||||
bool hookIsLoaded = HookScripts::LoadHookScriptFile(name, id);
|
||||
if (hookIsLoaded || injectHooks[id].injectState == 1 || (injectAllHooks && id != HOOK_SUBCOMBATDAMAGE)) {
|
||||
sprintf(filePath, "scripts\\%s.int", name);
|
||||
bool hookHasScript = fo::func::db_access(filePath);
|
||||
|
||||
if (hookHasScript || injectHooks[id].injectState == 1 || (injectAllHooks && id != HOOK_SUBCOMBATDAMAGE)) {
|
||||
HookScripts::InjectingHook(id); // inject hook to engine code
|
||||
|
||||
if (!hookIsLoaded) return; // only inject
|
||||
if (!hookHasScript) return; // only inject
|
||||
|
||||
HookFile hookFile = { id, name };
|
||||
HookScripts::hookScriptFilesList.push_back(hookFile);
|
||||
@@ -179,30 +181,25 @@ void HookScripts::LoadHookScript(const char* name, int id) {
|
||||
}
|
||||
|
||||
bool HookScripts::LoadHookScriptFile(const char* name, int id) {
|
||||
char filename[MAX_PATH];
|
||||
sprintf(filename, "scripts\\%s.int", name);
|
||||
|
||||
ScriptProgram prog;
|
||||
if (fo::func::db_access(filename)) {
|
||||
dlog("> ", DL_HOOK);
|
||||
dlog(name, DL_HOOK);
|
||||
LoadScriptProgram(prog, name);
|
||||
if (prog.ptr) {
|
||||
dlogr(" Done", DL_HOOK);
|
||||
HookScript hook;
|
||||
hook.prog = prog;
|
||||
hook.callback = -1;
|
||||
hook.isGlobalScript = false;
|
||||
hooks[id].push_back(hook);
|
||||
ScriptExtender::AddProgramToMap(prog);
|
||||
dlogr(" Done", DL_HOOK);
|
||||
} else {
|
||||
dlogr(" Error!", DL_HOOK);
|
||||
}
|
||||
}
|
||||
return (prog.ptr != nullptr);
|
||||
}
|
||||
|
||||
static void HookScriptInit() {
|
||||
void HookScripts::LoadHookScripts() {
|
||||
dlogr("Loading hook scripts:", DL_HOOK|DL_INIT);
|
||||
|
||||
static bool hooksFilesLoaded = false;
|
||||
@@ -221,17 +218,18 @@ static void HookScriptInit() {
|
||||
HookScripts::LoadHookScript("hs_gamemodechange", HOOK_GAMEMODECHANGE);
|
||||
|
||||
hooksFilesLoaded = !alwaysFindScripts;
|
||||
} else {
|
||||
for (auto& hook : HookScripts::hookScriptFilesList) {
|
||||
HookScripts::LoadHookScriptFile(hook.name.c_str(), hook.id);
|
||||
}
|
||||
}
|
||||
dlogr("Finished loading hook scripts.", DL_HOOK|DL_INIT);
|
||||
}
|
||||
|
||||
void HookScripts::LoadHookScripts() {
|
||||
isGlobalScriptLoading = 1; // this should allow to register global exported variables
|
||||
HookScriptInit();
|
||||
void HookScripts::InitHookScripts() {
|
||||
// Note: here isGlobalScriptLoading must be already set, this should allow to register global exported variables
|
||||
dlogr("Running hook scripts...", DL_HOOK);
|
||||
|
||||
for (auto& hook : HookScripts::hookScriptFilesList) {
|
||||
HookScripts::LoadHookScriptFile(hook.name.c_str(), hook.id);
|
||||
}
|
||||
|
||||
initingHookScripts = 1;
|
||||
for (int i = 0; i < numHooks; i++) {
|
||||
if (!hooks[i].empty()) {
|
||||
@@ -239,7 +237,6 @@ void HookScripts::LoadHookScripts() {
|
||||
InitScriptProgram(hooks[i][0].prog); // zero hook is always hs_*.int script because Hook scripts are loaded BEFORE global scripts
|
||||
}
|
||||
}
|
||||
isGlobalScriptLoading = 0;
|
||||
initingHookScripts = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -95,6 +95,7 @@ public:
|
||||
static void LoadHookScript(const char* name, int id);
|
||||
static bool LoadHookScriptFile(const char* name, int id);
|
||||
static void LoadHookScripts();
|
||||
static void InitHookScripts();
|
||||
static void HookScriptClear();
|
||||
|
||||
static bool HookHasScript(int hookId);
|
||||
|
||||
@@ -318,11 +318,9 @@ static void __stdcall NewGame_Before() {
|
||||
}
|
||||
|
||||
static void __stdcall NewGame_After() {
|
||||
dlogr("New Game started.", DL_MAIN);
|
||||
onAfterNewGame.invoke();
|
||||
onAfterGameStarted.invoke();
|
||||
|
||||
dlogr("New Game started.", DL_MAIN);
|
||||
|
||||
gameLoaded = true;
|
||||
}
|
||||
|
||||
@@ -333,7 +331,6 @@ static void __declspec(naked) main_load_new_hook() {
|
||||
pop eax;
|
||||
call fo::funcoffs::main_load_new_;
|
||||
jmp NewGame_After;
|
||||
//retn;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -124,8 +124,8 @@ typedef std::unordered_map<__int64, int>::iterator glob_itr;
|
||||
typedef std::unordered_map<__int64, int>::const_iterator glob_citr;
|
||||
|
||||
DWORD availableGlobalScriptTypes = 0;
|
||||
DWORD isGlobalScriptLoading = 0;
|
||||
bool isGameLoading;
|
||||
static DWORD isGlobalScriptLoading = 0;
|
||||
static bool isGameReset;
|
||||
bool alwaysFindScripts;
|
||||
|
||||
fo::ScriptInstance overrideScript = {0};
|
||||
@@ -304,7 +304,7 @@ proceedNormal:
|
||||
|
||||
// this hook prevents sfall scripts from being removed after switching to another map, since normal script engine re-loads completely
|
||||
static void __stdcall FreeProgram(fo::Program* progPtr) {
|
||||
if (isGameLoading || (sfallProgsMap.find(progPtr) == sfallProgsMap.end())) { // only delete non-sfall scripts or when actually loading the game
|
||||
if (isGameReset || (sfallProgsMap.find(progPtr) == sfallProgsMap.end())) { // only delete non-sfall scripts or when actually loading the game
|
||||
__asm {
|
||||
mov eax, progPtr;
|
||||
call fo::funcoffs::interpretFreeProgram_;
|
||||
@@ -483,27 +483,37 @@ bool IsGameScript(const char* filename) {
|
||||
}
|
||||
|
||||
static void LoadGlobalScriptsList() {
|
||||
dlogr("Running global scripts...", DL_SCRIPT);
|
||||
|
||||
ScriptProgram prog;
|
||||
for (auto& item : globalScriptFilesList) {
|
||||
auto &scriptFile = item.second;
|
||||
dlog("> " + scriptFile, DL_SCRIPT);
|
||||
isGlobalScriptLoading = 1;
|
||||
LoadScriptProgram(prog, scriptFile.c_str(), true);
|
||||
if (prog.ptr) {
|
||||
dlogr(" Done", DL_SCRIPT);
|
||||
GlobalScript gscript = GlobalScript(prog);
|
||||
gscript.startProc = prog.procLookup[fo::Scripts::ScriptProc::start]; // get 'start' procedure position
|
||||
globalScripts.push_back(gscript);
|
||||
ScriptExtender::AddProgramToMap(prog);
|
||||
dlogr(" Done", DL_SCRIPT);
|
||||
// initialize script (start proc will be executed for the first time) -- this needs to be after script is added to "globalScripts" array
|
||||
InitScriptProgram(prog);
|
||||
} else {
|
||||
dlogr(" Error!", DL_SCRIPT);
|
||||
}
|
||||
isGlobalScriptLoading = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void InitGlobalScripts() {
|
||||
isGameReset = false;
|
||||
isGlobalScriptLoading = 1; // this should allow to register global exported variables
|
||||
|
||||
HookScripts::InitHookScripts();
|
||||
LoadGlobalScriptsList();
|
||||
|
||||
isGlobalScriptLoading = 0;
|
||||
}
|
||||
|
||||
static void PrepareGlobalScriptsListByMask() {
|
||||
globalScriptFilesList.clear();
|
||||
for (auto& fileMask : globalScriptPathList) {
|
||||
@@ -518,6 +528,7 @@ static void PrepareGlobalScriptsListByMask() {
|
||||
std::string baseName(name);
|
||||
int lastDot = baseName.find_last_of('.');
|
||||
if ((baseName.length() - lastDot) > 4) continue; // skip files with invalid extension (bug in db_get_file_list fuction)
|
||||
dlog_f("Found global script: %s\n", DL_INIT, name);
|
||||
|
||||
baseName = baseName.substr(0, lastDot); // script name without extension
|
||||
if (basePath != fo::var::script_path_base || !IsGameScript(baseName.c_str())) {
|
||||
@@ -536,10 +547,9 @@ static void PrepareGlobalScriptsListByMask() {
|
||||
}
|
||||
}
|
||||
|
||||
// this runs after the game was loaded/started
|
||||
// this runs before the game was loaded/started
|
||||
static void LoadGlobalScripts() {
|
||||
static bool listIsPrepared = false;
|
||||
isGameLoading = false;
|
||||
|
||||
HookScripts::LoadHookScripts();
|
||||
|
||||
@@ -549,7 +559,6 @@ static void LoadGlobalScripts() {
|
||||
listIsPrepared = !alwaysFindScripts;
|
||||
if (listIsPrepared) globalScriptPathList.clear(); // clear path list, it is no longer needed
|
||||
}
|
||||
LoadGlobalScriptsList();
|
||||
dlogr("Finished loading global scripts.", DL_SCRIPT|DL_INIT);
|
||||
}
|
||||
|
||||
@@ -569,7 +578,6 @@ int __stdcall ScriptExtender::ScriptHasLoaded(fo::Program* script) {
|
||||
|
||||
lastProgram.script = script;
|
||||
lastProgram.index = i;
|
||||
|
||||
return loaded;
|
||||
}
|
||||
}
|
||||
@@ -579,7 +587,8 @@ int __stdcall ScriptExtender::ScriptHasLoaded(fo::Program* script) {
|
||||
|
||||
// this runs before actually loading/starting the game
|
||||
static void ClearGlobalScripts() {
|
||||
isGameLoading = true;
|
||||
devlog_f("\nReset global scripts.", DL_MAIN);
|
||||
isGameReset = true;
|
||||
lastProgram.script = nullptr;
|
||||
sfallProgsMap.clear();
|
||||
globalScripts.clear();
|
||||
@@ -889,7 +898,8 @@ static void BuildSortedIndexList() {
|
||||
|
||||
void ScriptExtender::init() {
|
||||
LoadGameHook::OnAfterGameInit() += BuildSortedIndexList;
|
||||
LoadGameHook::OnAfterGameStarted() += LoadGlobalScripts;
|
||||
LoadGameHook::OnBeforeGameStart() += LoadGlobalScripts; // loading sfall scripts
|
||||
LoadGameHook::OnAfterGameStarted() += InitGlobalScripts; // running sfall scripts
|
||||
LoadGameHook::OnGameReset() += [] () {
|
||||
ClearGlobalScripts();
|
||||
ClearGlobals();
|
||||
|
||||
@@ -109,7 +109,6 @@ void RunScriptProc(ScriptProgram* prog, long procId);
|
||||
int RunScriptStartProc(ScriptProgram* prog);
|
||||
|
||||
// variables
|
||||
extern DWORD isGlobalScriptLoading;
|
||||
extern DWORD availableGlobalScriptTypes;
|
||||
extern bool alwaysFindScripts;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user