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:
mr.Stalin
2018-05-08 12:18:44 +08:00
committed by NovaRain
parent 371a299640
commit 9fa59a0d75
9 changed files with 143 additions and 0 deletions
+8
View File
@@ -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 -------
------------------------
+1
View File
@@ -56,6 +56,7 @@ enum HookType
HOOK_COMBATTURN = 27,
HOOK_CARTRAVEL = 28,
HOOK_SETGLOBALVAR = 29,
HOOK_RESTTIMER = 30,
HOOK_COUNT
};
+68
View File
@@ -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&);
}
}
+46
View File
@@ -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);
}
}
+2
View File
@@ -32,6 +32,8 @@ public:
static Delegate<>& OnWorldmapLoop();
static void SetCarInterfaceArt(DWORD artIndex);
static void SetRestHealTime(DWORD minutes);
static void SetRestMode(DWORD mode);
};
}