Added "add_extra_msg_file" and "metarule_exist" script functions.

This commit is contained in:
NovaRain
2019-06-14 11:05:42 +08:00
parent 88438edbc5
commit ddda559898
9 changed files with 75 additions and 17 deletions
+2
View File
@@ -244,6 +244,7 @@
#define ADD_PERK_MODE_REMOVE (4) // remove from the list of selectable perks #define ADD_PERK_MODE_REMOVE (4) // remove from the list of selectable perks
// sfall_funcX macros // sfall_funcX macros
#define add_extra_msg_file(name, number) sfall_func2("add_extra_msg_file", name, number)
#define add_iface_tag sfall_func0("add_iface_tag") #define add_iface_tag sfall_func0("add_iface_tag")
#define art_cache_clear sfall_func0("art_cache_clear") #define art_cache_clear sfall_func0("art_cache_clear")
#define attack_is_aimed sfall_func0("attack_is_aimed") #define attack_is_aimed sfall_func0("attack_is_aimed")
@@ -280,6 +281,7 @@
#define item_weight(obj) sfall_func1("item_weight", obj) #define item_weight(obj) sfall_func1("item_weight", obj)
#define lock_is_jammed(obj) sfall_func1("lock_is_jammed", obj) #define lock_is_jammed(obj) sfall_func1("lock_is_jammed", obj)
#define loot_obj sfall_func0("loot_obj") #define loot_obj sfall_func0("loot_obj")
#define metarule_exist(metarule) sfall_func1("metarule_exist", metarule)
#define npc_engine_level_up(toggle) sfall_func1("npc_engine_level_up", toggle) #define npc_engine_level_up(toggle) sfall_func1("npc_engine_level_up", toggle)
#define obj_under_cursor(crSwitch, inclDude) sfall_func2("obj_under_cursor", crSwitch, inclDude) #define obj_under_cursor(crSwitch, inclDude) sfall_func2("obj_under_cursor", crSwitch, inclDude)
#define outlined_object sfall_func0("outlined_object") #define outlined_object sfall_func0("outlined_object")
+10 -2
View File
@@ -319,7 +319,7 @@ Some utility/math functions are available:
> string message_str_game(int fileId, int messageId) > string message_str_game(int fileId, int messageId)
- works exactly the same as message_str, except you get messages from files in "text\<language>\game\" directory - works exactly the same as message_str, except you get messages from files in "text\<language>\game\" directory
- use GAME_MSG_* defines or mstr_* macros from sfall.h to use specific msg file - 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. (e.g. if you set ExtraGameMsgFileList=foo,bar in ddraw.ini, foo.msg will be associated with 0x2000 and bar.msg with 0x2001.) - 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.) - 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 > int sneak_success
@@ -374,8 +374,11 @@ Some utility/math functions are available:
> array sfall_func0("get_metarule_table") > array sfall_func0("get_metarule_table")
- returns names of all currently available scripting functions (via sfall_funcX) - returns names of all currently available scripting functions (via sfall_funcX)
> bool sfall_func1("metarule_exist", string metaruleName)
- returns True if the specified name of metarule (sfall_funcX) function exists in the current version of sfall
> int sfall_func1("spatial_radius", object object) > int sfall_func1("spatial_radius", object object)
- return radius of spatial script, associated with given dummy-object (returned by create_spatial) - returns radius of spatial script, associated with given dummy-object (returned by create_spatial)
> object sfall_func2("critter_inven_obj2", object invenObj, int type) > object sfall_func2("critter_inven_obj2", object invenObj, int type)
- works just like vanilla critter_inven_obj, but correctly reports item in player's inactive hand slot - works just like vanilla critter_inven_obj, but correctly reports item in player's inactive hand slot
@@ -606,6 +609,11 @@ optional arguments:
> int sfall_func2("has_fake_trait_npc", object npc, string nameTrait) > int sfall_func2("has_fake_trait_npc", object npc, string nameTrait)
- these functions are similar to has_fake_*/set_fake_*/set_selectable_perk functions, but apply to the specified party member NPC (including dude_obj) - these functions are similar to has_fake_*/set_fake_*/set_selectable_perk functions, but apply to the specified party member NPC (including dude_obj)
> void sfall_func2("add_extra_msg_file", string fileName, int fileNumber)
- loads the custom message file and assigns it with the specified ID number
- fileName: the name of the custom message file (including the .msg extension) in "text\<language>\game\" directory
- fileNumber: the file ID number for the message_str_game function to get messages from the file. The available range is from 0x3000 to 0x3FFF
------------------------ ------------------------
------ MORE INFO ------- ------ MORE INFO -------
------------------------ ------------------------
+34 -12
View File
@@ -54,7 +54,7 @@ const fo::MessageList* gameMsgFiles[] = {
#undef CASTMSG #undef CASTMSG
ExtraGameMessageListsMap gExtraGameMsgLists; ExtraGameMessageListsMap gExtraGameMsgLists;
std::vector<std::string> msgFileList; static std::vector<std::string> msgFileList;
fo::MessageNode *GetMsgNode(fo::MessageList *msgList, int msgRef) { fo::MessageNode *GetMsgNode(fo::MessageList *msgList, int msgRef) {
if (msgList != nullptr && msgList->numMsgs > 0) { if (msgList != nullptr && msgList->numMsgs > 0) {
@@ -89,11 +89,11 @@ char* GetMsg(fo::MessageList *msgList, int msgRef, int msgNum) {
return nullptr; return nullptr;
} }
void ReadExtraGameMsgFiles() { static void ReadExtraGameMsgFiles() {
if (msgFileList.size() > 0) { if (!msgFileList.empty()) {
int number = 0; int number = 0;
for (auto& msgName : msgFileList) { for (auto& msgName : msgFileList) {
std::string path = "game\\"; std::string path("game\\");
auto n = msgName.find(':'); auto n = msgName.find(':');
if (n == std::string::npos) { if (n == std::string::npos) {
path += msgName; path += msgName;
@@ -108,25 +108,47 @@ void ReadExtraGameMsgFiles() {
} else { } else {
delete list; delete list;
} }
number++; if (++number == 4096) break;
}
msgFileList.clear();
}
}
long Message::AddExtraMsgFile(const char* msgName, long msgNumber) {
if (msgNumber < 0x3000 || msgNumber > 0x3FFF || gExtraGameMsgLists.count(msgNumber)) return -1;
std::string path("game\\");
path += msgName;
fo::MessageList* list = new fo::MessageList();
if (fo::func::message_load(list, path.c_str())) {
gExtraGameMsgLists.emplace(msgNumber, list);
} else {
delete list;
}
return 0;
}
static void ClearScriptAddedExtraGameMsg() { // C++11
for (auto it = gExtraGameMsgLists.begin(); it != gExtraGameMsgLists.end();) {
if (it->first >= 0x3000 && it->first <= 0x3FFF) {
fo::func::message_exit(it->second.get());
it = gExtraGameMsgLists.erase(it);
} else {
++it;
} }
} }
} }
void ClearReadExtraGameMsgFiles() { static void ClearReadExtraGameMsgFiles() {
ExtraGameMessageListsMap::iterator it; for (auto it = gExtraGameMsgLists.begin(); it != gExtraGameMsgLists.end(); ++it) {
for (it = gExtraGameMsgLists.begin(); it != gExtraGameMsgLists.end(); ++it) {
fo::func::message_exit(it->second.get()); fo::func::message_exit(it->second.get());
} }
//gExtraGameMsgLists.clear();
gExtraGameMsgLists.clear();
msgFileList.clear();
} }
void Message::init() { void Message::init() {
msgFileList = GetConfigList("Misc", "ExtraGameMsgFileList", "", 512); msgFileList = GetConfigList("Misc", "ExtraGameMsgFileList", "", 512);
LoadGameHook::OnBeforeGameStart() += ReadExtraGameMsgFiles; LoadGameHook::OnBeforeGameStart() += ReadExtraGameMsgFiles;
LoadGameHook::OnGameReset() += ClearScriptAddedExtraGameMsg;
} }
void Message::exit() { void Message::exit() {
+2
View File
@@ -37,6 +37,8 @@ public:
const char* name() { return "Message"; } const char* name() { return "Message"; }
void init(); void init();
void exit() override; void exit() override;
static long AddExtraMsgFile(const char* msgName, long msgNumber);
}; };
fo::MessageNode *GetMsgNode(fo::MessageList *msgList, int msgRef); fo::MessageNode *GetMsgNode(fo::MessageList *msgList, int msgRef);
@@ -59,6 +59,7 @@ static MetaruleTableType metaruleTable;
- arg1, arg2, ... - argument types for automatic validation - arg1, arg2, ... - argument types for automatic validation
*/ */
static const SfallMetarule metarules[] = { static const SfallMetarule metarules[] = {
{"add_extra_msg_file", sf_add_extra_msg_file, 2, 2, {ARG_STRING, ARG_INT}},
{"add_iface_tag", sf_add_iface_tag, 0, 0}, {"add_iface_tag", sf_add_iface_tag, 0, 0},
{"art_cache_clear", sf_art_cache_flush, 0, 0}, {"art_cache_clear", sf_art_cache_flush, 0, 0},
{"attack_is_aimed", sf_attack_is_aimed, 0, 0}, {"attack_is_aimed", sf_attack_is_aimed, 0, 0},
@@ -95,6 +96,7 @@ static const SfallMetarule metarules[] = {
{"item_weight", sf_item_weight, 1, 1, {ARG_OBJECT}}, {"item_weight", sf_item_weight, 1, 1, {ARG_OBJECT}},
{"lock_is_jammed", sf_lock_is_jammed, 1, 1, {ARG_OBJECT}}, {"lock_is_jammed", sf_lock_is_jammed, 1, 1, {ARG_OBJECT}},
{"loot_obj", sf_get_loot_object, 0, 0}, {"loot_obj", sf_get_loot_object, 0, 0},
{"metarule_exist", sf_metarule_exist, 1, 1},
{"npc_engine_level_up", sf_npc_engine_level_up, 1, 1, {ARG_ANY}}, {"npc_engine_level_up", sf_npc_engine_level_up, 1, 1, {ARG_ANY}},
{"obj_under_cursor", sf_get_obj_under_cursor, 2, 2, {ARG_INT, ARG_INT}}, {"obj_under_cursor", sf_get_obj_under_cursor, 2, 2, {ARG_INT, ARG_INT}},
{"outlined_object", sf_outlined_object, 0, 0}, {"outlined_object", sf_outlined_object, 0, 0},
@@ -136,6 +138,20 @@ static void sf_get_metarule_table(OpcodeContext& ctx) {
ctx.setReturn(arrId, DataType::INT); ctx.setReturn(arrId, DataType::INT);
} }
static void sf_metarule_exist(OpcodeContext& ctx) {
bool result = false;
auto funcXName = ctx.arg(0).asString();
if (funcXName[0] != '\0') {
for (auto it = metaruleTable.begin(); it != metaruleTable.end(); it++) {
if (it->first == funcXName) {
result = true;
break;
}
}
}
ctx.setReturn(result);
}
void InitMetaruleTable() { void InitMetaruleTable() {
for (auto metarule = std::begin(metarules); metarule != std::end(metarules); ++metarule) { for (auto metarule = std::begin(metarules); metarule != std::end(metarules); ++metarule) {
metaruleTable[metarule->name] = metarule; metaruleTable[metarule->name] = metarule;
@@ -38,6 +38,8 @@ void sf_test(OpcodeContext&);
// returns current contents of metarule table // returns current contents of metarule table
void sf_get_metarule_table(OpcodeContext&); void sf_get_metarule_table(OpcodeContext&);
void sf_metarule_exist(OpcodeContext&);
void InitMetaruleTable(); void InitMetaruleTable();
void HandleMetarule(OpcodeContext& ctx); void HandleMetarule(OpcodeContext& ctx);
+6 -2
View File
@@ -287,18 +287,22 @@ void sf_message_str_game(OpcodeContext& ctx) {
msg = fo::GetMessageStr(&fo::var::proto_msg_files[fileId - 0x1000], msgId); msg = fo::GetMessageStr(&fo::var::proto_msg_files[fileId - 0x1000], msgId);
} else if (fileId >= 0x2000) { // Extra game message files. } else if (fileId >= 0x2000) { // Extra game message files.
ExtraGameMessageListsMap::iterator it = gExtraGameMsgLists.find(fileId); ExtraGameMessageListsMap::iterator it = gExtraGameMsgLists.find(fileId);
if (it != gExtraGameMsgLists.end()) { if (it != gExtraGameMsgLists.end()) {
msg = GetMsg(it->second.get(), msgId, 2); msg = GetMsg(it->second.get(), msgId, 2);
} }
} }
if (msg == nullptr) { if (msg == nullptr) {
msg = "Error"; msg = "Error";
} }
ctx.setReturn(msg); ctx.setReturn(msg);
} }
void sf_add_extra_msg_file(OpcodeContext& ctx) {
long result = Message::AddExtraMsgFile(ctx.arg(0).strValue(), ctx.arg(1).rawValue());
if (result == -1) ctx.printOpcodeError("%s() - cannot add message file with the specified number.", ctx.getMetaruleName());
ctx.setReturn(result);
}
void sf_floor2(OpcodeContext& ctx) { void sf_floor2(OpcodeContext& ctx) {
ctx.setReturn(static_cast<int>(floor(ctx.arg(0).asFloat()))); ctx.setReturn(static_cast<int>(floor(ctx.arg(0).asFloat())));
} }
+2
View File
@@ -65,6 +65,8 @@ void sf_round(OpcodeContext&);
void sf_message_str_game(OpcodeContext&); void sf_message_str_game(OpcodeContext&);
void sf_add_extra_msg_file(OpcodeContext&);
void sf_floor2(OpcodeContext&); void sf_floor2(OpcodeContext&);
void sf_get_string_pointer(OpcodeContext&); void sf_get_string_pointer(OpcodeContext&);
+1 -1
View File
@@ -555,7 +555,7 @@ void WorldMapInterfacePatch() {
SafeWrite32(0x4C2C92, 181); // index of DNARWOFF.FRM SafeWrite32(0x4C2C92, 181); // index of DNARWOFF.FRM
SafeWrite8(0x4C2D04, 0x46); // dec esi > inc esi SafeWrite8(0x4C2D04, 0x46); // dec esi > inc esi
// Fix the position of the target marker for location circles // Fix the position of the target marker for small/medium location circles
MakeCall(0x4C03AA, wmWorldMap_hack, 2); MakeCall(0x4C03AA, wmWorldMap_hack, 2);
} }