mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Fixed the functions of the engine op_obj_can_see_obj_/op_obj_can_hear_obj_ (#189)
Added one additional argument for the hook HOOK_WITHINPERCEPTION.
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
Example engine algorithm.
|
||||
|
||||
* The AllowUnsafeScripting option must be enabled.
|
||||
*/
|
||||
|
||||
#include "define_lite.h"
|
||||
#include "command.h"
|
||||
|
||||
#include "sfall.h"
|
||||
#include "define_extra.h"
|
||||
|
||||
|
||||
#define can_see_(source, target) call_offset_r2(0x412BEC, source, target)
|
||||
#define obj_dist_(target, source) call_offset_r2(0x48BBD4, target, source)
|
||||
|
||||
procedure start;
|
||||
|
||||
procedure start begin
|
||||
if not(init_hook) then begin
|
||||
|
||||
variable source := get_sfall_arg,
|
||||
target := get_sfall_arg,
|
||||
original := get_sfall_arg,
|
||||
type := get_sfall_arg, /* new arg */
|
||||
result := 0,
|
||||
distance;
|
||||
|
||||
if target then begin
|
||||
distance := get_critter_stat(source, STAT_pe);
|
||||
|
||||
if can_see_(source, target) then begin
|
||||
distance *= 5;
|
||||
if (get_flags(target) bwand FLAG_TRANSGLASS) then distance /= 2;
|
||||
end
|
||||
else if combat_is_initialized then distance *= 2;
|
||||
|
||||
if target == dude_obj then begin
|
||||
if sneak_success then begin
|
||||
distance /= 4;
|
||||
if has_skill(target, SKILL_SNEAK) > 120 then distance -= 1;
|
||||
end
|
||||
else if dude_is_sneaking then distance := distance * 2 / 3;
|
||||
end
|
||||
|
||||
if obj_dist_(target, source) <= distance then result := 1;
|
||||
|
||||
// example
|
||||
if (result) then begin
|
||||
display_msg("hs_withinperception: " + obj_name(source) + " does he see > " + obj_name(target) + " [original: " + original + " script: " + result + "]");
|
||||
end else begin
|
||||
display_msg("hs_withinperception: " + obj_name(source) + " he does not see > " + obj_name(target) + " [original: " + original + " script: " + result + "]");
|
||||
end
|
||||
end
|
||||
|
||||
//set_sfall_return(result);
|
||||
end
|
||||
end
|
||||
@@ -401,6 +401,7 @@ This is fired after the default calculation is made.
|
||||
Critter arg1 - Watcher object
|
||||
Obj arg2 - Target object
|
||||
int arg3 - Result of vanilla function: 1 - within perception range, 0 - otherwise
|
||||
int arg4 - The type of the called hook: 1 - from the script function obj_can_see_obj, 2 - from the script function obj_can_hear_obj (need option CanHearObjFix enabled), 0 for all other cases
|
||||
|
||||
int ret1 - overrides the returned result of the function: 0 - not in range (can't see), 1 - in range (will see if not blocked), 2 - forced detection (will see regardless, only used in obj_can_see_obj scripting function which is called by every critter in the game)
|
||||
|
||||
|
||||
@@ -1292,6 +1292,30 @@ skip:
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) op_obj_can_see_obj_hack() {
|
||||
__asm {
|
||||
mov eax, [esp + 0x2C - 0x28 + 4]; // source
|
||||
mov ecx, [eax + tile]; // source.tile
|
||||
cmp ecx, -1;
|
||||
jz end;
|
||||
mov eax, [eax + elevation];
|
||||
mov edi, [edx + elevation]; // target.elev
|
||||
cmp eax, edi; // check source.elev == target.elev
|
||||
retn;
|
||||
end:
|
||||
dec ecx; // reset ZF
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) op_obj_can_hear_obj_hack() {
|
||||
__asm {
|
||||
mov eax, [esp + 0x28 - 0x28 + 4]; // target
|
||||
mov edx, [esp + 0x28 - 0x24 + 4]; // source
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BugFixes::init()
|
||||
{
|
||||
@@ -1648,6 +1672,20 @@ void BugFixes::init()
|
||||
HookCall(0x4C0AEB, wmRndEncounterOccurred_hook);
|
||||
dlogr(" Done", DL_INIT);
|
||||
}
|
||||
|
||||
// Fix op_obj_can_see_obj_
|
||||
MakeCall(0x456B63, op_obj_can_see_obj_hack);
|
||||
SafeWrite16(0x456B76, 0x23EB); // jz > jmp (skip unused engine code)
|
||||
|
||||
//Fix broken op_obj_can_hear_obj_ (enable a function)
|
||||
if (GetConfigInt("Misc", "CanHearObjFix", 0) != 0) {
|
||||
dlog("Applying obj_can_hear_obj opcode fix.", DL_INIT);
|
||||
SafeWrite8(0x4583D8, 0x3B); // change jz offset
|
||||
SafeWrite8(0x4583DE, 0x74); // jnz > jz
|
||||
MakeCall(0x4583E0, op_obj_can_hear_obj_hack);
|
||||
SafeWrite8(0x4583E5, 0x90);
|
||||
dlogr(" Done", DL_INIT);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -139,39 +139,62 @@ defaultHandler:
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) PerceptionRangeHook() {
|
||||
static void __stdcall PerceptionRangeHook_Script(int type) {
|
||||
__asm {
|
||||
HookBegin;
|
||||
mov args[0], eax; // watcher
|
||||
mov args[4], edx; // target
|
||||
call fo::funcoffs::is_within_perception_;
|
||||
mov args[8], eax; // check result
|
||||
pushad;
|
||||
push eax;
|
||||
}
|
||||
|
||||
argCount = 3;
|
||||
args[3] = type;
|
||||
|
||||
argCount = 4;
|
||||
RunHookScript(HOOK_WITHINPERCEPTION);
|
||||
EndHook();
|
||||
|
||||
__asm {
|
||||
popad;
|
||||
pop eax;
|
||||
cmp cRet, 1;
|
||||
cmovnb eax, rets[0];
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) PerceptionRangeHook() {
|
||||
__asm {
|
||||
push ecx;
|
||||
push 0;
|
||||
call PerceptionRangeHook_Script;
|
||||
pop ecx;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
static const DWORD PerceptionRangeBonusHack_back = 0x456BA7;
|
||||
static const DWORD PerceptionRangeBonusHack_skip = 0x456BDC;
|
||||
static void __declspec(naked) PerceptionRangeBonusHack() {
|
||||
static void __declspec(naked) PerceptionRangeSeeHook() {
|
||||
__asm {
|
||||
call PerceptionRangeHook;
|
||||
push ecx;
|
||||
push 1;
|
||||
call PerceptionRangeHook_Script;
|
||||
pop ecx;
|
||||
cmp eax, 2;
|
||||
jne nevermind; // return
|
||||
mov dword ptr[esp + 16], 1;
|
||||
jmp PerceptionRangeBonusHack_skip; // skip blocking check
|
||||
jne nevermind; // normal return
|
||||
dec eax;
|
||||
mov dword ptr[esp + 0x2C - 0x1C + 4], eax; // set 1, skip blocking check
|
||||
dec eax;
|
||||
nevermind:
|
||||
jmp PerceptionRangeBonusHack_back;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) PerceptionRangeHearHook() {
|
||||
__asm {
|
||||
push ecx;
|
||||
push 2;
|
||||
call PerceptionRangeHook_Script;
|
||||
pop ecx;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,9 +419,9 @@ void Inject_WithinPerceptionHook() {
|
||||
0x42BC87,
|
||||
0x42BC9F,
|
||||
0x42BD04,
|
||||
0x458403
|
||||
});
|
||||
MakeJump(0x456BA2, PerceptionRangeBonusHack);
|
||||
HookCall(0x456BA2, PerceptionRangeSeeHook);
|
||||
HookCall(0x458403, PerceptionRangeHearHook);
|
||||
}
|
||||
|
||||
void Inject_CarTravelHook() {
|
||||
|
||||
Reference in New Issue
Block a user