Backported "set_scr_name" script function from 4.x

Updated documents for the function.
Changed some make_pair to bare pair for map insertion.
This commit is contained in:
NovaRain
2021-10-05 22:04:12 +08:00
parent e3cb0bbaf5
commit 5c1cccae8f
13 changed files with 162 additions and 9 deletions
+2
View File
@@ -350,6 +350,7 @@
#define set_object_data(obj, offset, value) sfall_func3("set_object_data", obj, offset, value) #define set_object_data(obj, offset, value) sfall_func3("set_object_data", obj, offset, value)
#define set_outline(obj, color) sfall_func2("set_outline", obj, color) #define set_outline(obj, color) sfall_func2("set_outline", obj, color)
#define set_quest_failure_value(gvar, threshold) sfall_func2("set_quest_failure_value", gvar, threshold) #define set_quest_failure_value(gvar, threshold) sfall_func2("set_quest_failure_value", gvar, threshold)
#define set_scr_name(name) sfall_func1("set_scr_name", name)
#define set_terrain_name(x, y, name) sfall_func3("set_terrain_name", x, y, name) #define set_terrain_name(x, y, name) sfall_func3("set_terrain_name", x, y, name)
#define set_town_title(areaID, title) sfall_func2("set_town_title", areaID, title) #define set_town_title(areaID, title) sfall_func2("set_town_title", areaID, title)
#define set_unique_id(obj) sfall_func1("set_unique_id", obj) #define set_unique_id(obj) sfall_func1("set_unique_id", obj)
@@ -366,6 +367,7 @@
#define tile_by_position(x, y) sfall_func2("tile_by_position", x, y) #define tile_by_position(x, y) sfall_func2("tile_by_position", x, y)
#define tile_refresh_display sfall_func0("tile_refresh_display") #define tile_refresh_display sfall_func0("tile_refresh_display")
#define unjam_lock(obj) sfall_func1("unjam_lock", obj) #define unjam_lock(obj) sfall_func1("unjam_lock", obj)
#define unset_scr_name sfall_func0("set_scr_name") /* sets the name of the script object from pro_*.msg instead of scrname.msg */
#define unset_unique_id(obj) sfall_func2("set_unique_id", obj, -1) #define unset_unique_id(obj) sfall_func2("set_unique_id", obj, -1)
#define unwield_slot(critter, slot) sfall_func2("unwield_slot", critter, slot) #define unwield_slot(critter, slot) sfall_func2("unwield_slot", critter, slot)
#define win_fill_color(x, y, width, height, color) sfall_func5("win_fill_color", x, y, width, height, color) #define win_fill_color(x, y, width, height, color) sfall_func5("win_fill_color", x, y, width, height, color)
@@ -963,6 +963,15 @@ sfall_funcX metarule functions
- `gvarNumber`: the number of the global variable controlling the quest - `gvarNumber`: the number of the global variable controlling the quest
- `thresholdValue`: the value of the global variable at which the quest is counted as a failure - `thresholdValue`: the value of the global variable at which the quest is counted as a failure
----
#### set_scr_name
`void sfall_func1("set_scr_name", string name)`
- Overrides the name of the script object that was set from **scrname.msg**
- The changed name will be reset each time the player leaves the map or reloads the game
- Passing an empty string ("") to the `name` argument or omitting it will allow the game to get the name for the object from pro_*.msg files
- The function can override the name only once for the same object until reset
- __NOTE:__ this function is intended for use in normal game scripts
**** ****
_See other documentation files (arrays.md, hookscripts.md) for related functions reference._ _See other documentation files (arrays.md, hookscripts.md) for related functions reference._
+2
View File
@@ -330,6 +330,7 @@ FUNC(item_move_all_, 0x4776AC)
FUNC(item_move_all_hidden_, 0x4776E0) FUNC(item_move_all_hidden_, 0x4776E0)
FUNC(item_move_force_, 0x4776A4) FUNC(item_move_force_, 0x4776A4)
FUNC(item_mp_cost_, 0x478040) FUNC(item_mp_cost_, 0x478040)
FUNC(item_name_, 0x477AE4)
FUNC(item_remove_mult_, 0x477490) FUNC(item_remove_mult_, 0x477490)
FUNC(item_size_, 0x477B68) FUNC(item_size_, 0x477B68)
FUNC(item_total_cost_, 0x477DAC) FUNC(item_total_cost_, 0x477DAC)
@@ -487,6 +488,7 @@ FUNC(protinst_use_item_, 0x49BF38)
FUNC(protinst_use_item_on_, 0x49C3CC) FUNC(protinst_use_item_on_, 0x49C3CC)
FUNC(proto_dude_init_, 0x49FA64) FUNC(proto_dude_init_, 0x49FA64)
FUNC(proto_dude_update_gender_, 0x49F984) FUNC(proto_dude_update_gender_, 0x49F984)
FUNC(proto_get_msg_info_, 0x49EAA4)
FUNC(proto_list_str_, 0x49E758) FUNC(proto_list_str_, 0x49E758)
FUNC(proto_make_path_, 0x49E270) FUNC(proto_make_path_, 0x49E270)
FUNC(proto_ptr_, 0x4A2108) // eax - PID, edx - int** - pointer to a pointer to a proto struct FUNC(proto_ptr_, 0x4A2108) // eax - PID, edx - int** - pointer to a pointer to a proto struct
+1
View File
@@ -176,6 +176,7 @@ WRAP_WATCOM_FUNC2(long, perk_can_add, TGameObj*, critter, long, perkId)
WRAP_WATCOM_FUNC2(long, perk_level, TGameObj*, critter, long, perkId) WRAP_WATCOM_FUNC2(long, perk_level, TGameObj*, critter, long, perkId)
WRAP_WATCOM_FUNC6(long, pick_death, TGameObj*, attacker, TGameObj*, target, TGameObj*, weapon, long, amount, long, anim, long, hitFromBack) WRAP_WATCOM_FUNC6(long, pick_death, TGameObj*, attacker, TGameObj*, target, TGameObj*, weapon, long, amount, long, anim, long, hitFromBack)
WRAP_WATCOM_FUNC0(void, process_bk) WRAP_WATCOM_FUNC0(void, process_bk)
WRAP_WATCOM_FUNC2(const char*, proto_get_msg_info, long, pid, long, msgType) // msgType: 0 - name, 1 - desc
WRAP_WATCOM_FUNC0(void, proto_dude_update_gender) WRAP_WATCOM_FUNC0(void, proto_dude_update_gender)
WRAP_WATCOM_FUNC2(void, proto_make_path, char*, buffer, long, pid) WRAP_WATCOM_FUNC2(void, proto_make_path, char*, buffer, long, pid)
// Places pointer to a prototype structure into ptrPtr and returns 0 on success or -1 on failure // Places pointer to a prototype structure into ptrPtr and returns 0 on success or -1 on failure
+10 -1
View File
@@ -393,6 +393,10 @@ static void __stdcall GameClose() { // OnBeforeGameClose
WipeSounds(); WipeSounds();
} }
static void __stdcall MapLoadHook() { // OnBeforeMapLoad
ObjectNameReset();
}
static void __declspec(naked) main_init_system_hook() { static void __declspec(naked) main_init_system_hook() {
__asm { __asm {
pushadc; pushadc;
@@ -470,8 +474,13 @@ static void __declspec(naked) map_load_hook() {
mov ecx, 4; mov ecx, 4;
rep movsd; // copy the name of the loaded map to gameMapLoadingName rep movsd; // copy the name of the loaded map to gameMapLoadingName
mov onLoadingMap, 1; mov onLoadingMap, 1;
push eax;
push edx;
call MapLoadHook;
pop edx;
pop eax;
call map_load_file_; call map_load_file_;
mov onLoadingMap, cl; // unset mov onLoadingMap, 0;
retn; retn;
} }
} }
+2 -2
View File
@@ -170,7 +170,7 @@ void ReadExtraGameMsgFiles() {
path += ".msg"; path += ".msg";
MSGList* list = new MSGList(); MSGList* list = new MSGList();
if (fo_message_load(list, path.c_str()) == 1) { if (fo_message_load(list, path.c_str()) == 1) {
gExtraGameMsgLists.insert(std::make_pair(0x2000 + number, list)); gExtraGameMsgLists.insert(std::pair<const int, MSGList*>(0x2000 + number, list));
} else { } else {
delete list; delete list;
} }
@@ -198,7 +198,7 @@ long __stdcall Message_AddExtraMsgFile(const char* msgName, long msgNumber) {
//} //}
} }
if (msgNumber == 0) msgNumber = msgNumCounter++; if (msgNumber == 0) msgNumber = msgNumCounter++;
gExtraGameMsgLists.insert(std::make_pair(msgNumber, list)); gExtraGameMsgLists.insert(std::pair<const int, MSGList*>(msgNumber, list));
return msgNumber; return msgNumber;
} }
+7 -3
View File
@@ -27,6 +27,10 @@ static int maxCountLoadProto = 512;
long Objects_uniqueID = UID_START; // current counter id, saving to sfallgv.sav long Objects_uniqueID = UID_START; // current counter id, saving to sfallgv.sav
bool Objects_IsUniqueID(long id) {
return (id > UID_START || (id >= PLAYER_ID && id < 83536)); // 65535 maximum possible number of prototypes
}
static void SetScriptObjectID(TGameObj* obj) { static void SetScriptObjectID(TGameObj* obj) {
TScript* script; TScript* script;
if (fo_scr_ptr(obj->scriptId, &script) != -1) { if (fo_scr_ptr(obj->scriptId, &script) != -1) {
@@ -39,7 +43,7 @@ static void SetScriptObjectID(TGameObj* obj) {
// player ID = 18000, all party members have ID = 18000 + its pid (file number of prototype) // player ID = 18000, all party members have ID = 18000 + its pid (file number of prototype)
long __fastcall Objects_SetObjectUniqueID(TGameObj* obj) { long __fastcall Objects_SetObjectUniqueID(TGameObj* obj) {
long id = obj->id; long id = obj->id;
if (id > UID_START || (id >= PLAYER_ID && id < 83536)) return id; // 65535 maximum possible number of prototypes if (Objects_IsUniqueID(id)) return id;
if ((DWORD)Objects_uniqueID >= (DWORD)UID_END) Objects_uniqueID = UID_START; if ((DWORD)Objects_uniqueID >= (DWORD)UID_END) Objects_uniqueID = UID_START;
obj->id = ++Objects_uniqueID; obj->id = ++Objects_uniqueID;
@@ -155,7 +159,7 @@ end:
} }
} }
void Objects_SetAutoUnjamLockTime(DWORD time) { void __stdcall Objects_SetAutoUnjamLockTime(DWORD time) {
if (!unjamTimeState) BlockCall(0x4A364A); // disable auto unjam at midnight if (!unjamTimeState) BlockCall(0x4A364A); // disable auto unjam at midnight
if (time > 0) { if (time > 0) {
@@ -196,7 +200,7 @@ end:
} }
} }
void Objects_LoadProtoAutoMaxLimit() { void __stdcall Objects_LoadProtoAutoMaxLimit() {
MakeCall(0x4A21B2, proto_ptr_hack); MakeCall(0x4A21B2, proto_ptr_hack);
} }
+4 -2
View File
@@ -10,9 +10,11 @@ extern long Objects_uniqueID;
void Objects_Init(); void Objects_Init();
void Objects_OnGameLoad(); void Objects_OnGameLoad();
bool Objects_IsUniqueID(long id);
long __fastcall Objects_SetObjectUniqueID(TGameObj* obj); long __fastcall Objects_SetObjectUniqueID(TGameObj* obj);
long __fastcall Objects_SetSpecialID(TGameObj* obj); long __fastcall Objects_SetSpecialID(TGameObj* obj);
void Objects_SetNewEngineID(TGameObj* obj); void Objects_SetNewEngineID(TGameObj* obj);
void Objects_SetAutoUnjamLockTime(DWORD time); void __stdcall Objects_SetAutoUnjamLockTime(DWORD time);
void Objects_LoadProtoAutoMaxLimit(); void __stdcall Objects_LoadProtoAutoMaxLimit();
+112
View File
@@ -603,6 +603,7 @@ static const SfallOpcodeMetadata opcodeMetaArray[] = {
{mf_set_object_data, "set_object_data", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT, DATATYPE_MASK_INT}}, {mf_set_object_data, "set_object_data", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT, DATATYPE_MASK_INT}},
{mf_set_outline, "set_outline", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}}, {mf_set_outline, "set_outline", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}},
{mf_set_quest_failure_value, "set_quest_failure_value", {DATATYPE_MASK_INT, DATATYPE_MASK_INT}}, {mf_set_quest_failure_value, "set_quest_failure_value", {DATATYPE_MASK_INT, DATATYPE_MASK_INT}},
{mf_set_scr_name, "set_scr_name", {DATATYPE_MASK_STR}},
{mf_set_terrain_name, "set_terrain_name", {DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_STR}}, {mf_set_terrain_name, "set_terrain_name", {DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_STR}},
{mf_set_town_title, "set_town_title", {DATATYPE_MASK_INT, DATATYPE_MASK_STR}}, {mf_set_town_title, "set_town_title", {DATATYPE_MASK_INT, DATATYPE_MASK_STR}},
{mf_set_unique_id, "set_unique_id", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}}, {mf_set_unique_id, "set_unique_id", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}},
@@ -1510,11 +1511,114 @@ void BuildSortedIndexList() {
//devlog_f("\nCount: %d\n", DL_MAIN, scriptsIndexList.size()); //devlog_f("\nCount: %d\n", DL_MAIN, scriptsIndexList.size());
} }
///////////////////////////////// OBJECT NAME //////////////////////////////////
static std::tr1::unordered_map<int, std::string> overrideScrName;
static long lastNamePid = -1;
static long lastNameSid = -1;
static long lastItemPid = -1;
void __stdcall ObjectName_SetName(long sid, const char* name) {
if (sid == lastNameSid) lastNameSid = -1;
if (!name) name = "";
overrideScrName.insert(std::pair<const int, std::string>(sid, name));
}
const char* __stdcall ObjectName_GetName(TGameObj* object) {
if (!overrideScrName.empty()) {
std::tr1::unordered_map<int, std::string>::iterator name = overrideScrName.find(object->scriptId);
if (name != overrideScrName.cend()) {
return (name->second.length() > 0)
? name->second.c_str()
: fo_proto_get_msg_info(object->protoId, 0);
}
}
return nullptr;
}
static void __declspec(naked) critter_name_hack() {
static DWORD critter_name_hack_ret = 0x42D125;
using namespace Fields;
__asm {
push ebx; // object
call ObjectName_GetName;
test eax, eax;
jnz override;
mov edi, [ebx + scriptIndex];
retn;
override:
add esp, 4;
jmp critter_name_hack_ret;
}
}
static void __declspec(naked) critter_name_hack_check() {
static DWORD critter_name_hack_ret = 0x42D12F;
using namespace Fields;
__asm {
mov ecx, [ebx + scriptId];
cmp ecx, -1;
je checkPid; // has no script, check only the PID
cmp ecx, lastNameSid;
jne default;
add esp, 4;
mov eax, ds:[FO_VAR_name_critter];
jmp critter_name_hack_ret;
checkPid:
mov ecx, [ebx + protoId];
cmp ecx, lastNamePid;
jne default;
add esp, 4;
mov eax, ds:[FO_VAR_name_critter];
jmp critter_name_hack_ret;
default:
mov ecx, [ebx + scriptIndex];
retn;
}
}
static void __declspec(naked) critter_name_hack_end() {
using namespace Fields;
__asm {
mov edx, [ebx + protoId];
mov lastNamePid, edx;
mov ecx, [ebx + scriptId];
mov lastNameSid, ecx;
retn;
}
}
static void __declspec(naked) object_name_hook() {
using namespace Fields;
__asm {
mov edx, [eax + protoId];
cmp edx, lastItemPid;
je getLast;
mov lastItemPid, edx;
jmp item_name_;
getLast:
mov eax, ds:[FO_VAR_name_item];
retn;
}
}
void ObjectNameReset() {
overrideScrName.clear();
lastNameSid = -1;
}
////////////////////////////////////////////////////////////////////////////////
void ScriptExtender_OnGameLoad() { void ScriptExtender_OnGameLoad() {
ClearGlobalScripts(); ClearGlobalScripts();
ClearGlobals(); ClearGlobals();
RegAnimCombatCheck(1); RegAnimCombatCheck(1);
ForceEncounterRestore(); // restore if the encounter did not happen ForceEncounterRestore(); // restore if the encounter did not happen
ObjectNameReset();
lastNamePid = -1;
lastItemPid = -1;
} }
void ScriptExtender_Init() { void ScriptExtender_Init() {
@@ -1892,4 +1996,12 @@ void ScriptExtender_Init() {
InitOpcodeMetaTable(); InitOpcodeMetaTable();
InitMetaruleTable(); InitMetaruleTable();
// Returns the redefined object name
MakeCall(0x42D0F2, critter_name_hack, 1);
// Tweak for quickly getting last object name
MakeCall(0x42D0C4, critter_name_hack_check, 1);
MakeCall(0x42D12A, critter_name_hack_end);
HookCall(0x48C901, object_name_hook);
} }
+4
View File
@@ -96,6 +96,10 @@ int __stdcall ScriptHasLoaded(TProgram* script);
// loads and initializes script file (for normal game scripts) // loads and initializes script file (for normal game scripts)
long __fastcall InitScript(long sid); long __fastcall InitScript(long sid);
const char* __stdcall ObjectName_GetName(TGameObj* object);
void __stdcall ObjectName_SetName(long sid, const char* name);
void ObjectNameReset();
// variables // variables
extern DWORD availableGlobalScriptTypes; extern DWORD availableGlobalScriptTypes;
extern bool alwaysFindScripts; extern bool alwaysFindScripts;
+1
View File
@@ -175,6 +175,7 @@ static const SfallMetarule metaruleArray[] = {
{"set_object_data", mf_set_object_data, 3, 3}, {"set_object_data", mf_set_object_data, 3, 3},
{"set_outline", mf_set_outline, 2, 2}, {"set_outline", mf_set_outline, 2, 2},
{"set_quest_failure_value", mf_set_quest_failure_value, 2, 2}, {"set_quest_failure_value", mf_set_quest_failure_value, 2, 2},
{"set_scr_name", mf_set_scr_name, 0, 1},
{"set_terrain_name", mf_set_terrain_name, 3, 3}, {"set_terrain_name", mf_set_terrain_name, 3, 3},
{"set_town_title", mf_set_town_title, 2, 2}, {"set_town_title", mf_set_town_title, 2, 2},
{"set_unique_id", mf_set_unique_id, 1, 2}, {"set_unique_id", mf_set_unique_id, 1, 2},
+7
View File
@@ -678,3 +678,10 @@ static void mf_get_ini_section() {
static void mf_set_quest_failure_value() { static void mf_set_quest_failure_value() {
QuestList_AddQuestFailureValue(opHandler.arg(0).rawValue(), opHandler.arg(1).rawValue()); QuestList_AddQuestFailureValue(opHandler.arg(0).rawValue(), opHandler.arg(1).rawValue());
} }
static void mf_set_scr_name() {
long sid = fo_scr_find_sid_from_program(opHandler.program());
if (sid == -1) return;
ObjectName_SetName(sid, opHandler.arg(0).strValue());
}
+1 -1
View File
@@ -141,7 +141,7 @@ static bool LoadFrm(Frm* frm) {
if (GetFileAttributes(buf) != INVALID_FILE_ATTRIBUTES) frm->bakedBackground = 1; // fills entire frame surface with a key-color if (GetFileAttributes(buf) != INVALID_FILE_ATTRIBUTES) frm->bakedBackground = 1; // fills entire frame surface with a key-color
} }
frm->textures = textures; frm->textures = textures;
texMap.insert(std::make_pair(frm->key, TextureData(textures, frm->showHighlights, frm->bakedBackground, frm->frames))); texMap.insert(std::pair<const __int64, TextureData>(frm->key, TextureData(textures, frm->showHighlights, frm->bakedBackground, frm->frames)));
var_setInt(FO_VAR_bk_disabled) = 0; var_setInt(FO_VAR_bk_disabled) = 0;
} else { } else {
// Use preloaded textures // Use preloaded textures