mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Added "get/set_rest_on_map" script functions (from Mr.Stalin)
This commit is contained in:
@@ -230,6 +230,7 @@
|
|||||||
#define display_stats sfall_func0("display_stats")
|
#define display_stats sfall_func0("display_stats")
|
||||||
#define exec_map_update_scripts sfall_func0("exec_map_update_scripts")
|
#define exec_map_update_scripts sfall_func0("exec_map_update_scripts")
|
||||||
#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_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_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)
|
||||||
@@ -247,6 +248,7 @@
|
|||||||
#define lock_is_jammed(obj) sfall_func1("lock_is_jammed", obj)
|
#define lock_is_jammed(obj) sfall_func1("lock_is_jammed", obj)
|
||||||
#define outlined_object sfall_func0("outlined_object")
|
#define outlined_object sfall_func0("outlined_object")
|
||||||
#define real_dude_obj sfall_func0("real_dude_obj")
|
#define real_dude_obj sfall_func0("real_dude_obj")
|
||||||
|
#define set_can_rest_on_map(map, elev, value) sfall_func3("set_can_rest_on_map", map, elev, value)
|
||||||
#define set_car_intface_art(artIndex) sfall_func1("set_car_intface_art", artIndex)
|
#define set_car_intface_art(artIndex) sfall_func1("set_car_intface_art", artIndex)
|
||||||
#define set_cursor_mode(mode) sfall_func1("set_cursor_mode", mode)
|
#define set_cursor_mode(mode) sfall_func1("set_cursor_mode", mode)
|
||||||
#define set_dude_obj(critter) sfall_func1("set_dude_obj", critter)
|
#define set_dude_obj(critter) sfall_func1("set_dude_obj", critter)
|
||||||
|
|||||||
@@ -505,6 +505,17 @@ Some utility/math functions are available:
|
|||||||
- works just like vanilla CreateWin function, but creates a window with MoveOnTop flag if flags argument is not specified, and allows to set additional flags for the created window
|
- works just like vanilla CreateWin function, but creates a window with MoveOnTop flag if flags argument is not specified, and allows to set additional flags for the created window
|
||||||
- MoveOnTop flag allows the created window to be placed on top of the game interface
|
- MoveOnTop flag allows the created window to be placed on top of the game interface
|
||||||
|
|
||||||
|
> void sfall_func3("set_can_rest_on_map", int mapNum, int elev, bool value)
|
||||||
|
- allows/disallows to rest on the map for the specified level, overrides the can_rest_here values in maps.txt
|
||||||
|
- mapNum is the map index from maps.txt
|
||||||
|
- passing -1 to the elev argument will set the rest value for all map elevations
|
||||||
|
- the set rest value will be stored in sfalldb.sav file (in savegame)
|
||||||
|
|
||||||
|
> int sfall_func2("get_can_rest_on_map", int mapNum, int elev)
|
||||||
|
- returns the set rest value of the map after using the set_can_rest_on_map function
|
||||||
|
- returns -1 if the rest value of the map was not previously set (i.e. no data for the map in sfalldb.sav)
|
||||||
|
- the can_rest_here values in maps.txt are ignored
|
||||||
|
|
||||||
------------------------
|
------------------------
|
||||||
------ MORE INFO -------
|
------ MORE INFO -------
|
||||||
------------------------
|
------------------------
|
||||||
|
|||||||
@@ -109,6 +109,7 @@
|
|||||||
#define FO_VAR_main_window 0x5194F0
|
#define FO_VAR_main_window 0x5194F0
|
||||||
#define FO_VAR_map_elevation 0x519578
|
#define FO_VAR_map_elevation 0x519578
|
||||||
#define FO_VAR_map_global_vars 0x51956C
|
#define FO_VAR_map_global_vars 0x51956C
|
||||||
|
#define FO_VAR_map_number 0x631D88
|
||||||
#define FO_VAR_map_state 0x631D28
|
#define FO_VAR_map_state 0x631D28
|
||||||
#define FO_VAR_master_db_handle 0x58E948
|
#define FO_VAR_master_db_handle 0x58E948
|
||||||
#define FO_VAR_max 0x56FB50
|
#define FO_VAR_max 0x56FB50
|
||||||
|
|||||||
@@ -44,7 +44,4 @@ void _stdcall EndHook();
|
|||||||
|
|
||||||
#define HookBegin __asm pushad __asm call BeginHook __asm popad
|
#define HookBegin __asm pushad __asm call BeginHook __asm popad
|
||||||
|
|
||||||
#define hookbegin(a) __asm pushad __asm call BeginHook __asm popad __asm mov argCount, a
|
|
||||||
#define hookend __asm pushad __asm call EndHook __asm popad
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
#include "ScriptExtender.h"
|
#include "ScriptExtender.h"
|
||||||
#include "Scripting\Arrays.h"
|
#include "Scripting\Arrays.h"
|
||||||
#include "ExtraSaveSlots.h"
|
#include "ExtraSaveSlots.h"
|
||||||
|
#include "Worldmap.h"
|
||||||
|
|
||||||
#include "LoadGameHook.h"
|
#include "LoadGameHook.h"
|
||||||
|
|
||||||
@@ -131,6 +132,14 @@ static void _stdcall SaveGame2() {
|
|||||||
fo::DisplayPrint(saveSfallDataFailMsg);
|
fo::DisplayPrint(saveSfallDataFailMsg);
|
||||||
fo::func::gsound_play_sfx_file("IISXXXX1");
|
fo::func::gsound_play_sfx_file("IISXXXX1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GetSavePath(buf, "db");
|
||||||
|
h = CreateFileA(buf, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
|
||||||
|
if (h != INVALID_HANDLE_VALUE) {
|
||||||
|
Worldmap::SaveData(h);
|
||||||
|
}
|
||||||
|
CloseHandle(h);
|
||||||
|
|
||||||
GetSavePath(buf, "fs");
|
GetSavePath(buf, "fs");
|
||||||
h = CreateFileA(buf, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
|
h = CreateFileA(buf, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
|
||||||
if (h != INVALID_HANDLE_VALUE) {
|
if (h != INVALID_HANDLE_VALUE) {
|
||||||
@@ -207,6 +216,17 @@ static void _stdcall LoadGame_Before() {
|
|||||||
} else {
|
} else {
|
||||||
dlogr("Cannot read sfallgv.sav - assuming non-sfall save.", DL_MAIN);
|
dlogr("Cannot read sfallgv.sav - assuming non-sfall save.", DL_MAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GetSavePath(buf, "db");
|
||||||
|
h = CreateFileA(buf, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
|
||||||
|
if (h != INVALID_HANDLE_VALUE) {
|
||||||
|
dlog("Loading data from sfalldb.sav...", DL_INIT);
|
||||||
|
Worldmap::LoadData(h);
|
||||||
|
CloseHandle(h);
|
||||||
|
dlogr(" Done", DL_INIT);
|
||||||
|
} else {
|
||||||
|
dlogr("Cannot read sfalldb.sav.", DL_INIT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// called whenever game is being reset (prior to loading a save or when returning to main menu)
|
// called whenever game is being reset (prior to loading a save or when returning to main menu)
|
||||||
@@ -278,9 +298,9 @@ static void __stdcall NewGame_After() {
|
|||||||
static void __declspec(naked) main_load_new_hook() {
|
static void __declspec(naked) main_load_new_hook() {
|
||||||
__asm {
|
__asm {
|
||||||
pushad;
|
pushad;
|
||||||
push eax;
|
mov esi, eax; // keep
|
||||||
call NewGame_Before;
|
call NewGame_Before;
|
||||||
pop eax;
|
mov eax, esi; // restore
|
||||||
call fo::funcoffs::main_load_new_;
|
call fo::funcoffs::main_load_new_;
|
||||||
call NewGame_After;
|
call NewGame_After;
|
||||||
popad;
|
popad;
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ static const SfallMetarule metarules[] = {
|
|||||||
{"display_stats", sf_display_stats, 0, 0},
|
{"display_stats", sf_display_stats, 0, 0},
|
||||||
{"exec_map_update_scripts", sf_exec_map_update_scripts, 0, 0},
|
{"exec_map_update_scripts", sf_exec_map_update_scripts, 0, 0},
|
||||||
{"floor2", sf_floor2, 1, 1, {ARG_NUMBER}},
|
{"floor2", sf_floor2, 1, 1, {ARG_NUMBER}},
|
||||||
|
{"get_can_rest_on_map", sf_get_rest_on_map, 2, 2, {ARG_INT, ARG_INT}},
|
||||||
{"get_current_inven_size", sf_get_current_inven_size, 1, 1, {ARG_OBJECT}},
|
{"get_current_inven_size", sf_get_current_inven_size, 1, 1, {ARG_OBJECT}},
|
||||||
{"get_cursor_mode", sf_get_cursor_mode, 0, 0},
|
{"get_cursor_mode", sf_get_cursor_mode, 0, 0},
|
||||||
{"get_flags", sf_get_flags, 1, 1, {ARG_OBJECT}},
|
{"get_flags", sf_get_flags, 1, 1, {ARG_OBJECT}},
|
||||||
@@ -103,6 +104,7 @@ static const SfallMetarule metarules[] = {
|
|||||||
{"lock_is_jammed", sf_lock_is_jammed, 1, 1, {ARG_OBJECT}},
|
{"lock_is_jammed", sf_lock_is_jammed, 1, 1, {ARG_OBJECT}},
|
||||||
{"outlined_object", sf_outlined_object, 0, 0},
|
{"outlined_object", sf_outlined_object, 0, 0},
|
||||||
{"real_dude_obj", sf_real_dude_obj, 0, 0},
|
{"real_dude_obj", sf_real_dude_obj, 0, 0},
|
||||||
|
{"set_can_rest_on_map", sf_set_rest_on_map, 3, 3, {ARG_INT, ARG_INT, ARG_INT}},
|
||||||
{"set_car_intface_art", sf_set_car_intface_art, 1, 1, {ARG_INT}},
|
{"set_car_intface_art", sf_set_car_intface_art, 1, 1, {ARG_INT}},
|
||||||
{"set_cursor_mode", sf_set_cursor_mode, 1, 1, {ARG_INT}},
|
{"set_cursor_mode", sf_set_cursor_mode, 1, 1, {ARG_INT}},
|
||||||
{"set_dude_obj", sf_set_dude_obj, 1, 1, {ARG_OBJECT}},
|
{"set_dude_obj", sf_set_dude_obj, 1, 1, {ARG_OBJECT}},
|
||||||
|
|||||||
@@ -263,5 +263,28 @@ void sf_set_rest_mode(OpcodeContext& ctx) {
|
|||||||
Worldmap::SetRestMode(ctx.arg(0).asInt());
|
Worldmap::SetRestMode(ctx.arg(0).asInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sf_set_rest_on_map(OpcodeContext& ctx) {
|
||||||
|
long mapId = ctx.arg(0).asInt();
|
||||||
|
if (mapId < 0) {
|
||||||
|
ctx.printOpcodeError("set_rest_on_map() - invalid map number argument.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
long elev = ctx.arg(1).asInt();
|
||||||
|
if (elev < -1 && elev > 2) {
|
||||||
|
ctx.printOpcodeError("set_rest_on_map() - invalid map elevation argument.");
|
||||||
|
} else {
|
||||||
|
Worldmap::SetRestMapLevel(mapId, elev, ctx.arg(2).asBool());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sf_get_rest_on_map(OpcodeContext& ctx) {
|
||||||
|
long elev = ctx.arg(1).asInt();
|
||||||
|
if (elev < 0 && elev > 2) {
|
||||||
|
ctx.printOpcodeError("get_rest_on_map() - invalid map elevation argument.");
|
||||||
|
} else {
|
||||||
|
ctx.setReturn(Worldmap::GetRestMapLevel(elev, ctx.arg(0).asInt()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,5 +50,9 @@ void sf_set_rest_heal_time(OpcodeContext&);
|
|||||||
|
|
||||||
void sf_set_rest_mode(OpcodeContext&);
|
void sf_set_rest_mode(OpcodeContext&);
|
||||||
|
|
||||||
|
void sf_set_rest_on_map(OpcodeContext&);
|
||||||
|
|
||||||
|
void sf_get_rest_on_map(OpcodeContext&);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <map>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "..\main.h"
|
#include "..\main.h"
|
||||||
@@ -32,6 +33,12 @@ static Delegate<> onWorldmapLoop;
|
|||||||
static DWORD ViewportX;
|
static DWORD ViewportX;
|
||||||
static DWORD ViewportY;
|
static DWORD ViewportY;
|
||||||
|
|
||||||
|
struct levelRest {
|
||||||
|
char level[4];
|
||||||
|
};
|
||||||
|
std::map<int, levelRest> mapRestInfo;
|
||||||
|
|
||||||
|
static bool restMap;
|
||||||
static bool restMode;
|
static bool restMode;
|
||||||
static bool restTime;
|
static bool restTime;
|
||||||
|
|
||||||
@@ -209,6 +216,24 @@ static void __declspec(naked) wmInterfaceInit_text_font_hook() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __declspec(naked) critter_can_obj_dude_rest_hook() {
|
||||||
|
using namespace fo;
|
||||||
|
__asm {
|
||||||
|
push eax;
|
||||||
|
mov ecx, eax; // elevation
|
||||||
|
mov edx, dword ptr ds:[FO_VAR_map_number];
|
||||||
|
call Worldmap::GetRestMapLevel;
|
||||||
|
xor edx, edx;
|
||||||
|
cmp eax, edx;
|
||||||
|
jge skip;
|
||||||
|
pop eax;
|
||||||
|
jmp fo::funcoffs::wmMapCanRestHere_;
|
||||||
|
skip:
|
||||||
|
add esp, 4;
|
||||||
|
retn; // overrides
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void RestRestore() {
|
static void RestRestore() {
|
||||||
if (!restMode) return;
|
if (!restMode) return;
|
||||||
|
|
||||||
@@ -413,6 +438,31 @@ void WorldMapFontPatch() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Worldmap::SaveData(HANDLE file) {
|
||||||
|
DWORD sizeWrite, count = mapRestInfo.size();
|
||||||
|
WriteFile(file, &count, 4, &sizeWrite, 0);
|
||||||
|
std::map<int, levelRest>::iterator it;
|
||||||
|
for (it = mapRestInfo.begin(); it != mapRestInfo.end(); it++) {
|
||||||
|
WriteFile(file, &it->first, 4, &sizeWrite, 0);
|
||||||
|
WriteFile(file, &it->second, sizeof(levelRest), &sizeWrite, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Worldmap::LoadData(HANDLE file) {
|
||||||
|
DWORD count, sizeRead;
|
||||||
|
ReadFile(file, &count, 4, &sizeRead, 0);
|
||||||
|
if (sizeRead != 4) return;
|
||||||
|
if (!restMap) HookCall(0x42E57A, critter_can_obj_dude_rest_hook);
|
||||||
|
for (DWORD i = 0; i < count; i++) {
|
||||||
|
DWORD mID;
|
||||||
|
levelRest elevData;
|
||||||
|
ReadFile(file, &mID, 4, &sizeRead, 0);
|
||||||
|
ReadFile(file, &elevData, sizeof(levelRest), &sizeRead, 0);
|
||||||
|
mapRestInfo.insert(std::make_pair(mID, elevData));
|
||||||
|
}
|
||||||
|
restMap = true;
|
||||||
|
}
|
||||||
|
|
||||||
void Worldmap::init() {
|
void Worldmap::init() {
|
||||||
PathfinderFixInit();
|
PathfinderFixInit();
|
||||||
StartingStatePatches();
|
StartingStatePatches();
|
||||||
@@ -426,6 +476,7 @@ void Worldmap::init() {
|
|||||||
SetCarInterfaceArt(0x1B1);
|
SetCarInterfaceArt(0x1B1);
|
||||||
if (restTime) SetRestHealTime(180);
|
if (restTime) SetRestHealTime(180);
|
||||||
RestRestore();
|
RestRestore();
|
||||||
|
mapRestInfo.clear();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,4 +516,41 @@ void Worldmap::SetRestMode(DWORD mode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Worldmap::SetRestMapLevel(int mapId, long elev, bool canRest) {
|
||||||
|
auto keyIt = mapRestInfo.find(mapId);
|
||||||
|
if (keyIt != mapRestInfo.end()) {
|
||||||
|
if (elev == -1) {
|
||||||
|
keyIt->second.level[++elev] = canRest;
|
||||||
|
keyIt->second.level[++elev] = canRest;
|
||||||
|
elev++;
|
||||||
|
}
|
||||||
|
keyIt->second.level[elev] = canRest;
|
||||||
|
} else {
|
||||||
|
if (!restMap) {
|
||||||
|
HookCall(0x42E57A, critter_can_obj_dude_rest_hook);
|
||||||
|
restMap = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
levelRest elevData = {-1, -1, -1, -1};
|
||||||
|
std::pair<int, levelRest> info (mapId, elevData);
|
||||||
|
if (elev == -1) {
|
||||||
|
info.second.level[++elev] = canRest;
|
||||||
|
info.second.level[++elev] = canRest;
|
||||||
|
elev++;
|
||||||
|
}
|
||||||
|
info.second.level[elev] = canRest;
|
||||||
|
mapRestInfo.insert(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long __fastcall Worldmap::GetRestMapLevel(long elev, int mapId) {
|
||||||
|
if (mapRestInfo.empty()) return -1;
|
||||||
|
|
||||||
|
auto keyIt = mapRestInfo.find(mapId);
|
||||||
|
if (keyIt != mapRestInfo.end()) {
|
||||||
|
return keyIt->second.level[elev];
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,9 +31,14 @@ public:
|
|||||||
|
|
||||||
static Delegate<>& OnWorldmapLoop();
|
static Delegate<>& OnWorldmapLoop();
|
||||||
|
|
||||||
|
static void Worldmap::SaveData(HANDLE);
|
||||||
|
static void Worldmap::LoadData(HANDLE);
|
||||||
|
|
||||||
static void SetCarInterfaceArt(DWORD artIndex);
|
static void SetCarInterfaceArt(DWORD artIndex);
|
||||||
static void SetRestHealTime(DWORD minutes);
|
static void SetRestHealTime(DWORD minutes);
|
||||||
static void SetRestMode(DWORD mode);
|
static void SetRestMode(DWORD mode);
|
||||||
|
static void SetRestMapLevel(int mapId, long elev, bool canRest);
|
||||||
|
static long __fastcall GetRestMapLevel(long elev, int mapId);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user