mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Added a fixed implementation of the tile_num_beyond_ function
Removed the code of multihex critter self-hit fix from BugFixes.cpp (now fixed properly with the aforementioned implementation)
This commit is contained in:
+6
-5
@@ -47,18 +47,19 @@ TGameObj* __stdcall AI_CheckShootAndFriendlyInLineOfFire(TGameObj* object, long
|
||||
}
|
||||
// continue checking the line of fire from object tile to targetTile
|
||||
TGameObj* obj = object; // for ignoring the object (multihex) when building the path
|
||||
fo_make_straight_path_func(object, objTile, targetTile, 0, (DWORD*)&obj, 32, (void*)obj_shoot_blocking_at_);
|
||||
if (!AI_CheckShootAndFriendlyInLineOfFire(obj, targetTile, team)) return nullptr;
|
||||
fo_make_straight_path_func(object, objTile, targetTile, 0, (DWORD*)&obj, 0x20, (void*)obj_shoot_blocking_at_);
|
||||
|
||||
object = AI_CheckShootAndFriendlyInLineOfFire(obj, targetTile, team);
|
||||
}
|
||||
return object;
|
||||
return object; // friendly critter, any object or null
|
||||
}
|
||||
|
||||
// Returns the friendly critter in the line of fire
|
||||
TGameObj* __stdcall AI_CheckFriendlyFire(TGameObj* target, TGameObj* attacker) {
|
||||
TGameObj* object = nullptr;
|
||||
fo_make_straight_path_func(attacker, attacker->tile, target->tile, 0, (DWORD*)&object, 32, (void*)obj_shoot_blocking_at_);
|
||||
fo_make_straight_path_func(attacker, attacker->tile, target->tile, 0, (DWORD*)&object, 0x20, (void*)obj_shoot_blocking_at_);
|
||||
object = AI_CheckShootAndFriendlyInLineOfFire(object, target->tile, attacker->critter.teamNum);
|
||||
return (object && object->IsCritter()) ? object : nullptr; // 0 if there are no friendly critters
|
||||
return (object && object->IsCritter()) ? object : nullptr; // 0 - if there are no friendly critters
|
||||
}
|
||||
|
||||
bool __stdcall AI_AttackInRange(TGameObj* source, TGameObj* weapon, long distance) {
|
||||
|
||||
@@ -987,28 +987,6 @@ runToObject:
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) MultiHexAIMissHitFix() {
|
||||
__asm {
|
||||
mov ecx, ebx; // distance weaponRange
|
||||
call tile_num_beyond_;
|
||||
mov ebx, [esi]; // ctd.source
|
||||
test [ebx + flags + 1], 0x08; // is source multihex?
|
||||
jnz checkTile;
|
||||
retn;
|
||||
checkTile:
|
||||
mov edx, [ebx + tile]; // source tile
|
||||
call tile_dist_; // eax - tile form tile_num_beyond_
|
||||
cmp eax, 1; // if distance is less than or equal to 1, this is a self-hit
|
||||
jle fix;
|
||||
retn;
|
||||
fix: // get correct tile beyond
|
||||
mov eax, [ebx + tile]; // source tile
|
||||
mov edx, [ebx + rotation]; // source rotation
|
||||
mov ebx, ecx; // distance weaponRange
|
||||
jmp tile_num_in_direction_; // return new tile for missed projectile
|
||||
}
|
||||
}
|
||||
|
||||
// checks if an attacked object is a critter before attempting dodge animation
|
||||
static void __declspec(naked) action_melee_hack() {
|
||||
__asm {
|
||||
@@ -3166,16 +3144,6 @@ void BugFixes_Init()
|
||||
dlogr(" Done", DL_INIT);
|
||||
//}
|
||||
|
||||
// Fix for multihex critters hitting themselves when they miss an attack with ranged weapons
|
||||
// Note: in fact, the bug is in tile_num_beyond_ and related functions. In case of a more comprehensive fix to them, this fix
|
||||
// will need to be removed
|
||||
//if (GetConfigInt("Misc", "MultiHexSelfHitFix", 1)) {
|
||||
dlog("Applying multihex critter self-hit fix.", DL_INIT);
|
||||
const DWORD multiHexBeyondAddr[] = {0x423B44, 0x42315D};
|
||||
HookCalls(MultiHexAIMissHitFix, multiHexBeyondAddr);
|
||||
dlogr(" Done", DL_INIT);
|
||||
//}
|
||||
|
||||
//if (GetConfigInt("Misc", "DodgyDoorsFix", 1)) {
|
||||
dlog("Applying Dodgy Door Fix.", DL_INIT);
|
||||
MakeJump(0x4113D6, action_melee_hack);
|
||||
|
||||
@@ -530,6 +530,7 @@ FUNC(tile_dist_, 0x4B185C)
|
||||
FUNC(tile_num_, 0x4B1754)
|
||||
FUNC(tile_num_beyond_, 0x4B1B84)
|
||||
FUNC(tile_num_in_direction_, 0x4B1A6C)
|
||||
FUNC(tile_on_edge_, 0x4B1D20)
|
||||
FUNC(tile_refresh_display_, 0x4B12D8)
|
||||
FUNC(tile_refresh_rect_, 0x4B12C0) // (int elevation<edx>, unkown<ecx>)
|
||||
FUNC(tile_scroll_to_, 0x4B3924)
|
||||
|
||||
@@ -50,6 +50,7 @@ WRAP_WATCOM_FFUNC4(void, register_object_call, long*, target, long*, source, voi
|
||||
WRAP_WATCOM_FFUNC3(long, scr_get_local_var, long, sid, long, varId, long*, value)
|
||||
WRAP_WATCOM_FFUNC3(long, scr_set_local_var, long, sid, long, varId, long, value)
|
||||
WRAP_WATCOM_FFUNC6(long, text_object_create, TGameObj*, object, const char*, text, long, font, long, colorText, long, colorOutline, BoundRect*, rect)
|
||||
WRAP_WATCOM_FFUNC3(long, tile_coord, long, tile, long*, outX, long*, outY) // the fourth argument of the function is not used
|
||||
WRAP_WATCOM_FFUNC3(long, tile_num_in_direction, long, tile, long, rotation, long, distance)
|
||||
WRAP_WATCOM_FFUNC8(void, trans_cscale, void*, fromBuff, long, width, long, height, long, fromPitch, void*, toBuff, long, toWidth, long, toHeight, long, toPitch)
|
||||
WRAP_WATCOM_FFUNC3(void, win_clip, WINinfo*, window, RectList**, rects, void*, buffer)
|
||||
@@ -221,6 +222,7 @@ WRAP_WATCOM_FUNC2(long, stat_level, TGameObj*, critter, long, statId)
|
||||
WRAP_WATCOM_FUNC1(long, text_font, long, fontNum)
|
||||
WRAP_WATCOM_FUNC2(long, tile_dist, long, scrTile, long, dstTile)
|
||||
WRAP_WATCOM_FUNC2(long, tile_dir, long, scrTile, long, dstTile)
|
||||
WRAP_WATCOM_FUNC1(long, tile_on_edge, long, tile)
|
||||
WRAP_WATCOM_FUNC0(void, tile_refresh_display) // Redraws the whole screen
|
||||
WRAP_WATCOM_FUNC2(void, tile_refresh_rect, BoundRect*, boundRect, long, elevation) // Redraws the given rectangle on screen
|
||||
WRAP_WATCOM_FUNC1(long, trait_level, long, traitID)
|
||||
|
||||
@@ -512,6 +512,148 @@ static void __declspec(naked) trait_adjust_stat_hack() {
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////// TILEMAP ////////////////////////////////////
|
||||
|
||||
static std::vector<int> buildLineTiles;
|
||||
|
||||
static bool __stdcall TileExists(long tile) {
|
||||
return (std::find(buildLineTiles.cbegin(), buildLineTiles.cend(), tile) != buildLineTiles.cend());
|
||||
}
|
||||
|
||||
// Fixed and improved implementation of tile_num_beyond_ engine function
|
||||
// compared to the original implementation, this function gets the hex (tile) from the constructed line more correctly
|
||||
long __fastcall sfgame_tile_num_beyond(long sourceTile, long targetTile, long maxRange) {
|
||||
if (maxRange <= 0 || sourceTile == targetTile) return sourceTile;
|
||||
|
||||
maxRange++;
|
||||
|
||||
if (buildLineTiles.empty()) {
|
||||
buildLineTiles.reserve(50);
|
||||
} else {
|
||||
buildLineTiles.clear();
|
||||
}
|
||||
|
||||
long currentRange = fo_tile_dist(sourceTile, targetTile);
|
||||
//fo_debug_printf("\ntile_dist: %d", currentRange);
|
||||
|
||||
long lastTile = targetTile;
|
||||
long source_X, source_Y, target_X, target_Y;
|
||||
|
||||
fo_tile_coord(sourceTile, &source_X, &source_Y);
|
||||
fo_tile_coord(targetTile, &target_X, &target_Y);
|
||||
|
||||
// set the point to the center of the hexagon
|
||||
source_X += 16;
|
||||
source_Y += 8;
|
||||
target_X += 16;
|
||||
target_Y += 8;
|
||||
|
||||
long diffX = target_X - source_X;
|
||||
long addToX = -1;
|
||||
if (diffX >= 0) addToX = (diffX > 0);
|
||||
|
||||
long diffY = target_Y - source_Y;
|
||||
long addToY = -1;
|
||||
if (diffY >= 0) addToY = (diffY > 0);
|
||||
|
||||
long diffX_x2 = 2 * std::abs(diffX);
|
||||
long diffY_x2 = 2 * std::abs(diffY);
|
||||
|
||||
long direction = (source_X != target_X) ? fo_tile_dir(sourceTile, targetTile) : -1;
|
||||
//fo_debug_printf("\ntile_dir: %d", direction);
|
||||
switch (direction) {
|
||||
case 0:
|
||||
target_X += 8;
|
||||
target_Y -= 4;
|
||||
break;
|
||||
case 1:
|
||||
target_X += 15;
|
||||
break;
|
||||
case 2:
|
||||
target_X += 8;
|
||||
target_Y += 4;
|
||||
break;
|
||||
case 3:
|
||||
target_X -= 8;
|
||||
target_Y += 4;
|
||||
break;
|
||||
case 4:
|
||||
target_X -= 15;
|
||||
break;
|
||||
case 5:
|
||||
target_X -= 8;
|
||||
target_Y -= 4;
|
||||
break;
|
||||
}
|
||||
long step = 0;
|
||||
|
||||
if (diffX_x2 > diffY_x2) {
|
||||
long stepY = diffY_x2 - (diffX_x2 >> 1);
|
||||
while (true) {
|
||||
if (!(++step % 2)) {
|
||||
long tile = fo_tile_num(target_X, target_Y);
|
||||
//fo_debug_printf("\ntile_num: %d [x:%d y:%d]", tile, target_X, target_Y);
|
||||
if (tile != lastTile) {
|
||||
if (!TileExists(tile)) {
|
||||
if (++currentRange >= maxRange || fo_tile_on_edge(tile)) return tile;
|
||||
buildLineTiles.push_back(tile);
|
||||
}
|
||||
lastTile = tile;
|
||||
}
|
||||
}
|
||||
if (stepY >= 0) {
|
||||
stepY -= diffX_x2;
|
||||
target_Y += addToY;
|
||||
}
|
||||
stepY += diffY_x2;
|
||||
target_X += addToX;
|
||||
|
||||
// Example of an algorithm constructing a straight line from point A to B
|
||||
// source: x = 784(800), y = 278(286)
|
||||
// target: x = 640(656), y = 314(322) - the target is located to the left and below
|
||||
// 0. x = 800, y = 286, stepY = -72
|
||||
// 1. x = 799, y = 286, stepY = -72+72=0
|
||||
// 2. x = 798, y = 287, stepY = 0-288+72=-216
|
||||
// 3. x = 797, y = 287, stepY = -216+72=-144
|
||||
// 4. x = 796, y = 287, stepY = -144+72=-72
|
||||
// 5. x = 795, y = 287, stepY = -72+72=0
|
||||
// 6. x = 794, y = 288, stepY = 0-288+72=-216
|
||||
}
|
||||
} else {
|
||||
long stepX = diffX_x2 - (diffY_x2 >> 1);
|
||||
while (true) {
|
||||
if (!(++step % 2)) {
|
||||
long tile = fo_tile_num(target_X, target_Y);
|
||||
//fo_debug_printf("\ntile_num: %d [x:%d y:%d]", tile, target_X, target_Y);
|
||||
if (tile != lastTile) {
|
||||
if (!TileExists(tile)) {
|
||||
if (++currentRange >= maxRange || fo_tile_on_edge(tile)) return tile;
|
||||
buildLineTiles.push_back(tile);
|
||||
}
|
||||
lastTile = tile;
|
||||
}
|
||||
}
|
||||
if (stepX >= 0) {
|
||||
stepX -= diffY_x2;
|
||||
target_X += addToX;
|
||||
}
|
||||
stepX += diffX_x2;
|
||||
target_Y += addToY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) tile_num_beyond_hack() {
|
||||
__asm {
|
||||
//push ecx;
|
||||
push ebx;
|
||||
mov ecx, eax;
|
||||
call sfgame_tile_num_beyond;
|
||||
pop ecx;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void InitReplacementHacks() {
|
||||
@@ -538,4 +680,7 @@ void InitReplacementHacks() {
|
||||
|
||||
// Fix the carry weight penalty of the Small Frame trait not being applied to bonus Strength points
|
||||
smallFrameTraitFix = (GetConfigInt("Misc", "SmallFrameFix", 0) != 0);
|
||||
|
||||
// Replace tile_num_beyond_ function
|
||||
MakeJump(tile_num_beyond_ + 1, tile_num_beyond_hack); // 0x4B1B84
|
||||
}
|
||||
|
||||
@@ -54,3 +54,5 @@ int __stdcall sfgame_trait_adjust_skill(DWORD skillID);
|
||||
int __stdcall sfgame_trait_level(DWORD traitID);
|
||||
|
||||
int __stdcall sfgame_trait_adjust_stat(DWORD statID);
|
||||
|
||||
long __fastcall sfgame_tile_num_beyond(long sourceTile, long targetTile, long maxRange);
|
||||
|
||||
@@ -20,10 +20,6 @@
|
||||
|
||||
#include <psapi.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "main.h"
|
||||
#include "FalloutEngine.h"
|
||||
#include "AI.h"
|
||||
|
||||
Reference in New Issue
Block a user