diff --git a/artifacts/ddraw.ini b/artifacts/ddraw.ini index 1d9c8c35..ad14f7da 100644 --- a/artifacts/ddraw.ini +++ b/artifacts/ddraw.ini @@ -1,5 +1,5 @@ ;sfall configuration settings -;v3.8.28 +;v3.8.28.1 [Main] ;Change to 1 if you want to use command line args to tell sfall to use another ini file. @@ -687,6 +687,9 @@ CarPlacedTileFix=1 InstantWeaponEquip=0 ;To add additional game msg files, uncomment the next line and set a comma delimited list of filenames without .msg extension +;By default, the files will have consecutive numbers assigned beginning with 0 +;You can use the syntax 'filename:number' to manually assign numbers to specific msg files, with each pair separated by a comma +;If a file after the specified pair does not have a number assigned, it will have the next consecutive number from the last pair ;You need to use the message_str_game script function to get messages from the files ;ExtraGameMsgFileList= diff --git a/artifacts/scripting/sfall function notes.txt b/artifacts/scripting/sfall function notes.txt index 65686290..dce57b62 100644 --- a/artifacts/scripting/sfall function notes.txt +++ b/artifacts/scripting/sfall function notes.txt @@ -324,6 +324,7 @@ Some utility/math functions are available: - works exactly the same as message_str, except you get messages from files in "text\\game\" directory - use GAME_MSG_* defines or mstr_* macros from sfall.h to use specific msg file - Additional game msg files added by ExtraGameMsgFileList setting will have consecutive fileIds assigned beginning from 0x2000 to 0x2FFF. (e.g. if you set ExtraGameMsgFileList=foo,bar in ddraw.ini, foo.msg will be associated with 0x2000 and bar.msg with 0x2001.) +- if a file has a specific number assigned in ExtraGameMsgFileList, its fileId will be (0x2000 + assigned number). (e.g. with ExtraGameMsgFileList=foo,bar:2,foobar in ddraw.ini, bar.msg will be associated with 0x2002 and foobar.msg with 0x2003.) > int sneak_success - returns 1 if the player is currently sneaking, and last sneak attempt (roll against skill) was successful; 0 otherwise diff --git a/sfall/LoadGameHook.cpp b/sfall/LoadGameHook.cpp index a1b68928..6edc233f 100644 --- a/sfall/LoadGameHook.cpp +++ b/sfall/LoadGameHook.cpp @@ -346,10 +346,6 @@ static void __declspec(naked) NewGame() { } } -static void ReadExtraGameMsgFilesIfNeeded() { - if (gExtraGameMsgLists.empty()) ReadExtraGameMsgFiles(); -} - static void __declspec(naked) MainMenuHook() { __asm { pushad; @@ -357,7 +353,7 @@ static void __declspec(naked) MainMenuHook() { call ResetState; mov al, pipBoyAvailableAtGameStart; mov byte ptr ds:[_gmovie_played_list + 3], al; - call ReadExtraGameMsgFilesIfNeeded; + call ReadExtraGameMsgFiles; popad; jmp main_menu_loop_; } diff --git a/sfall/Message.cpp b/sfall/Message.cpp index b0947d58..7cc23b05 100644 --- a/sfall/Message.cpp +++ b/sfall/Message.cpp @@ -17,9 +17,10 @@ */ #include -#include "main.h" +#include "main.h" #include "FalloutEngine.h" + #include "Message.h" #define CASTMSG(adr) reinterpret_cast(adr) @@ -48,6 +49,7 @@ const MSGList* gameMsgFiles[] = { #undef CASTMSG ExtraGameMessageListsMap gExtraGameMsgLists; +static std::vector msgFileList; // Loads the msg file from the 'english' folder if it does not exist in the current language directory static void __declspec(naked) message_load_hook() { @@ -106,40 +108,27 @@ char* GetMsg(MSGList* msgList, int msgRef, int msgNum) { } void ReadExtraGameMsgFiles() { - int read; - std::string names; - - names.resize(256); - - while ((read = GetConfigString("Misc", "ExtraGameMsgFileList", "", - (LPSTR)names.data(), names.size())) == names.size() - 1) - names.resize(names.size() + 256); - - if (names.empty()) return; - - names.resize(names.find_first_of('\0')); - names.append(","); - - int begin = 0; - int end; - int length; - int number = 0; - - while ((end = names.find_first_of(',', begin)) != std::string::npos) { - length = end - begin; - - if (length > 0) { - std::string path = "game\\" + names.substr(begin, length) + ".msg"; - MSGList* list = new MSGList; + if (!msgFileList.empty()) { + int number = 0; + for (std::vector::const_iterator it = msgFileList.begin(); it != msgFileList.end(); ++it) { + std::string path("game\\"); + size_t n = it->find(':'); + if (n == std::string::npos) { + path += *it; + } else { + path += it->substr(0, n); + number = std::stoi(it->substr(n + 1), nullptr, 0); + } + path += ".msg"; + MSGList* list = new MSGList(); if (MessageLoad(list, path.c_str()) == 1) { gExtraGameMsgLists.insert(std::make_pair(0x2000 + number, list)); } else { delete list; } + if (++number == 4096) break; } - if (++number == 4096) break; - - begin = end + 1; + msgFileList.clear(); } } @@ -156,3 +145,11 @@ void ClearReadExtraGameMsgFiles() { delete it->second; } } + +void MessageInit() { + msgFileList = GetConfigList("Misc", "ExtraGameMsgFileList", "", 512); +} + +//void MessageExit() { + //gExtraGameMsgLists.clear(); +//} diff --git a/sfall/Message.h b/sfall/Message.h index 0dc66fb6..d6e1fc8a 100644 --- a/sfall/Message.h +++ b/sfall/Message.h @@ -19,6 +19,7 @@ #pragma once #include + #include "main.h" #define MSG_FILE_COMBAT (0x56D368) @@ -46,9 +47,12 @@ typedef std::tr1::unordered_map ExtraGameMessageListsMap; extern ExtraGameMessageListsMap gExtraGameMsgLists; extern const MSGList* gameMsgFiles[]; -MSGNode* GetMsgNode(MSGList* msgList, int msgRef); -char* GetMsg(MSGList* msgList, int msgRef, int msgNum); +void MessageInit(); +//void MessageExit(); void ReadExtraGameMsgFiles(); void FallbackEnglishLoadMsgFiles(); void ClearReadExtraGameMsgFiles(); + +MSGNode* GetMsgNode(MSGList* msgList, int msgRef); +char* GetMsg(MSGList* msgList, int msgRef, int msgNum); diff --git a/sfall/main.cpp b/sfall/main.cpp index eb0f0ffb..7f1a6ad4 100644 --- a/sfall/main.cpp +++ b/sfall/main.cpp @@ -254,6 +254,9 @@ static void DllMain2() { dlogr("Running ExplosionInit().", DL_INIT); ExplosionInit(); + dlogr("Running MessageInit().", DL_INIT); + MessageInit(); + dlogr("Running ElevatorsInit().", DL_INIT); ElevatorsInit(); @@ -304,7 +307,7 @@ static void __stdcall OnExit() { ConsoleExit(); ExtraSaveSlotsExit(); BooksExit(); - //gExtraGameMsgLists.clear(); + //MessageExit(); AnimationsExit(); BarBoxesExit(); HeroAppearanceModExit();