mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Fixed NPC stuck in an animation loop in combat (#321)
* this happens when trying to move close to a multihex critter.
This commit is contained in:
+10
-4
@@ -9,10 +9,14 @@ namespace sfall
|
||||
|
||||
std::multimap<long, long> writeAddress;
|
||||
|
||||
static std::vector<long> excludeAddr = {
|
||||
static std::vector<long> excludeWarning = {
|
||||
0x44E949, 0x44E94A, 0x44E937, 0x4F5F40, 0x4CB850, // from movies.cpp
|
||||
};
|
||||
|
||||
static std::vector<long> excludeConflict = {
|
||||
0x42A0F8, // bugfixes.cpp
|
||||
};
|
||||
|
||||
struct HackPair {
|
||||
long addr;
|
||||
long len;
|
||||
@@ -135,8 +139,10 @@ void PrintAddrList() {
|
||||
if (diff == 0) {
|
||||
dlog_f("0x%x L:%d [Overwriting]\n", DL_MAIN, el.addr, el.len);
|
||||
} else if (diff < pl) {
|
||||
dlog_f("0x%x L:%d [Conflict] with 0x%x L:%d\n", DL_MAIN, el.addr, el.len, pa, pl);
|
||||
MessageBoxA(0, "Conflict detected!", "", MB_TASKMODAL);
|
||||
if (std::find(excludeConflict.cbegin(), excludeConflict.cend(), el.addr) == excludeConflict.cend()) {
|
||||
dlog_f("0x%x L:%d [Conflict] with 0x%x L:%d\n", DL_MAIN, el.addr, el.len, pa, pl);
|
||||
MessageBoxA(0, "Conflict detected!", "", MB_TASKMODAL);
|
||||
}
|
||||
} else if (level >= 11 && diff == pl) {
|
||||
dlog_f("0x%x L:%d [Warning] Hacking near:0x%x\n", DL_MAIN, el.addr, el.len, pa);
|
||||
} else if (level >= 12) {
|
||||
@@ -149,7 +155,7 @@ void PrintAddrList() {
|
||||
|
||||
void CheckConflict(DWORD addr, long len) {
|
||||
if (writeAddress.find(addr) != writeAddress.cend()) {
|
||||
if (std::find(excludeAddr.cbegin(), excludeAddr.cend(), addr) != excludeAddr.cend()) return;
|
||||
if (std::find(excludeWarning.cbegin(), excludeWarning.cend(), addr) != excludeWarning.cend()) return;
|
||||
char buf[64];
|
||||
sprintf_s(buf, "Memory overwriting at address 0x%x", addr);
|
||||
MessageBoxA(0, buf, "", MB_TASKMODAL);
|
||||
|
||||
+56
-44
@@ -1237,42 +1237,6 @@ end:
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) wmTeleportToArea_hack() {
|
||||
static const DWORD wmTeleportToArea_Ret = 0x4C5A77;
|
||||
__asm {
|
||||
xor ecx, ecx;
|
||||
cmp ebx, ds:[FO_VAR_WorldMapCurrArea];
|
||||
je end;
|
||||
mov ds:[FO_VAR_WorldMapCurrArea], ebx;
|
||||
sub eax, edx;
|
||||
add eax, ds:[FO_VAR_wmAreaInfoList];
|
||||
cmp dword ptr [eax + 0x34], 1; // wmAreaInfoList.size
|
||||
mov edx, [eax + 0x30]; // wmAreaInfoList.world_posy
|
||||
mov eax, [eax + 0x2C]; // wmAreaInfoList.world_posx
|
||||
jg largeLoc;
|
||||
je mediumLoc;
|
||||
//smallLoc:
|
||||
sub eax, 5;
|
||||
lea edx, [edx - 5];
|
||||
mediumLoc:
|
||||
sub eax, 10
|
||||
lea edx, [edx - 10];
|
||||
// check negative values
|
||||
test eax, eax;
|
||||
cmovl eax, ecx;
|
||||
test edx, edx;
|
||||
cmovl edx, ecx;
|
||||
largeLoc:
|
||||
mov ds:[FO_VAR_world_ypos], edx;
|
||||
mov ds:[FO_VAR_world_xpos], eax;
|
||||
end:
|
||||
mov ds:[FO_VAR_target_xpos], ecx;
|
||||
mov ds:[FO_VAR_target_ypos], ecx;
|
||||
mov ds:[FO_VAR_In_WorldMap], ecx;
|
||||
jmp wmTeleportToArea_Ret;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) db_get_file_list_hack() {
|
||||
__asm {
|
||||
push edi
|
||||
@@ -2337,6 +2301,42 @@ static void __declspec(naked) action_climb_ladder_hack() {
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) wmTeleportToArea_hack() {
|
||||
static const DWORD wmTeleportToArea_Ret = 0x4C5A77;
|
||||
__asm {
|
||||
xor ecx, ecx;
|
||||
cmp ebx, ds:[FO_VAR_WorldMapCurrArea];
|
||||
je end;
|
||||
mov ds:[FO_VAR_WorldMapCurrArea], ebx;
|
||||
sub eax, edx;
|
||||
add eax, ds:[FO_VAR_wmAreaInfoList];
|
||||
cmp dword ptr [eax + 0x34], 1; // wmAreaInfoList.size
|
||||
mov edx, [eax + 0x30]; // wmAreaInfoList.world_posy
|
||||
mov eax, [eax + 0x2C]; // wmAreaInfoList.world_posx
|
||||
jg largeLoc;
|
||||
je mediumLoc;
|
||||
//smallLoc:
|
||||
sub eax, 5;
|
||||
lea edx, [edx - 5];
|
||||
mediumLoc:
|
||||
sub eax, 10
|
||||
lea edx, [edx - 10];
|
||||
// check negative values
|
||||
test eax, eax;
|
||||
cmovl eax, ecx;
|
||||
test edx, edx;
|
||||
cmovl edx, ecx;
|
||||
largeLoc:
|
||||
mov ds:[FO_VAR_world_ypos], edx;
|
||||
mov ds:[FO_VAR_world_xpos], eax;
|
||||
end:
|
||||
mov ds:[FO_VAR_target_xpos], ecx;
|
||||
mov ds:[FO_VAR_target_ypos], ecx;
|
||||
mov ds:[FO_VAR_In_WorldMap], ecx;
|
||||
jmp wmTeleportToArea_Ret;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) wmAreaMarkVisitedState_hack() {
|
||||
static const DWORD wmAreaMarkVisitedState_Ret = 0x4C46A2;
|
||||
//static const DWORD wmAreaMarkVisitedState_Error = 0x4C4698;
|
||||
@@ -3010,13 +3010,6 @@ void BugFixes::init()
|
||||
// Fix for checking the horizontal position on the y-axis instead of x when setting coordinates on the world map
|
||||
SafeWrite8(0x4C4743, 0xC6); // cmp esi, eax
|
||||
|
||||
// Partial fix for incorrect positioning after exiting small/medium locations (e.g. Ghost Farm)
|
||||
//if (GetConfigInt("Misc", "SmallLocExitFix", 1)) {
|
||||
dlog("Applying fix for incorrect positioning after exiting small/medium locations.", DL_INIT);
|
||||
MakeJump(0x4C5A41, wmTeleportToArea_hack);
|
||||
dlogr(" Done", DL_INIT);
|
||||
//}
|
||||
|
||||
//if (GetConfigInt("Misc", "PrintToFileFix", 1)) {
|
||||
dlog("Applying print to file fix.", DL_INIT);
|
||||
MakeCall(0x4C67D4, db_get_file_list_hack);
|
||||
@@ -3332,6 +3325,13 @@ void BugFixes::init()
|
||||
MakeCall(0x411FD6, action_use_an_item_on_object_hack);
|
||||
MakeCall(0x411DF7, action_climb_ladder_hack); // bug caused by anim_move_to_tile_ fix
|
||||
|
||||
// Partial fix for incorrect positioning after exiting small/medium locations (e.g. Ghost Farm)
|
||||
//if (GetConfigInt("Misc", "SmallLocExitFix", 1)) {
|
||||
dlog("Applying fix for incorrect positioning after exiting small/medium locations.", DL_INIT);
|
||||
MakeJump(0x4C5A41, wmTeleportToArea_hack);
|
||||
dlogr(" Done", DL_INIT);
|
||||
//}
|
||||
|
||||
// Fix for Scout perk being taken into account when setting the visibility of locations with mark_area_known function
|
||||
// also fix the incorrect coordinates for small/medium location circles that the engine uses to highlight their sub-tiles
|
||||
// and fix visited tiles on the world map being darkened again when a location is added next to them
|
||||
@@ -3417,7 +3417,19 @@ void BugFixes::init()
|
||||
0x74, 0x1A, // jz 0x426D83
|
||||
0x90
|
||||
};
|
||||
SafeWriteBytes(0x426D5C, codeData, 14);
|
||||
SafeWriteBytes(0x426D5C, codeData, 14); // combat_is_shot_blocked_
|
||||
|
||||
// Fix for NPC stuck in an animation loop in combat when trying to move close to a multihex critter
|
||||
// this prevents moving to the multihex critter when the critters are close together
|
||||
BYTE codeData1[] = {
|
||||
0x89, 0xF0, // mov eax, esi
|
||||
0x89, 0xFA, // mov edx, edi
|
||||
0xE8, 0x00, 0x00, 0x0, 0x0, // call obj_dist_
|
||||
0x83, 0xF8, 0x01, // cmp eax, 1
|
||||
0x0F, 0x8E, 0xAB, 0x0, 0x0, 0x0, // jle 0x42A1B1 (exit)
|
||||
};
|
||||
SafeWriteBytes(0x42A0F4, codeData1, 18); // ai_move_steps_closer_
|
||||
HookCall(0x42A0F8, (void*)fo::funcoffs::obj_dist_);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ static void __declspec(naked) intface_item_reload_hook() {
|
||||
mov eax, dword ptr ds:[FO_VAR_obj_dude];
|
||||
call fo::funcoffs::register_clear_;
|
||||
xor edx, edx; // ANIM_stand
|
||||
xor ebx, ebx; // no delay
|
||||
xor ebx, ebx; // delay (unused)
|
||||
lea eax, [edx + 1]; // RB_UNRESERVED
|
||||
call fo::funcoffs::register_begin_;
|
||||
mov eax, dword ptr ds:[FO_VAR_obj_dude];
|
||||
|
||||
Reference in New Issue
Block a user