Reorganized and fixed the order of loading global scripts from multiple paths (from Mr.Stalin)

This commit is contained in:
NovaRain
2018-11-21 10:52:12 +08:00
parent 8dbe5921ba
commit b3a4f2c19e
2 changed files with 61 additions and 49 deletions
+59 -47
View File
@@ -20,12 +20,12 @@
#include <set>
#include <string>
#include <unordered_map>
#include <map>
#include "..\main.h"
#include "..\FalloutEngine\Fallout2.h"
#include "..\InputFuncs.h"
#include "..\Logging.h"
#include "..\SimplePatch.h"
#include "..\Version.h"
#include "..\Utils.h"
#include "BarBoxes.h"
@@ -47,7 +47,6 @@ using namespace script;
static DWORD _stdcall HandleMapUpdateForScripts(const DWORD procId);
// TODO: move to a better place
static int idle;
struct GlobalScript {
@@ -71,6 +70,9 @@ struct ExportedVar {
ExportedVar() : val(0), type(VAR_TYPE_INT) {}
};
static std::vector<std::string> globalScriptPathList;
static std::map<std::string, std::string> globalScriptFilesList;
static std::vector<fo::Program*> checkedScripts;
static std::vector<GlobalScript> globalScripts;
// a map of all sfall programs (global and hook scripts) by thier scriptPtr
@@ -176,7 +178,7 @@ static void __declspec(naked) ExecMapScriptsHack() {
push ebp;
sub esp, 0x20;
//------
push eax; // int procId
push eax; // procId
call HandleMapUpdateForScripts;
jmp ExecMapScriptsRet;
}
@@ -411,52 +413,64 @@ bool _stdcall IsGameScript(const char* filename) {
return false;
}
void LoadGLobalScriptsByMask(const std::string& fileMask) {
char* *filenames;
auto basePath = fileMask.substr(0, fileMask.find_last_of("\\/") + 1);
ToLowerCase(basePath);
int count = fo::func::db_get_file_list(fileMask.c_str(), &filenames);
// TODO: refactor script programs
static void LoadGlobalScriptsList() {
ScriptProgram prog;
for (int i = 0; i < count; i++) {
char* name = _strlwr(filenames[i]);
std::string baseName(name);
baseName = baseName.substr(0, baseName.find_last_of('.'));
if (basePath != fo::var::script_path_base || !IsGameScript(baseName.c_str())) {
dlog(">", DL_SCRIPT);
std::string fullPath(basePath);
fullPath += name;
dlog(fullPath, DL_SCRIPT);
isGlobalScriptLoading = 1;
LoadScriptProgram(prog, fullPath.c_str(), true);
if (prog.ptr) {
dlogr(" Done", DL_SCRIPT);
DWORD idx;
GlobalScript gscript = GlobalScript(prog);
idx = globalScripts.size();
globalScripts.push_back(gscript);
AddProgramToMap(prog);
// 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;
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);
globalScripts.push_back(gscript);
AddProgramToMap(prog);
// 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;
}
fo::func::db_free_file_list(&filenames, 0);
}
static void PrepareGlobalScriptsListByMask() {
for (auto& fileMask : globalScriptPathList) {
char** filenames;
auto basePath = fileMask.substr(0, fileMask.find_last_of("\\/") + 1); // path to scripts without mask
int count = fo::func::db_get_file_list(fileMask.c_str(), &filenames);
for (int i = 0; i < count; i++) {
char* name = _strlwr(filenames[i]); // name of the script in lower case
std::string baseName(name);
baseName = baseName.substr(0, baseName.find_last_of('.')); // script name without extension
if (basePath != fo::var::script_path_base || !IsGameScript(baseName.c_str())) {
std::string fullPath(basePath);
fullPath += name;
// prevent loading global scripts with the same name from different directories
if (globalScriptFilesList.find(baseName) != globalScriptFilesList.end()) {
fo::func::debug_printf("\n[SFALL] Script: %s will not be executed. A script with the same name already exists in another directory.", fullPath);
continue;
}
globalScriptFilesList.insert(std::make_pair(baseName, fullPath));
}
}
fo::func::db_free_file_list(&filenames, 0);
}
globalScriptPathList.clear(); // clear path list, it is no longer needed
}
// this runs after the game was loaded/started
void LoadGlobalScripts() {
static void LoadGlobalScripts() {
isGameLoading = false;
LoadHookScripts();
dlogr("Loading global scripts", DL_SCRIPT|DL_INIT);
auto maskList = GetConfigList("Scripts", "GlobalScriptPaths", "scripts\\gl*.int", 255);
for (auto& mask : maskList) {
LoadGLobalScriptsByMask(mask);
globalScriptPathList = GetConfigList("Scripts", "GlobalScriptPaths", "scripts\\gl*.int", 255);
for (unsigned int i = 0; i < globalScriptPathList.size(); i++) {
ToLowerCase(globalScriptPathList[i]);
}
PrepareGlobalScriptsListByMask();
LoadGlobalScriptsList();
dlogr("Finished loading global scripts", DL_SCRIPT|DL_INIT);
}
@@ -486,7 +500,7 @@ void _stdcall RegAnimCombatCheck(DWORD newValue) {
}
// this runs before actually loading/starting the game
void ClearGlobalScripts() {
static void ClearGlobalScripts() {
isGameLoading = true;
checkedScripts.clear();
sfallProgsMap.clear();
@@ -534,11 +548,10 @@ static void ResetStateAfterFrame() {
}
static inline void RunGlobalScripts(int mode1, int mode2) {
// TODO: move processor idle out?
if (idle > -1 && idle <= 127) {
Sleep(idle);
}
for (DWORD d=0; d<globalScripts.size(); d++) {
for (DWORD d = 0; d < globalScripts.size(); d++) {
if (globalScripts[d].repeat
&& (globalScripts[d].mode == mode1 || globalScripts[d].mode == mode2)
&& ++globalScripts[d].count >= globalScripts[d].repeat) {
@@ -552,13 +565,13 @@ static void RunGlobalScriptsOnMainLoop() {
RunGlobalScripts(0, 3);
}
void RunGlobalScriptsOnInput() {
static void RunGlobalScriptsOnInput() {
if (IsMapLoaded()) {
RunGlobalScripts(1, 1);
}
}
void RunGlobalScriptsOnWorldMap() {
static void RunGlobalScriptsOnWorldMap() {
RunGlobalScripts(2, 3);
}
@@ -570,7 +583,7 @@ static DWORD _stdcall HandleMapUpdateForScripts(const DWORD procId) {
}
}
RunGlobalScriptsAtProc(procId); // gl* scripts of types 0 and 3
RunHookScriptsAtProc(procId); // all hs_ scripts
RunHookScriptsAtProc(procId); // all hs_ scripts
return procId; // restore eax (don't delete)
}
@@ -608,7 +621,7 @@ void SaveGlobals(HANDLE h) {
}
}
void ClearGlobals() {
static void ClearGlobals() {
globalVars.clear();
for (array_itr it = arrays.begin(); it != arrays.end(); ++it) {
it->second.clear();
@@ -653,7 +666,6 @@ void ScriptExtender::init() {
OnInputLoop() += RunGlobalScriptsOnInput;
Worldmap::OnWorldmapLoop() += RunGlobalScriptsOnWorldMap;
// TODO: move out?
idle = GetConfigInt("Misc", "ProcessorIdle", -1);
if (idle > -1 && idle <= 127) {
fo::var::idle_func = reinterpret_cast<DWORD>(Sleep);
+2 -2
View File
@@ -72,8 +72,8 @@ static int __fastcall check_stat_level(register int value, int stat) {
static const DWORD StatLevelHackCheck_Ret = 0x4AF3D7;
static void __declspec(naked) stat_level_hack_check() {
__asm {
mov edx, esi;
call check_stat_level; // ecx - value stat
mov edx, esi; // stat
call check_stat_level; // ecx - value
jmp StatLevelHackCheck_Ret;
}
}