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:
+1
-1
@@ -15,7 +15,7 @@ UseCommandLine=0
|
||||
;If DataLoadOrderPatch is enabled, the data load order is:
|
||||
;master_patches > critter_patches > PatchFileXX > patchXXX.dat > critter_dat > f2_res_patches > f2_res_dat > master_dat
|
||||
;Paths to folders and Fallout .dat files are supported. The available range for PatchFile option names is from 0 to 99
|
||||
;The greater numbers take precedence over lesser numbers
|
||||
;Larger numbers take precedence over smaller numbers (same as patchXXX.dat)
|
||||
;PatchFile0=mods\RP_data
|
||||
|
||||
;Path to the folder in which the game will automatically search and load custom files (by *.dat mask, including folders)
|
||||
|
||||
@@ -54,6 +54,7 @@ WRAP_WATCOM_FFUNC3(long, register_object_play_sfx, fo::GameObject*, object, cons
|
||||
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, fo::GameObject*, object, const char*, text, long, font, long, colorText, long, colorOutline, fo::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, fo::Window*, window, fo::RectList**, rects, void*, buffer)
|
||||
@@ -268,6 +269,7 @@ WRAP_WATCOM_FUNC1(void, stat_pc_add_experience, long, amount) // Adds experience
|
||||
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, fo::BoundRect*, boundRect, long, elevation) // Redraws the given rectangle on screen
|
||||
WRAP_WATCOM_FUNC1(long, trait_level, long, traitID)
|
||||
|
||||
@@ -110,7 +110,7 @@ static void __declspec(naked) adjust_fid_hack() {
|
||||
}
|
||||
|
||||
void Inventory::init() {
|
||||
// Replace functions
|
||||
// Replace adjust_fid_ function
|
||||
sf::MakeJump(fo::funcoffs::adjust_fid_, adjust_fid_hack); // 0x4716E8
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ static void __declspec(naked) trait_adjust_skill_hack() {
|
||||
}
|
||||
|
||||
void Skills::init() {
|
||||
// Replace functions
|
||||
// Replace trait_adjust_skill_ function
|
||||
sf::MakeJump(fo::funcoffs::trait_adjust_skill_, trait_adjust_skill_hack); // 0x4B40FC
|
||||
}
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ static void __declspec(naked) trait_adjust_stat_hack() {
|
||||
}
|
||||
|
||||
void Stats::init() {
|
||||
// Replace functions
|
||||
// Replace trait_adjust_stat_ function
|
||||
sf::MakeJump(fo::funcoffs::trait_adjust_stat_, trait_adjust_stat_hack); // 0x4B3C7C
|
||||
|
||||
// Fix the carry weight penalty of the Small Frame trait not being applied to bonus Strength points
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* sfall
|
||||
* Copyright (C) 2008-2021 The sfall team
|
||||
*
|
||||
*/
|
||||
|
||||
#include "..\main.h"
|
||||
#include "..\FalloutEngine\Fallout2.h"
|
||||
|
||||
#include "tilemap.h"
|
||||
|
||||
namespace game
|
||||
{
|
||||
|
||||
namespace sf = sfall;
|
||||
|
||||
static std::vector<int> buildLineTiles;
|
||||
|
||||
static bool 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 Tilemap::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::func::tile_dist(sourceTile, targetTile);
|
||||
//fo::func::debug_printf("\ntile_dist: %d", currentRange);
|
||||
|
||||
long lastTile = targetTile;
|
||||
long source_X, source_Y, target_X, target_Y;
|
||||
|
||||
fo::func::tile_coord(sourceTile, &source_X, &source_Y);
|
||||
fo::func::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::func::tile_dir(sourceTile, targetTile) : -1;
|
||||
//fo::func::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::func::tile_num(target_X, target_Y);
|
||||
//fo::func::debug_printf("\ntile_num: %d [x:%d y:%d]", tile, target_X, target_Y);
|
||||
if (tile != lastTile) {
|
||||
if (!TileExists(tile)) {
|
||||
if (++currentRange >= maxRange || fo::func::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::func::tile_num(target_X, target_Y);
|
||||
//fo::func::debug_printf("\ntile_num: %d [x:%d y:%d]", tile, target_X, target_Y);
|
||||
if (tile != lastTile) {
|
||||
if (!TileExists(tile)) {
|
||||
if (++currentRange >= maxRange || fo::func::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 Tilemap::tile_num_beyond;
|
||||
pop ecx;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
void Tilemap::init() {
|
||||
// Replace tile_num_beyond_ function
|
||||
sf::MakeJump(fo::funcoffs::tile_num_beyond_ + 1, tile_num_beyond_hack); // 0x4B1B84
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* sfall
|
||||
* Copyright (C) 2008-2021 The sfall team
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace game
|
||||
{
|
||||
|
||||
class Tilemap {
|
||||
public:
|
||||
static void init();
|
||||
|
||||
static long __fastcall tile_num_beyond(long sourceTile, long targetTile, long maxRange);
|
||||
};
|
||||
|
||||
}
|
||||
@@ -47,18 +47,19 @@ fo::GameObject* AI::CheckShootAndFriendlyInLineOfFire(fo::GameObject* object, lo
|
||||
}
|
||||
// continue checking the line of fire from object tile to targetTile
|
||||
fo::GameObject* obj = object; // for ignoring the object (multihex) when building the path
|
||||
fo::func::make_straight_path_func(object, objTile, targetTile, 0, (DWORD*)&obj, 32, (void*)fo::funcoffs::obj_shoot_blocking_at_);
|
||||
if (!CheckShootAndFriendlyInLineOfFire(obj, targetTile, team)) return nullptr;
|
||||
fo::func::make_straight_path_func(object, objTile, targetTile, 0, (DWORD*)&obj, 0x20, (void*)fo::funcoffs::obj_shoot_blocking_at_);
|
||||
|
||||
object = CheckShootAndFriendlyInLineOfFire(obj, targetTile, team);
|
||||
}
|
||||
return object;
|
||||
return object; // friendly critter, any object or null
|
||||
}
|
||||
|
||||
// Returns the friendly critter in the line of fire
|
||||
fo::GameObject* AI::CheckFriendlyFire(fo::GameObject* target, fo::GameObject* attacker) {
|
||||
fo::GameObject* object = nullptr;
|
||||
fo::func::make_straight_path_func(attacker, attacker->tile, target->tile, 0, (DWORD*)&object, 32, (void*)fo::funcoffs::obj_shoot_blocking_at_);
|
||||
fo::func::make_straight_path_func(attacker, attacker->tile, target->tile, 0, (DWORD*)&object, 0x20, (void*)fo::funcoffs::obj_shoot_blocking_at_);
|
||||
object = 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 AI::AttackInRange(fo::GameObject* source, fo::GameObject* weapon, long distance) {
|
||||
|
||||
@@ -1004,28 +1004,6 @@ runToObject:
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) MultiHexAIMissHitFix() {
|
||||
__asm {
|
||||
mov ecx, ebx; // distance weaponRange
|
||||
call fo::funcoffs::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 fo::funcoffs::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 fo::funcoffs::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 {
|
||||
@@ -3180,15 +3158,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);
|
||||
HookCalls(MultiHexAIMissHitFix, {0x423B44, 0x42315D});
|
||||
dlogr(" Done", DL_INIT);
|
||||
//}
|
||||
|
||||
//if (GetConfigInt("Misc", "DodgyDoorsFix", 1)) {
|
||||
dlog("Applying Dodgy Door Fix.", DL_INIT);
|
||||
MakeJump(0x4113D6, action_melee_hack);
|
||||
|
||||
@@ -11,3 +11,4 @@
|
||||
#include "Game\render.h"
|
||||
#include "Game\skills.h"
|
||||
#include "Game\stats.h"
|
||||
#include "Game\tilemap.h"
|
||||
|
||||
@@ -297,6 +297,7 @@
|
||||
<ClInclude Include="Game\render.h" />
|
||||
<ClInclude Include="Game\skills.h" />
|
||||
<ClInclude Include="Game\stats.h" />
|
||||
<ClInclude Include="Game\tilemap.h" />
|
||||
<ClInclude Include="IniReader.h" />
|
||||
<ClInclude Include="Modules\CritterPoison.h" />
|
||||
<ClInclude Include="Modules\CritterStats.h" />
|
||||
@@ -406,6 +407,7 @@
|
||||
<ClCompile Include="Game\render.cpp" />
|
||||
<ClCompile Include="Game\skills.cpp" />
|
||||
<ClCompile Include="Game\stats.cpp" />
|
||||
<ClCompile Include="Game\tilemap.cpp" />
|
||||
<ClCompile Include="IniReader.cpp" />
|
||||
<ClCompile Include="Modules\CritterPoison.cpp" />
|
||||
<ClCompile Include="Modules\CritterStats.cpp" />
|
||||
|
||||
@@ -339,6 +339,9 @@
|
||||
<Filter>Modules\Scripting\Handlers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="IniReader.h" />
|
||||
<ClInclude Include="Game\tilemap.h">
|
||||
<Filter>Game</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp" />
|
||||
@@ -628,6 +631,9 @@
|
||||
<Filter>Modules\Scripting\Handlers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IniReader.cpp" />
|
||||
<ClCompile Include="Game\tilemap.cpp">
|
||||
<Filter>Game</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="version.rc" />
|
||||
|
||||
+1
-4
@@ -20,10 +20,6 @@
|
||||
|
||||
#include <psapi.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdio.h>
|
||||
#include <memory>
|
||||
|
||||
#include "FalloutEngine\Fallout2.h"
|
||||
#include "ModuleManager.h"
|
||||
#include "Modules\Module.h"
|
||||
@@ -108,6 +104,7 @@ void InitReplacementHacks() {
|
||||
game::Render::init();
|
||||
game::Skills::init();
|
||||
game::Stats::init();
|
||||
game::Tilemap::init();
|
||||
}
|
||||
|
||||
static void InitModules() {
|
||||
|
||||
Reference in New Issue
Block a user