mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
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:
@@ -350,6 +350,7 @@
|
||||
#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_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_town_title(areaID, title) sfall_func2("set_town_title", areaID, title)
|
||||
#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_refresh_display sfall_func0("tile_refresh_display")
|
||||
#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 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)
|
||||
|
||||
@@ -963,6 +963,15 @@ sfall_funcX metarule functions
|
||||
- `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
|
||||
|
||||
----
|
||||
#### 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._
|
||||
|
||||
@@ -330,6 +330,7 @@ FUNC(item_move_all_, 0x4776AC)
|
||||
FUNC(item_move_all_hidden_, 0x4776E0)
|
||||
FUNC(item_move_force_, 0x4776A4)
|
||||
FUNC(item_mp_cost_, 0x478040)
|
||||
FUNC(item_name_, 0x477AE4)
|
||||
FUNC(item_remove_mult_, 0x477490)
|
||||
FUNC(item_size_, 0x477B68)
|
||||
FUNC(item_total_cost_, 0x477DAC)
|
||||
@@ -487,6 +488,7 @@ FUNC(protinst_use_item_, 0x49BF38)
|
||||
FUNC(protinst_use_item_on_, 0x49C3CC)
|
||||
FUNC(proto_dude_init_, 0x49FA64)
|
||||
FUNC(proto_dude_update_gender_, 0x49F984)
|
||||
FUNC(proto_get_msg_info_, 0x49EAA4)
|
||||
FUNC(proto_list_str_, 0x49E758)
|
||||
FUNC(proto_make_path_, 0x49E270)
|
||||
FUNC(proto_ptr_, 0x4A2108) // eax - PID, edx - int** - pointer to a pointer to a proto struct
|
||||
|
||||
@@ -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_FUNC6(long, pick_death, TGameObj*, attacker, TGameObj*, target, TGameObj*, weapon, long, amount, long, anim, long, hitFromBack)
|
||||
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_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
|
||||
|
||||
+10
-1
@@ -393,6 +393,10 @@ static void __stdcall GameClose() { // OnBeforeGameClose
|
||||
WipeSounds();
|
||||
}
|
||||
|
||||
static void __stdcall MapLoadHook() { // OnBeforeMapLoad
|
||||
ObjectNameReset();
|
||||
}
|
||||
|
||||
static void __declspec(naked) main_init_system_hook() {
|
||||
__asm {
|
||||
pushadc;
|
||||
@@ -470,8 +474,13 @@ static void __declspec(naked) map_load_hook() {
|
||||
mov ecx, 4;
|
||||
rep movsd; // copy the name of the loaded map to gameMapLoadingName
|
||||
mov onLoadingMap, 1;
|
||||
push eax;
|
||||
push edx;
|
||||
call MapLoadHook;
|
||||
pop edx;
|
||||
pop eax;
|
||||
call map_load_file_;
|
||||
mov onLoadingMap, cl; // unset
|
||||
mov onLoadingMap, 0;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -170,7 +170,7 @@ void ReadExtraGameMsgFiles() {
|
||||
path += ".msg";
|
||||
MSGList* list = new MSGList();
|
||||
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 {
|
||||
delete list;
|
||||
}
|
||||
@@ -198,7 +198,7 @@ long __stdcall Message_AddExtraMsgFile(const char* msgName, long msgNumber) {
|
||||
//}
|
||||
}
|
||||
if (msgNumber == 0) msgNumber = msgNumCounter++;
|
||||
gExtraGameMsgLists.insert(std::make_pair(msgNumber, list));
|
||||
gExtraGameMsgLists.insert(std::pair<const int, MSGList*>(msgNumber, list));
|
||||
return msgNumber;
|
||||
}
|
||||
|
||||
|
||||
+7
-3
@@ -27,6 +27,10 @@ static int maxCountLoadProto = 512;
|
||||
|
||||
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) {
|
||||
TScript* script;
|
||||
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)
|
||||
long __fastcall Objects_SetObjectUniqueID(TGameObj* obj) {
|
||||
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;
|
||||
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 (time > 0) {
|
||||
@@ -196,7 +200,7 @@ end:
|
||||
}
|
||||
}
|
||||
|
||||
void Objects_LoadProtoAutoMaxLimit() {
|
||||
void __stdcall Objects_LoadProtoAutoMaxLimit() {
|
||||
MakeCall(0x4A21B2, proto_ptr_hack);
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -10,9 +10,11 @@ extern long Objects_uniqueID;
|
||||
void Objects_Init();
|
||||
void Objects_OnGameLoad();
|
||||
|
||||
bool Objects_IsUniqueID(long id);
|
||||
|
||||
long __fastcall Objects_SetObjectUniqueID(TGameObj* obj);
|
||||
long __fastcall Objects_SetSpecialID(TGameObj* obj);
|
||||
void Objects_SetNewEngineID(TGameObj* obj);
|
||||
|
||||
void Objects_SetAutoUnjamLockTime(DWORD time);
|
||||
void Objects_LoadProtoAutoMaxLimit();
|
||||
void __stdcall Objects_SetAutoUnjamLockTime(DWORD time);
|
||||
void __stdcall Objects_LoadProtoAutoMaxLimit();
|
||||
|
||||
@@ -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_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_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_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}},
|
||||
@@ -1510,11 +1511,114 @@ void BuildSortedIndexList() {
|
||||
//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() {
|
||||
ClearGlobalScripts();
|
||||
ClearGlobals();
|
||||
RegAnimCombatCheck(1);
|
||||
ForceEncounterRestore(); // restore if the encounter did not happen
|
||||
|
||||
ObjectNameReset();
|
||||
lastNamePid = -1;
|
||||
lastItemPid = -1;
|
||||
}
|
||||
|
||||
void ScriptExtender_Init() {
|
||||
@@ -1892,4 +1996,12 @@ void ScriptExtender_Init() {
|
||||
|
||||
InitOpcodeMetaTable();
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -96,6 +96,10 @@ int __stdcall ScriptHasLoaded(TProgram* script);
|
||||
// loads and initializes script file (for normal game scripts)
|
||||
long __fastcall InitScript(long sid);
|
||||
|
||||
const char* __stdcall ObjectName_GetName(TGameObj* object);
|
||||
void __stdcall ObjectName_SetName(long sid, const char* name);
|
||||
void ObjectNameReset();
|
||||
|
||||
// variables
|
||||
extern DWORD availableGlobalScriptTypes;
|
||||
extern bool alwaysFindScripts;
|
||||
|
||||
@@ -175,6 +175,7 @@ static const SfallMetarule metaruleArray[] = {
|
||||
{"set_object_data", mf_set_object_data, 3, 3},
|
||||
{"set_outline", mf_set_outline, 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_town_title", mf_set_town_title, 2, 2},
|
||||
{"set_unique_id", mf_set_unique_id, 1, 2},
|
||||
|
||||
@@ -678,3 +678,10 @@ static void mf_get_ini_section() {
|
||||
static void mf_set_quest_failure_value() {
|
||||
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());
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
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;
|
||||
} else {
|
||||
// Use preloaded textures
|
||||
|
||||
Reference in New Issue
Block a user