Added "get_terrain_name" script function

Updated documents for the function.
Minor edits to other code.
This commit is contained in:
NovaRain
2022-06-14 21:04:51 +08:00
parent 7015db2414
commit 85e5da660b
15 changed files with 192 additions and 135 deletions
+5
View File
@@ -497,6 +497,11 @@
- name: set_terrain_name - name: set_terrain_name
detail: void sfall_func3("set_terrain_name", int x, int y, string name) detail: void sfall_func3("set_terrain_name", int x, int y, string name)
doc: Overrides the terrain type name for the sub-tile on the world map by the specified coordinates. doc: Overrides the terrain type name for the sub-tile on the world map by the specified coordinates.
macro: sfall.h
- name: get_terrain_name
detail: string sfall_func2("get_terrain_name", int x, int y)
doc: Returns the terrain type name for the sub-tile on the world map by the specified coordinates, or by the player's current position if called without arguments.
macro: sfall.h
- name: set_town_title - name: set_town_title
detail: void sfall_func2("set_town_title", int areaID, string title) detail: void sfall_func2("set_town_title", int areaID, string title)
doc: | doc: |
+2
View File
@@ -319,6 +319,7 @@
#define floor2(value) sfall_func1("floor2", value) #define floor2(value) sfall_func1("floor2", value)
#define get_can_rest_on_map(map, elev) sfall_func2("get_can_rest_on_map", map, elev) #define get_can_rest_on_map(map, elev) sfall_func2("get_can_rest_on_map", map, elev)
#define get_current_inven_size(obj) sfall_func1("get_current_inven_size", obj) #define get_current_inven_size(obj) sfall_func1("get_current_inven_size", obj)
#define get_current_terrain_name sfall_func0("get_terrain_name")
#define get_cursor_mode sfall_func0("get_cursor_mode") #define get_cursor_mode sfall_func0("get_cursor_mode")
#define get_flags(obj) sfall_func1("get_flags", obj) #define get_flags(obj) sfall_func1("get_flags", obj)
#define get_ini_section(file, sect) sfall_func2("get_ini_section", file, sect) #define get_ini_section(file, sect) sfall_func2("get_ini_section", file, sect)
@@ -340,6 +341,7 @@
#define get_npc_stat_min(stat) sfall_func2("get_stat_min", stat, 1) #define get_npc_stat_min(stat) sfall_func2("get_stat_min", stat, 1)
#define get_sfall_arg_at(argNum) sfall_func1("get_sfall_arg_at", argNum) #define get_sfall_arg_at(argNum) sfall_func1("get_sfall_arg_at", argNum)
#define get_string_pointer(text) sfall_func1("get_string_pointer", text) #define get_string_pointer(text) sfall_func1("get_string_pointer", text)
#define get_terrain_name(x, y) sfall_func2("get_terrain_name", x, y)
#define get_text_width(text) sfall_func1("get_text_width", text) #define get_text_width(text) sfall_func1("get_text_width", text)
#define has_fake_perk_npc(npc, perk) sfall_func2("has_fake_perk_npc", npc, perk) #define has_fake_perk_npc(npc, perk) sfall_func2("has_fake_perk_npc", npc, perk)
#define has_fake_trait_npc(npc, trait) sfall_func2("has_fake_trait_npc", npc, trait) #define has_fake_trait_npc(npc, trait) sfall_func2("has_fake_trait_npc", npc, trait)
@@ -936,6 +936,12 @@ sfall_funcX metarule functions
`void sfall_func3("set_terrain_name", int x, int y, string name)` `void sfall_func3("set_terrain_name", int x, int y, string name)`
- Overrides the terrain type name for the sub-tile on the world map by the specified coordinates - Overrides the terrain type name for the sub-tile on the world map by the specified coordinates
----
#### get_terrain_name
`string sfall_func0("get_terrain_name")`\
`string sfall_func2("get_terrain_name", int x, int y)`
- Returns the terrain type name for the sub-tile on the world map by the specified coordinates, or by the player's current position if called without arguments
---- ----
#### get_window_attribute #### get_window_attribute
`int sfall_func1("get_window_attribute", int winType)`\ `int sfall_func1("get_window_attribute", int winType)`\
+13 -1
View File
@@ -407,7 +407,19 @@ fo::GameObject* __fastcall MultiHexMoveIsBlocking(fo::GameObject* source, long d
return nullptr; return nullptr;
} }
// Returns the type of the terrain sub tile at the the player's position on the world map // Returns the terrain type of the sub-tile at the specified coordinates on the world map
long wmGetTerrainType(long xPos, long yPos) {
long* terrainId;
__asm {
lea ebx, terrainId;
mov edx, yPos;
mov eax, xPos;
call fo::funcoffs::wmFindCurSubTileFromPos_;
}
return *terrainId;
}
// Returns the terrain type of the sub-tile at the the player's position on the world map
long wmGetCurrentTerrainType() { long wmGetCurrentTerrainType() {
long* terrainId = *(long**)FO_VAR_world_subtile; long* terrainId = *(long**)FO_VAR_world_subtile;
if (terrainId == nullptr) { if (terrainId == nullptr) {
+2
View File
@@ -137,6 +137,8 @@ fo::GameObject* CheckAroundBlockingTiles(fo::GameObject* source, long dstTile);
fo::GameObject* __fastcall MultiHexMoveIsBlocking(fo::GameObject* source, long dstTile); fo::GameObject* __fastcall MultiHexMoveIsBlocking(fo::GameObject* source, long dstTile);
long wmGetTerrainType(long xPos, long yPos);
long wmGetCurrentTerrainType(); long wmGetCurrentTerrainType();
void SurfaceCopyToMem(long fromX, long fromY, long width, long height, long fromWidth, BYTE* fromSurface, BYTE* toMem); void SurfaceCopyToMem(long fromX, long fromY, long width, long height, long fromWidth, BYTE* fromSurface, BYTE* toMem);
+121 -122
View File
@@ -1258,22 +1258,22 @@ inCombat:
static void __declspec(naked) action_explode_hack() { static void __declspec(naked) action_explode_hack() {
using namespace fo::Scripts; using namespace fo::Scripts;
__asm { __asm {
mov edx, destroy_p_proc mov edx, destroy_p_proc;
mov eax, [esi + scriptId] // pobj.sid mov eax, [esi + scriptId]; // pobj.sid
call fo::funcoffs::exec_script_proc_ call fo::funcoffs::exec_script_proc_;
xor edx, edx xor edx, edx;
dec edx dec edx;
retn retn;
} }
} }
static void __declspec(naked) action_explode_hack1() { static void __declspec(naked) action_explode_hack1() {
__asm { __asm {
push esi push esi;
mov esi, [esi+0x40] // ctd.target# mov esi, [esi + 0x40]; // ctd.target#
call action_explode_hack call action_explode_hack;
pop esi pop esi;
retn retn;
} }
} }
@@ -1342,140 +1342,140 @@ end:
static void __declspec(naked) db_get_file_list_hack() { static void __declspec(naked) db_get_file_list_hack() {
__asm { __asm {
push edi push edi;
push edx push edx;
xchg edi, eax // edi = *filename xchg edi, eax; // edi = *filename
mov eax, [eax+4] // file_lists.filenames mov eax, [eax + 4]; // file_lists.filenames
lea esi, [eax+edx] lea esi, [eax + edx];
cld cld;
push es push es;
push ds push ds;
pop es pop es;
xor ecx, ecx xor ecx, ecx;
dec ecx dec ecx;
mov edx, ecx mov edx, ecx;
mov ebx, ecx mov ebx, ecx;
xor eax, eax // searching for end of line xor eax, eax; // searching for end of line
repne scasb repne scasb;
not ecx not ecx;
dec ecx dec ecx;
xchg ebx, ecx // ebx = filename length xchg ebx, ecx; // ebx = filename length
lea edi, [esp+0x200+4*6] lea edi, [esp + 0x200 + 6*4];
repne scasb repne scasb;
not ecx not ecx;
xchg edx, ecx // edx = extension length +1 for "end of line" xchg edx, ecx; // edx = extension length +1 for "end of line"
mov edi, [esi] mov edi, [esi];
repne scasb repne scasb;
not ecx // ecx = buffer line length +1 for "end of line" not ecx; // ecx = buffer line length +1 for "end of line"
pop es pop es;
lea eax, [ebx+edx] // eax = new line length lea eax, [ebx + edx]; // eax = new line length
cmp eax, ecx // new line length <= buffer line length? cmp eax, ecx; // new line length <= buffer line length?
jbe end // Yes jbe end; // Yes
mov edx, [esi] mov edx, [esi];
xchg edx, eax xchg edx, eax;
call fo::funcoffs::nrealloc_ // eax = mem, edx = size call fo::funcoffs::nrealloc_; // eax = mem, edx = size
test eax, eax test eax, eax;
jnz skip jnz skip;
push 0x50B2F0 // "Error: Ran out of memory!" push 0x50B2F0; // "Error: Ran out of memory!"
call fo::funcoffs::debug_printf_ call fo::funcoffs::debug_printf_;
add esp, 4 add esp, 4;
jmp end jmp end;
skip: skip:
mov [esi], eax mov [esi], eax;
end: end:
xchg esi, eax xchg esi, eax;
pop edx pop edx;
pop edi pop edi;
retn retn;
} }
} }
static void __declspec(naked) gdActivateBarter_hook() { static void __declspec(naked) gdActivateBarter_hook() {
__asm { __asm {
call fo::funcoffs::gdialog_barter_pressed_ call fo::funcoffs::gdialog_barter_pressed_;
cmp ds:[FO_VAR_dialogue_state], ecx cmp ds:[FO_VAR_dialogue_state], ecx;
jne skip jne skip;
cmp ds:[FO_VAR_dialogue_switch_mode], esi cmp ds:[FO_VAR_dialogue_switch_mode], esi;
je end je end;
skip: skip:
push ecx push ecx;
push esi push esi;
push edi push edi;
push ebp push ebp;
sub esp, 0x18 sub esp, 0x18;
push 0x44A5CC push 0x44A5CC;
end: end:
retn retn;
} }
} }
static void __declspec(naked) switch_hand_hack() { static void __declspec(naked) switch_hand_hack() {
__asm { __asm {
mov eax, ds:[FO_VAR_inven_dude] mov eax, ds:[FO_VAR_inven_dude];
push eax push eax;
mov [edi], ebp mov [edi], ebp;
inc ecx // if ecx == -1 inc ecx; // if ecx == -1
jz skip jz skip;
xor ebx, ebx xor ebx, ebx;
inc ebx inc ebx;
mov edx, ebp mov edx, ebp;
call fo::funcoffs::item_remove_mult_ call fo::funcoffs::item_remove_mult_;
skip: skip:
pop edx // _inven_dude pop edx; // _inven_dude
mov eax, ebp mov eax, ebp;
call fo::funcoffs::item_get_type_ call fo::funcoffs::item_get_type_;
cmp eax, item_type_container cmp eax, item_type_container;
jne end jne end;
mov [ebp + owner], edx // iobj.owner = _inven_dude mov [ebp + owner], edx; // iobj.owner = _inven_dude
end: end:
pop ebp pop ebp;
pop edi pop edi;
pop esi pop esi;
retn retn;
} }
} }
static void __declspec(naked) inven_item_wearing() { static void __declspec(naked) inven_item_wearing() {
__asm { __asm {
mov esi, ds:[FO_VAR_inven_dude] mov esi, ds:[FO_VAR_inven_dude];
xchg ebx, eax // ebx = source xchg ebx, eax; // ebx = source
mov eax, [esi + artFid] mov eax, [esi + artFid];
and eax, 0xF000000 and eax, 0xF000000;
sar eax, 0x18 sar eax, 0x18;
test eax, eax // check if object FID type flag is set to item test eax, eax; // check if object FID type flag is set to item
jnz skip // No jnz skip; // No
mov eax, esi mov eax, esi;
call fo::funcoffs::item_get_type_ call fo::funcoffs::item_get_type_;
cmp eax, item_type_container // Bag/Backpack? cmp eax, item_type_container; // Bag/Backpack?
jne skip // No jne skip; // No
mov eax, esi mov eax, esi;
call fo::funcoffs::obj_top_environment_ call fo::funcoffs::obj_top_environment_;
test eax, eax // has an owner? test eax, eax; // has an owner?
jz skip // No jz skip; // No
mov ecx, [eax + artFid] mov ecx, [eax + artFid];
and ecx, 0xF000000 and ecx, 0xF000000;
sar ecx, 0x18 sar ecx, 0x18;
cmp ecx, OBJ_TYPE_CRITTER // check if object FID type flag is set to critter cmp ecx, OBJ_TYPE_CRITTER; // check if object FID type flag is set to critter
jne skip // No jne skip; // No
cmp eax, ebx // the owner of the bag == source? cmp eax, ebx; // the owner of the bag == source?
je end // Yes je end; // Yes
skip: skip:
xchg ebx, eax xchg ebx, eax;
cmp eax, esi cmp eax, esi;
end: end:
retn retn;
} }
} }
static void __declspec(naked) inven_action_cursor_hack() { static void __declspec(naked) inven_action_cursor_hack() {
__asm { __asm {
cmp dword ptr [esp+0x44+0x4], item_type_container cmp dword ptr [esp + 0x44 + 4], item_type_container;
jne end jne end;
cmp eax, ds:[FO_VAR_stack] cmp eax, ds:[FO_VAR_stack];
je end je end;
cmp eax, ds:[FO_VAR_target_stack] cmp eax, ds:[FO_VAR_target_stack];
end: end:
retn retn;
} }
} }
@@ -1574,7 +1574,7 @@ end:
static void __declspec(naked) apply_damage_hack() { static void __declspec(naked) apply_damage_hack() {
__asm { __asm {
xchg edx, eax; xchg edx, eax;
test [esi+0x15], dl; // ctd.flags2Source & DAM_HIT_? test [esi + 0x15], dl; // ctd.flags2Source & DAM_HIT_?
jz end; // No jz end; // No
inc ebx; inc ebx;
end: end:
@@ -1585,9 +1585,9 @@ end:
static void __declspec(naked) compute_attack_hook() { static void __declspec(naked) compute_attack_hook() {
__asm { __asm {
call fo::funcoffs::attack_crit_success_; call fo::funcoffs::attack_crit_success_;
test [esi+0x15], 2; // ctd.flags2Source & DAM_CRITICAL_? test [esi + 0x15], 2; // ctd.flags2Source & DAM_CRITICAL_?
jz end; // No jz end; // No
cmp dword ptr [esp+0x4+0x20], 4; // Has Silent Death perk? cmp dword ptr [esp + 0x20 + 4], 4; // Has Silent Death perk?
jne end; // No jne end; // No
shl eax, 1; // Multiply by 2 for the perk effect shl eax, 1; // Multiply by 2 for the perk effect
end: end:
@@ -1949,8 +1949,8 @@ fix:
} }
} }
static DWORD op_start_gdialog_ret = 0x456F4B;
static void __declspec(naked) op_start_gdialog_hack() { static void __declspec(naked) op_start_gdialog_hack() {
static const DWORD op_start_gdialog_ret = 0x456F4B;
__asm { __asm {
cmp eax, -1; // check mood arg cmp eax, -1; // check mood arg
jnz useMood; jnz useMood;
@@ -3179,8 +3179,7 @@ static void __declspec(naked) action_can_be_pushed_hook() {
} }
} }
void BugFixes::init() void BugFixes::init() {
{
#ifndef NDEBUG #ifndef NDEBUG
LoadGameHook::OnBeforeGameClose() += PrintAddrList; LoadGameHook::OnBeforeGameClose() += PrintAddrList;
if (IniReader::GetIntDefaultConfig("Debugging", "BugFixes", 1) == 0) return; if (IniReader::GetIntDefaultConfig("Debugging", "BugFixes", 1) == 0) return;
@@ -170,6 +170,5 @@ void mf_unwield_slot(OpcodeContext& ctx) {
if (update) fo::func::intface_update_items(0, -1, -1); if (update) fo::func::intface_update_items(0, -1, -1);
} }
} }
} }
@@ -98,6 +98,7 @@ static const SfallMetarule metarules[] = {
{"get_stat_max", mf_get_stat_max, 1, 2, 0, {ARG_INT, ARG_INT}}, {"get_stat_max", mf_get_stat_max, 1, 2, 0, {ARG_INT, ARG_INT}},
{"get_stat_min", mf_get_stat_min, 1, 2, 0, {ARG_INT, ARG_INT}}, {"get_stat_min", mf_get_stat_min, 1, 2, 0, {ARG_INT, ARG_INT}},
{"get_string_pointer", mf_get_string_pointer, 1, 1, 0, {ARG_STRING}}, {"get_string_pointer", mf_get_string_pointer, 1, 1, 0, {ARG_STRING}},
{"get_terrain_name", mf_get_terrain_name, 0, 2, -1, {ARG_INT, ARG_INT}},
{"get_text_width", mf_get_text_width, 1, 1, 0, {ARG_STRING}}, {"get_text_width", mf_get_text_width, 1, 1, 0, {ARG_STRING}},
{"get_window_attribute", mf_get_window_attribute, 1, 2, -1, {ARG_INT, ARG_INT}}, {"get_window_attribute", mf_get_window_attribute, 1, 2, -1, {ARG_INT, ARG_INT}},
{"has_fake_perk_npc", mf_has_fake_perk_npc, 2, 2, 0, {ARG_OBJECT, ARG_STRING}}, {"has_fake_perk_npc", mf_has_fake_perk_npc, 2, 2, 0, {ARG_OBJECT, ARG_STRING}},
+1 -1
View File
@@ -42,7 +42,7 @@ namespace sfall
namespace script namespace script
{ {
const char* stringTooLong = "%s() - the string exceeds maximum length of 64 characters."; static const char* stringTooLong = "%s() - the string exceeds maximum length of 64 characters.";
void __declspec(naked) op_stop_game() { void __declspec(naked) op_stop_game() {
__asm { __asm {
+1 -1
View File
@@ -112,7 +112,7 @@ void op_set_fake_trait(OpcodeContext& ctx) {
Perks::SetFakeTrait(ctx.arg(0).strValue(), ctx.arg(1).rawValue(), ctx.arg(2).rawValue(), ctx.arg(3).strValue()); Perks::SetFakeTrait(ctx.arg(0).strValue(), ctx.arg(1).rawValue(), ctx.arg(2).rawValue(), ctx.arg(3).strValue());
} }
const char* notPartyMemberErr = "%s() - the object is not a party member."; static const char* notPartyMemberErr = "%s() - the object is not a party member.";
void mf_set_selectable_perk_npc(OpcodeContext& ctx) { void mf_set_selectable_perk_npc(OpcodeContext& ctx) {
auto obj = ctx.arg(0).object(); auto obj = ctx.arg(0).object();
+2 -2
View File
@@ -34,8 +34,8 @@ namespace sfall
namespace script namespace script
{ {
const char* invalidStat = "%s() - stat number out of range."; static const char* invalidStat = "%s() - stat number out of range.";
const char* objNotCritter = "%s() - the object is not a critter."; static const char* objNotCritter = "%s() - the object is not a critter.";
void __declspec(naked) op_set_hp_per_level_mod() { void __declspec(naked) op_set_hp_per_level_mod() {
__asm { __asm {
+30 -1
View File
@@ -237,8 +237,37 @@ void mf_tile_by_position(OpcodeContext& ctx) {
ctx.setReturn(fo::func::tile_num(ctx.arg(0).rawValue(), ctx.arg(1).rawValue())); ctx.setReturn(fo::func::tile_num(ctx.arg(0).rawValue(), ctx.arg(1).rawValue()));
} }
static const char* invalidSubTilePos = "%s() - invalid x/y coordinates for the sub-tile.";
void mf_set_terrain_name(OpcodeContext& ctx) { void mf_set_terrain_name(OpcodeContext& ctx) {
Worldmap::SetTerrainTypeName(ctx.arg(0).rawValue(), ctx.arg(1).rawValue(), ctx.arg(2).strValue()); long x = ctx.arg(0).rawValue();
long y = ctx.arg(1).rawValue();
if (x < 0 || x >= (long)(7 * fo::var::wmNumHorizontalTiles) ||
y < 0 || y >= (long)(6 * (fo::var::wmMaxTileNum / fo::var::wmNumHorizontalTiles)))
{
ctx.printOpcodeError(invalidSubTilePos, ctx.getMetaruleName());
} else {
Worldmap::SetTerrainTypeName(x, y, ctx.arg(2).strValue());
}
}
void mf_get_terrain_name(OpcodeContext& ctx) {
if (ctx.numArgs() < 2) {
ctx.setReturn(Worldmap::GetCurrentTerrainName());
} else {
long x = ctx.arg(0).rawValue();
long y = ctx.arg(1).rawValue();
if (x < 0 || x >= (long)(7 * fo::var::wmNumHorizontalTiles) ||
y < 0 || y >= (long)(6 * (fo::var::wmMaxTileNum / fo::var::wmNumHorizontalTiles)))
{
ctx.printOpcodeError(invalidSubTilePos, ctx.getMetaruleName());
ctx.setReturn("Error");
} else {
ctx.setReturn(Worldmap::GetTerrainTypeName(x, y));
}
}
} }
void mf_set_town_title(OpcodeContext& ctx) { void mf_set_town_title(OpcodeContext& ctx) {
@@ -60,6 +60,8 @@ void mf_tile_by_position(OpcodeContext&);
void mf_set_terrain_name(OpcodeContext&); void mf_set_terrain_name(OpcodeContext&);
void mf_get_terrain_name(OpcodeContext&);
void mf_set_town_title(OpcodeContext&); void mf_set_town_title(OpcodeContext&);
} }
+5 -5
View File
@@ -672,13 +672,13 @@ void Worldmap::SetTerrainTypeName(long x, long y, const char* name) {
wmTerrainTypeNames.push_back(std::make_pair(subTileID, name)); wmTerrainTypeNames.push_back(std::make_pair(subTileID, name));
} }
// TODO: someone might need to know the name of a terrain type? // Returns the name of the terrain type at the specified coordinates on the world map
/*const char* Worldmap::GetTerrainTypeName(long x, long y) { const char* Worldmap::GetTerrainTypeName(long x, long y) {
const char* name = GetOverrideTerrainName(x, y); const char* name = GetOverrideTerrainName(x, y);
return (name) ? name : fo::util::GetMessageStr(&fo::var::wmMsgFile, 1000 + fo::wmGetTerrainType(x, y)); return (name) ? name : fo::util::GetMessageStr(&fo::var::wmMsgFile, 1000 + fo::util::wmGetTerrainType(x * 50, y * 50));
}*/ }
// Returns the name of the terrain type in the position of the player's marker on the world map // Returns the name of the terrain type at the position of the player's marker on the world map
const char* Worldmap::GetCurrentTerrainName() { const char* Worldmap::GetCurrentTerrainName() {
const char* name = GetOverrideTerrainName(fo::var::world_xpos / 50, fo::var::world_ypos / 50); const char* name = GetOverrideTerrainName(fo::var::world_xpos / 50, fo::var::world_ypos / 50);
return (name) ? name : fo::util::GetMessageStr(&fo::var::wmMsgFile, 1000 + fo::util::wmGetCurrentTerrainType()); return (name) ? name : fo::util::GetMessageStr(&fo::var::wmMsgFile, 1000 + fo::util::wmGetCurrentTerrainType());
+1 -1
View File
@@ -44,7 +44,7 @@ public:
static void SetAddedYears(DWORD years); static void SetAddedYears(DWORD years);
static void SetTerrainTypeName(long x, long y, const char* name); static void SetTerrainTypeName(long x, long y, const char* name);
//static const char* GetTerrainTypeName(long x, long y); static const char* GetTerrainTypeName(long x, long y);
static const char* GetCurrentTerrainName(); static const char* GetCurrentTerrainName();
static bool AreaTitlesIsEmpty(); static bool AreaTitlesIsEmpty();