Added IniConfigFolder option to override the path of all scripted ini

Fixed a crash bug in message_str_game function when passing a negative
fileId value.
This commit is contained in:
NovaRain
2019-08-20 00:26:35 +08:00
parent 9d0b061d1b
commit 5c4eb31bc3
7 changed files with 76 additions and 11 deletions
+6 -1
View File
@@ -364,7 +364,7 @@ AdditionalWeaponAnims=1
;If the ExtraKillTypes option is enabled, this should be set to 3, with containing entries for any new types
;Must be non-zero to use the edit/get/reset_critical script functions
OverrideCriticalTable=2
;Uncomment the next line to specify an alternative path and file name for the critical table file
;To change the path and filename of the critical table file, uncomment the next line
;OverrideCriticalFile=CriticalOverrides.ini
;Set to 1 to get notification of karma changes in the notification window
@@ -724,6 +724,11 @@ CreditsAtBottom=0
;Paths outside of scripts folder are supported
GlobalScriptPaths=scripts\gl*.int,scripts\sfall\gl*.int
;Uncomment the option to specify a common folder path for all scripted ini configuration files
;You will need to place all the available ini files of the mods to this directory
;The maximum length of the specified path is 61 characters
;IniConfigFolder=IniConfig
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[Debugging]
;Extra sfall configuration settings that can be used by modders
+15
View File
@@ -53,6 +53,8 @@ static DWORD _stdcall HandleMapUpdateForScripts(const DWORD procId);
static int idle;
std::string ScriptExtender::iniConfigFolder;
struct GlobalScript {
ScriptProgram prog;
int count;
@@ -724,6 +726,19 @@ void ScriptExtender::init() {
dlogr("Arrays in backward-compatiblity mode.", DL_SCRIPT);
}
iniConfigFolder = GetConfigString("Scripts", "IniConfigFolder", "");
size_t len = iniConfigFolder.length();
if (len) {
char c = iniConfigFolder[len - 1];
bool pathSeparator = (c == '\\' || c == '/');
if (len > 62 || (len == 62 && !pathSeparator)) {
iniConfigFolder.clear();
dlogr("Error: IniConfigFolder path is too long.", DL_SCRIPT);
} else if (!pathSeparator) {
iniConfigFolder += '\\';
}
}
alwaysFindScripts = isDebug && (GetPrivateProfileIntA("Debugging", "AlwaysFindScripts", 0, ::sfall::ddrawIni) != 0);
if (alwaysFindScripts) dlogr("Always searching for global scripts behavior enabled.", DL_SCRIPT);
+2
View File
@@ -32,6 +32,8 @@ public:
const char* name() { return "ScriptExtender"; }
void init();
static std::string iniConfigFolder;
// Called before map exit (before map_exit_p_proc handlers in normal scripts)
static Delegate<>& OnMapExit();
};
+37 -9
View File
@@ -18,6 +18,7 @@
#include <cstring>
#include "..\..\..\Utils.h"
#include "..\..\..\FalloutEngine\Fallout2.h"
#include "..\..\AI.h"
#include "..\..\Combat.h"
@@ -523,7 +524,8 @@ static int ParseIniSetting(const char* iniString, const char* &key, char section
if (!key) return -1;
DWORD filelen = (DWORD)key - (DWORD)iniString;
if (filelen >= 64) return -1;
if (ScriptExtender::iniConfigFolder.empty() && filelen >= 64) return -1;
const char* fileEnd = key;
key = strstr(key + 1, "|");
if (!key) return -1;
@@ -533,9 +535,24 @@ static int ParseIniSetting(const char* iniString, const char* &key, char section
file[0] = '.';
file[1] = '\\';
memcpy(&file[2], iniString, filelen);
file[filelen + 2] = 0;
if (!ScriptExtender::iniConfigFolder.empty()) {
const char* pos = strfind(iniString, &::sfall::ddrawIni[2]);
if (pos && pos < fileEnd) goto ddraw;
size_t len = ScriptExtender::iniConfigFolder.length(); // limit to 62 characters
memcpy(&file[2], ScriptExtender::iniConfigFolder.c_str(), len);
int n = 0; // position of the beginning of the file name
for (int i = filelen - 4; i > 0; i--) {
if (iniString[i] == '\\' || iniString[i] == '/') {
n = i + 1;
break;
}
}
strncpy_s(&file[2 + len], (128 - 2) - len, &iniString[n], filelen - n); // copy filename (max len 63)
} else {
ddraw:
memcpy(&file[2], iniString, filelen);
file[filelen + 2] = 0;
}
memcpy(section, &iniString[filelen + 1], seclen);
section[seclen] = 0;
@@ -546,7 +563,7 @@ static int ParseIniSetting(const char* iniString, const char* &key, char section
static char IniStrBuffer[256];
static DWORD GetIniSetting(const char* str, bool isString) {
const char* key;
char section[33], file[67];
char section[33], file[128];
if (ParseIniSetting(str, key, section, file) < 0) {
return -1;
@@ -1232,11 +1249,23 @@ void sf_set_ini_setting(OpcodeContext& ctx) {
}
}
static std::string GetIniFilePath(const ScriptValue& arg) {
std::string fileName(".\\");
if (ScriptExtender::iniConfigFolder.empty()) {
fileName += arg.strValue();
} else {
fileName += ScriptExtender::iniConfigFolder;
std::string name(arg.strValue());
int pos = name.find_last_of("\\/");
fileName += (pos > 0) ? name.substr(pos + 1) : name;
}
return fileName;
}
char getIniSectionBuf[5120];
void sf_get_ini_sections(OpcodeContext& ctx) {
auto fileName = std::string(".\\") + ctx.arg(0).asString();
GetPrivateProfileSectionNamesA(getIniSectionBuf, 5120, fileName.data());
GetPrivateProfileSectionNamesA(getIniSectionBuf, 5120, GetIniFilePath(ctx.arg(0)).data());
std::vector<char*> sections;
char* section = getIniSectionBuf;
while (*section != 0) {
@@ -1256,9 +1285,8 @@ void sf_get_ini_sections(OpcodeContext& ctx) {
}
void sf_get_ini_section(OpcodeContext& ctx) {
auto fileName = std::string(".\\") + ctx.arg(0).asString();
auto section = ctx.arg(1).asString();
GetPrivateProfileSectionA(section, getIniSectionBuf, 5120, fileName.data());
GetPrivateProfileSectionA(section, getIniSectionBuf, 5120, GetIniFilePath(ctx.arg(0)).data());
int arrayId = TempArray(-1, 0); // associative
auto& arr = arrays[arrayId];
char *key = getIniSectionBuf, *val = nullptr;
+1 -1
View File
@@ -281,7 +281,7 @@ void sf_message_str_game(OpcodeContext& ctx) {
int fileId = fileIdArg.asInt();
int msgId = msgIdArg.asInt();
if (fileId < 20) { // main msg files
if (fileId >= 0 && fileId <= 19) { // main msg files
msg = fo::GetMessageStr(gameMsgFiles[fileId], msgId);
} else if (fileId >= 0x1000 && fileId <= 0x1005) { // proto msg files
msg = fo::GetMessageStr(&fo::var::proto_msg_files[fileId - 0x1000], msgId);
+13
View File
@@ -47,4 +47,17 @@ void strtrim(char* str) {
}
}
// returns position, find word must be lowercase
const char* strfind(const char* source, const char* word) {
if (source == 0 || word == 0 || *word == 0) return 0;
const char *w_pos, *s_pos;
while(*source != 0) {
w_pos = word, s_pos = source++;
while (tolower(*s_pos++) == *w_pos++) {
if (*w_pos == 0) return s_pos - (w_pos - word);
}
}
return 0;
}
}
+2
View File
@@ -32,4 +32,6 @@ bool isSpace(char c);
void strtrim(char* str);
const char* strfind(const char* source, const char* word);
}