mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Rest hook and functions (#144)
* Added new HOOK_RESTTIMER (#89) * Added "set_rest_mode" and "set_rest_heal_time" script functions.
This commit is contained in:
@@ -50,6 +50,7 @@
|
||||
#define HOOK_COMBATTURN (27)
|
||||
#define HOOK_CARTRAVEL (28)
|
||||
#define HOOK_SETGLOBALVAR (29)
|
||||
#define HOOK_RESTTIMER (30)
|
||||
|
||||
//Valid arguments to list_begin
|
||||
#define LIST_CRITTERS (0)
|
||||
@@ -206,6 +207,11 @@
|
||||
#define BLOCKING_TYPE_AI (2)
|
||||
#define BLOCKING_TYPE_SIGHT (3) // not really useful (works not as you would expect), game uses this only when checking if you can talk to a person
|
||||
|
||||
//Rest mode flags
|
||||
#define DISABLE_REST (1)
|
||||
#define DISABLE_REST_FIX (2)
|
||||
#define DISABLE_REST_HEAL (4)
|
||||
|
||||
#define party_member_list_critters party_member_list(0)
|
||||
#define party_member_list_all party_member_list(1)
|
||||
|
||||
@@ -236,6 +242,8 @@
|
||||
#define set_ini_setting(setting, value) sfall_func2("set_ini_setting", setting, value)
|
||||
#define set_map_enter_position(tile, elev, rot) sfall_func3("set_map_enter_position", tile, elev, rot)
|
||||
#define set_outline(obj, color) sfall_func2("set_outline", obj, color)
|
||||
#define set_rest_heal_time(time) sfall_func1("set_rest_heal_time", time)
|
||||
#define set_rest_mode(mode) sfall_func1("set_rest_mode", mode)
|
||||
#define set_unjam_locks_time(time) sfall_func1("set_unjam_locks_time", time)
|
||||
#define spatial_radius(obj) sfall_func1("spatial_radius", obj)
|
||||
#define tile_refresh_display sfall_func0("tile_refresh_display")
|
||||
|
||||
@@ -465,6 +465,10 @@ Some utility/math functions are available:
|
||||
- setting the tile to 0 will put the player on the start hex (default tile and elevation) of the map
|
||||
- works only in map_enter_p_proc procedure
|
||||
|
||||
> void sfall_func1("set_rest_heal_time", int minutes)
|
||||
|
||||
> void sfall_func1("set_rest_mode", int mode)
|
||||
|
||||
------------------------
|
||||
------ MORE INFO -------
|
||||
------------------------
|
||||
|
||||
@@ -56,6 +56,7 @@ enum HookType
|
||||
HOOK_COMBATTURN = 27,
|
||||
HOOK_CARTRAVEL = 28,
|
||||
HOOK_SETGLOBALVAR = 29,
|
||||
HOOK_RESTTIMER = 30,
|
||||
HOOK_COUNT
|
||||
};
|
||||
|
||||
|
||||
@@ -289,6 +289,70 @@ static void __declspec(naked) SetGlobalVarHook() {
|
||||
}
|
||||
}
|
||||
|
||||
static int restTicks; // previous ticks
|
||||
static void _stdcall RestTimerHookScript() {
|
||||
int addrHook;
|
||||
__asm {
|
||||
mov addrHook, ebx;
|
||||
mov args[0], eax;
|
||||
mov args[8], ecx;
|
||||
mov args[12], edx;
|
||||
}
|
||||
|
||||
BeginHook();
|
||||
argCount = 4;
|
||||
addrHook -= 5;
|
||||
if (addrHook == 0x499CA1 || addrHook == 0x499B63) {
|
||||
args[0] = restTicks;
|
||||
args[1] = -1;
|
||||
} else {
|
||||
restTicks = args[0];
|
||||
args[1] = (addrHook == 0x499DF2 || (args[2] == 0 && addrHook == 0x499BE0)) ? 1 : 0;
|
||||
}
|
||||
RunHookScript(HOOK_RESTTIMER);
|
||||
EndHook();
|
||||
}
|
||||
|
||||
static void __declspec(naked) RestTimerLoopHook() {
|
||||
__asm {
|
||||
pushad;
|
||||
mov ebx, [esp + 32];
|
||||
mov ecx, [esp+36+0x40]; // hours_
|
||||
mov edx, [esp+36+0x44]; // minutes_
|
||||
call RestTimerHookScript;
|
||||
popad;
|
||||
cmp cRet, 1;
|
||||
jl skip;
|
||||
cmp rets[0], 1;
|
||||
jnz skip;
|
||||
mov edi, 1;
|
||||
skip:
|
||||
jmp fo::funcoffs::set_game_time_;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) RestTimerEscapeHook() {
|
||||
__asm {
|
||||
cmp eax, 0x1B;
|
||||
jnz skip;
|
||||
pushad;
|
||||
mov ebx, [esp+32];
|
||||
mov ecx, [esp+36+0x40]; // hours_
|
||||
mov edx, [esp+36+0x44]; // minutes_
|
||||
call RestTimerHookScript;
|
||||
popad;
|
||||
cmp cRet, 1;
|
||||
jl skip;
|
||||
cmp rets[0], 0;
|
||||
jnz skip;
|
||||
mov edi, 0; // cancel escape
|
||||
retn;
|
||||
skip:
|
||||
mov edi, 1;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
void InitMiscHookScripts() {
|
||||
LoadHookScript("hs_useobjon", HOOK_USEOBJON);
|
||||
HookCalls(UseObjOnHook, { 0x49C606, 0x473619 });
|
||||
@@ -335,6 +399,10 @@ void InitMiscHookScripts() {
|
||||
LoadHookScript("hs_setglobalvar", HOOK_SETGLOBALVAR);
|
||||
HookCall(0x455A6D, SetGlobalVarHook);
|
||||
|
||||
LoadHookScript("hs_resttimer", HOOK_RESTTIMER);
|
||||
HookCalls(RestTimerLoopHook, { 0x499B4B, 0x499BE0, 0x499D2C, 0x499DF2 });
|
||||
MakeCalls(RestTimerEscapeHook, { 0x499B63, 0x499CA1 });
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -104,6 +104,8 @@ static const SfallMetarule metarules[] = {
|
||||
{"set_ini_setting", sf_set_ini_setting, 2, 2, {ARG_STRING, ARG_INTSTR}},
|
||||
{"set_map_enter_position", sf_set_map_enter_position, 3, 3, {ARG_INT, ARG_INT, ARG_INT}},
|
||||
{"set_outline", sf_set_outline, 2, 2, {ARG_OBJECT, ARG_INT}},
|
||||
{"set_rest_heal_time", sf_set_rest_heal_time, 1, 1, {ARG_INT}},
|
||||
{"set_rest_mode", sf_set_rest_mode, 1, 1, {ARG_INT}},
|
||||
{"set_unjam_locks_time", sf_set_unjam_locks_time, 1, 1, {ARG_INT}},
|
||||
{"spatial_radius", sf_spatial_radius, 1, 1, {ARG_OBJECT}},
|
||||
{"tile_refresh_display", sf_tile_refresh_display, 0, 0},
|
||||
|
||||
@@ -255,5 +255,13 @@ void sf_get_map_enter_position(OpcodeContext& ctx) {
|
||||
ctx.setReturn(id, DataType::INT);
|
||||
}
|
||||
|
||||
void sf_set_rest_heal_time(OpcodeContext& ctx) {
|
||||
Worldmap::SetRestHealTime(ctx.arg(0).asInt());
|
||||
}
|
||||
|
||||
void sf_set_rest_mode(OpcodeContext& ctx) {
|
||||
Worldmap::SetRestMode(ctx.arg(0).asInt());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,5 +46,9 @@ void sf_set_map_enter_position(OpcodeContext&);
|
||||
|
||||
void sf_get_map_enter_position(OpcodeContext&);
|
||||
|
||||
void sf_set_rest_heal_time(OpcodeContext&);
|
||||
|
||||
void sf_set_rest_mode(OpcodeContext&);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,9 @@ static Delegate<> onWorldmapLoop;
|
||||
static DWORD ViewportX;
|
||||
static DWORD ViewportY;
|
||||
|
||||
static bool restMode;
|
||||
static bool restTime;
|
||||
|
||||
static __declspec(naked) void GetDateWrapper() {
|
||||
__asm {
|
||||
push ecx;
|
||||
@@ -420,6 +423,9 @@ void Worldmap::init() {
|
||||
|
||||
LoadGameHook::OnGameReset() += []() {
|
||||
SetCarInterfaceArt(0x1B1);
|
||||
if (restTime)
|
||||
SetRestHealTime(180);
|
||||
RestRestore();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -431,4 +437,44 @@ void Worldmap::SetCarInterfaceArt(DWORD artIndex) {
|
||||
SafeWrite32(0x4C2D9B, artIndex);
|
||||
}
|
||||
|
||||
static void SetRestHealTime(DWORD minutes) {
|
||||
if (minutes > 0) {
|
||||
SafeWrite32(0x499FDE, minutes);
|
||||
restTime = (minutes != 180);
|
||||
}
|
||||
}
|
||||
|
||||
static void SetRestMode(DWORD mode) {
|
||||
RestRestore(); // restore default
|
||||
|
||||
restMode = ((mode & 0x7) > 0);
|
||||
if (!restMode) return;
|
||||
|
||||
if (mode & 1) { // bit1 - disable rest
|
||||
SafeWrite8(0x49952C, 0x31); //test to xor
|
||||
SafeWrite8(0x497557, 0x31);
|
||||
return;
|
||||
}
|
||||
if (mode & 2) { // bit2 - fix rest
|
||||
SafeWrite8(0x42E587, 0xE9);
|
||||
SafeWrite32(0x42E588, 0x94);
|
||||
}
|
||||
if (mode & 4) { // bit3 - disable heal
|
||||
SafeWrite16(0x499FD4, 0x9090);
|
||||
SafeWrite16(0x499E93, 0x8FEB);
|
||||
}
|
||||
}
|
||||
|
||||
static void RestRestore() {
|
||||
if (!restMode) return;
|
||||
|
||||
restMode = false;
|
||||
SafeWrite8(0x49952C, 0x85);
|
||||
SafeWrite8(0x497557, 0x85);
|
||||
SafeWrite8(0x42E587, 0xC7);
|
||||
SafeWrite32(0x42E588, 0x10C2444);
|
||||
SafeWrite16(0x499FD4, 0xC201);
|
||||
SafeWrite16(0x499E93, 0x0574);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,6 +32,8 @@ public:
|
||||
static Delegate<>& OnWorldmapLoop();
|
||||
|
||||
static void SetCarInterfaceArt(DWORD artIndex);
|
||||
static void SetRestHealTime(DWORD minutes);
|
||||
static void SetRestMode(DWORD mode);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user