diff --git a/sfall/FalloutEngine/Functions.cpp b/sfall/FalloutEngine/Functions.cpp
index ac38c512..7b09e28b 100644
--- a/sfall/FalloutEngine/Functions.cpp
+++ b/sfall/FalloutEngine/Functions.cpp
@@ -1,20 +1,20 @@
/*
-* sfall
-* Copyright (C) 2008-2016 The sfall team
-*
-* This program is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program. If not, see .
-*/
+ * sfall
+ * Copyright (C) 2008-2016 The sfall team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
#include "FunctionOffsets.h"
#include "VariableOffsets.h"
@@ -155,9 +155,18 @@ void __declspec(naked) interpretError(const char* fmt, ...) {
}
long __fastcall tile_num(long x, long y) {
- __asm push ebx; // don't delete (bug in tile_num_)
+ __asm xor ebx, ebx; // don't delete (bug in tile_num_)
WRAP_WATCOM_FCALL2(tile_num_, x, y);
- __asm pop ebx;
+}
+
+void __fastcall square_xy(long x, long y, long* outSX, long* outSY) {
+ __asm {
+ xor ebx, ebx; // don't delete (bug in square_xy_)
+ mov eax, ecx;
+ push outSY;
+ mov ecx, outSX;
+ call fo::funcoffs::square_xy_;
+ }
}
GameObject* __fastcall obj_blocking_at_wrapper(GameObject* obj, DWORD tile, DWORD elevation, void* func) {
diff --git a/sfall/FalloutEngine/Functions.h b/sfall/FalloutEngine/Functions.h
index af529a98..db550d4e 100644
--- a/sfall/FalloutEngine/Functions.h
+++ b/sfall/FalloutEngine/Functions.h
@@ -1,20 +1,20 @@
/*
-* sfall
-* Copyright (C) 2008-2017 The sfall team
-*
-* This program is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program. If not, see .
-*/
+ * sfall
+ * Copyright (C) 2008-2017 The sfall team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
#pragma once
@@ -54,6 +54,8 @@ void __declspec() interpretError(const char* fmt, ...);
long __fastcall tile_num(long x, long y);
+void __fastcall square_xy(long x, long y, long* outSX, long* outSY);
+
GameObject* __fastcall obj_blocking_at_wrapper(GameObject* obj, DWORD tile, DWORD elevation, void* func);
// Creates a button on a given window
diff --git a/sfall/FalloutEngine/Functions_def.h b/sfall/FalloutEngine/Functions_def.h
index e494b982..1334ba55 100644
--- a/sfall/FalloutEngine/Functions_def.h
+++ b/sfall/FalloutEngine/Functions_def.h
@@ -60,6 +60,7 @@ WRAP_WATCOM_FFUNC4(long, register_object_run_to_object, fo::GameObject*, source,
WRAP_WATCOM_FFUNC3(long, register_object_play_sfx, fo::GameObject*, object, const char*, sfxName, long, delay)
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_FFUNC3(long, square_coord, long, square, long*, outX, long*, outY)
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)
diff --git a/sfall/HRP/Init.cpp b/sfall/HRP/Init.cpp
index 08a8a825..81c369a2 100644
--- a/sfall/HRP/Init.cpp
+++ b/sfall/HRP/Init.cpp
@@ -57,6 +57,8 @@ bool HRP::CheckExternalPatch() {
}
void HRP::init() {
+ //SafeWrite16(0x4B2EA8, 0x9090); // _show_grid
+
if (!hrpIsEnabled && IniReader::GetIntDefaultConfig("Main", "HiResMode", 1) == 0) return; // vanilla game mode
SCR_WIDTH = IniReader::GetInt("Main", "SCR_WIDTH", 640, f2ResIni);
@@ -93,8 +95,8 @@ void HRP::init() {
std::string x = trim(IniReader::GetString("MAPS", "SCROLL_DIST_X", "480", 16, f2ResIni));
std::string y = trim(IniReader::GetString("MAPS", "SCROLL_DIST_Y", "400", 16, f2ResIni));
- ViewMap::SCROLL_DIST_X = (x == "HALF_SCRN") ? (SCR_WIDTH / 2) + 32 : std::atol(x.c_str());
- ViewMap::SCROLL_DIST_Y = (y == "HALF_SCRN") ? (SCR_HEIGHT / 2) + 24 : std::atol(y.c_str());
+ ViewMap::SCROLL_DIST_X = (!x.compare(0, 9, "HALF_SCRN")) ? (SCR_WIDTH / 2) + 32 : std::atol(x.c_str());
+ ViewMap::SCROLL_DIST_Y = (!y.compare(0, 9, "HALF_SCRN")) ? (SCR_HEIGHT / 2) + 24 : std::atol(y.c_str());
ViewMap::IGNORE_PLAYER_SCROLL_LIMITS = (IniReader::GetInt("MAPS", "IGNORE_PLAYER_SCROLL_LIMITS", 0, f2ResIni) != 0);
ViewMap::IGNORE_MAP_EDGES = (IniReader::GetInt("MAPS", "IGNORE_MAP_EDGES", 0, f2ResIni) != 0);
@@ -106,20 +108,27 @@ void HRP::init() {
IniReader::GetString("Main", "f2_res_patches", "data", MAX_PATH, f2ResIni)
);
- // Inject hacks
+ /* Inject hacks */
SafeWrite32(0x482E30, FO_VAR_mapEntranceTileNum); // map_load_file_ (_tile_center_tile to _mapEntranceTileNum)
- // Set the resolution for GNW95_init_mode_ex_
- SafeWrite32(0x4CAD6B, SCR_WIDTH); // 640
- SafeWrite32(0x4CAD66, SCR_HEIGHT); // 480
+ if (SCR_WIDTH != 640 || SCR_HEIGHT != 480) {
+ // Set the resolution for GNW95_init_mode_ex_
+ SafeWrite32(0x4CAD6B, SCR_WIDTH); // 640
+ SafeWrite32(0x4CAD66, SCR_HEIGHT); // 480
- // Set the resolution for the overlapping temporary black window when loading/starting the game
- // main_load_new_
- SafeWrite32(0x480D6C, SCR_HEIGHT);
- SafeWrite32(0x480D84, SCR_WIDTH);
- // gnw_main_
- SafeWrite32(0x480AFA, SCR_HEIGHT); // -100 for ifacebar?
- SafeWrite32(0x480B04, SCR_WIDTH);
+ // Set the resolution for the overlapping temporary black window when loading/starting the game
+ // main_load_new_
+ SafeWrite32(0x480D6C, SCR_HEIGHT);
+ SafeWrite32(0x480D84, SCR_WIDTH);
+ // gnw_main_
+ SafeWrite32(0x480AFA, SCR_HEIGHT); // -100 for ifacebar?
+ SafeWrite32(0x480B04, SCR_WIDTH);
+ // LoadGame_
+ SafeWrite32(0x47C6E0, SCR_HEIGHT);
+ SafeWrite32(0x47C6E5, SCR_WIDTH);
+ SafeWrite32(0x47C703, SCR_WIDTH);
+ SafeWrite32(0x47C70D, SCR_HEIGHT);
+ }
// Inits
SplashScreen::init();
diff --git a/sfall/HRP/ViewMap/EdgeBorder.cpp b/sfall/HRP/ViewMap/EdgeBorder.cpp
index d0ed9987..c4c6a8f3 100644
--- a/sfall/HRP/ViewMap/EdgeBorder.cpp
+++ b/sfall/HRP/ViewMap/EdgeBorder.cpp
@@ -16,15 +16,15 @@ namespace sfall
{
static EdgeBorder::Edge* MapEdgeData;
-
-// reference
-EdgeBorder::Edge* currentMapEdge;
-
-EdgeBorder::Edge* EdgeBorder::CurrentMapEdge() { return currentMapEdge; }
+static EdgeBorder::Edge* currentMapEdge; // reference
static long edgeVersion; // 0 - version 1 (obsolete), 1 - version 2 (current)
-bool isLoadingMapEdge;
-bool isDefaultSetEdge;
+static bool isDefaultSetEdge;
+//bool isLoadingMapEdge;
+
+long EdgeBorder::EdgeVersion() { return edgeVersion; }
+
+EdgeBorder::Edge* EdgeBorder::CurrentMapEdge() { return currentMapEdge; }
// Implementation from HRP by Mash
static void CalcEdgeData(EdgeBorder::Edge* edgeData, long w, long h) {
@@ -67,7 +67,7 @@ static void CalcEdgeData(EdgeBorder::Edge* edgeData, long w, long h) {
long rectH = (edgeData->borderRect.bottom - edgeData->borderRect.top) / 2;
long _rectH = rectH;
if (rectH % 24) {
- rectH -= rectH % 24; // truncate
+ rectH -= rectH % 24;
_rectH = rectH + 24;
}
if (rectH < h) {
@@ -78,7 +78,6 @@ static void CalcEdgeData(EdgeBorder::Edge* edgeData, long w, long h) {
edgeData->borderRect.bottom -= h;
}
- // borderRect: right is less than left
if ((edgeData->borderRect.left < edgeData->borderRect.right) || (edgeData->borderRect.left - edgeData->borderRect.right) == 32) {
edgeData->borderRect.left = edgeData->borderRect.right;
}
@@ -197,6 +196,7 @@ static fo::DbFile* LoadMapEdgeFileSub(char* mapName) {
if (getValue != mapLevel) break; // next level
EdgeBorder::Edge *edge = new EdgeBorder::Edge;
+ edge->prevEdgeData = edgeData;
edge->nextEdgeData = nullptr;
edge->squareRect = edgeData->squareRect; // rect copy
edgeData->nextEdgeData = edge;
@@ -303,8 +303,8 @@ long EdgeBorder::CheckBorder(long tile) {
long x, y;
ViewMap::GetTileCoordOffset(tile, x, y);
- if (x > currentMapEdge->borderRect.left || x < currentMapEdge->borderRect.right ||
- y > currentMapEdge->borderRect.bottom || y < currentMapEdge->borderRect.top)
+ if (x > currentMapEdge->borderRect.left || x < currentMapEdge->borderRect.right ||
+ y < currentMapEdge->borderRect.top || y > currentMapEdge->borderRect.bottom)
{
return 0; // block
}
diff --git a/sfall/HRP/ViewMap/EdgeBorder.h b/sfall/HRP/ViewMap/EdgeBorder.h
index ee151802..c05f1b20 100644
--- a/sfall/HRP/ViewMap/EdgeBorder.h
+++ b/sfall/HRP/ViewMap/EdgeBorder.h
@@ -12,8 +12,8 @@ namespace sfall
class EdgeBorder {
public:
struct Edge {
- POINT center; // x/y center of current map screen?
- RECT borderRect;
+ POINT center; // x/y center of current map screen?
+ RECT borderRect; // right is less than left
RECT rect_2;
RECT tileRect;
RECT squareRect;
@@ -36,7 +36,10 @@ public:
};
static void init();
+
static Edge* CurrentMapEdge();
+ static long EdgeVersion();
+
static long GetCenterTile(long tile, long mapLevel);
static long CheckBorder(long tile);
};
diff --git a/sfall/HRP/ViewMap/EdgeClipping.cpp b/sfall/HRP/ViewMap/EdgeClipping.cpp
index e9b5c2a6..77cc4001 100644
--- a/sfall/HRP/ViewMap/EdgeClipping.cpp
+++ b/sfall/HRP/ViewMap/EdgeClipping.cpp
@@ -19,7 +19,7 @@ static RECT mapVisibleArea;
// Returns -1 if the scrRect is not in the rectangle of inRect (same as rect_inside_bound_)
static __inline long rect_inside_bound(RECT* srcRect, RECT* inRect, RECT* outRect) {
- *outRect = *srcRect; // srcRect copy to outRect
+ if (srcRect != outRect) *outRect = *srcRect; // srcRect copy to outRect
if (inRect->right < srcRect->left ||
inRect->left > srcRect->right ||
@@ -111,7 +111,7 @@ static long __fastcall rect_inside_bound_clip(RECT* srcRect, RECT* inRect, RECT*
if (ViewMap::EDGE_CLIPPING_ON) {
if (CheckRect(outRect)) { // when do you need the fill below?
- long height = outRect->bottom - outRect->top + 1;
+ long height = (outRect->bottom - outRect->top) + 1;
if (height > 0) {
long width = (outRect->right - outRect->left) + 1;
if (width > 0) {
@@ -139,7 +139,7 @@ static void __declspec(naked) refresh_game_hook_rect_inside_bound() {
static long __fastcall rect_inside_bound_scroll_clip(RECT* srcRect, RECT* inRect, RECT* outRect) {
long height = (srcRect->bottom - srcRect->top) + 1;
if (height > 0) {
- long width = srcRect->right - srcRect->left + 1;
+ long width = (srcRect->right - srcRect->left) + 1;
if (width > 0) {
ClearRect(width, height, srcRect);
}
@@ -159,9 +159,10 @@ static void __declspec(naked) map_scroll_refresh_game_hook_rect_inside_bound() {
}
static long __fastcall MouseCheckArea(long x, long y) {
- if (x < (mapVisibleArea.left) || x > (mapVisibleArea.right) || y < mapVisibleArea.top || y >= mapVisibleArea.bottom) {
+ if (!ViewMap::EDGE_CLIPPING_ON) return 0;
+ if (x < mapVisibleArea.left || x > mapVisibleArea.right || y < mapVisibleArea.top || y >= mapVisibleArea.bottom) {
if (fo::func::win_get_top_win(x, y) == fo::var::getInt(FO_VAR_display_win)) {
- return -7;
+ return 40000;
}
}
return 0;
@@ -186,7 +187,8 @@ check:
jnz set;
retn;
set:
- mov ebx, eax;
+ mov ebx, -7;
+ //mov ecx, 3;
retn;
}
}
diff --git a/sfall/HRP/ViewMap/ViewMap.cpp b/sfall/HRP/ViewMap/ViewMap.cpp
index 767a2a70..075338d4 100644
--- a/sfall/HRP/ViewMap/ViewMap.cpp
+++ b/sfall/HRP/ViewMap/ViewMap.cpp
@@ -17,6 +17,10 @@
namespace sfall
{
+const long grid_width = 200; // _grid_width
+const long square_width = 100;
+const long square_length = 100;
+
static Rectangle obj_on_screen_rect;
long ViewMap::SCROLL_DIST_X;
@@ -39,15 +43,15 @@ void ViewMap::GetCoordFromOffset(long &inOutX, long &inOutY) {
}
void ViewMap::GetTileCoord(long tile, long &outX, long &outY) {
- int x = tile % 200; // tile % _grid_width // 20100%200 = 100
- int y = (tile / 200) + (x / 2); // tile / _grid_width + x / 2 // 20100/200 = 100+(100/2) = y:150 ???
+ int x = tile % grid_width; // 20100%200 = 100
+ int y = (tile / grid_width) + (x / 2); // 20100/200 = 100+(100/2) = y:150 ???
outY = y;
outX = (2 * x) - y; // 2*100 = 200-150 = x:50 ???
}
void ViewMap::GetTileCoordOffset(long tile, long &outX, long &outY) {
- int x = tile % 200; // tile % _grid_width // 20100%200 = 100
- int y = (tile / 200) + (x / 2); // tile / _grid_width + x / 2 // 20100/200 = 100+(100/2) = y:150 ???
+ int x = tile % grid_width; // 20100%200 = 100
+ int y = (tile / grid_width) + (x / 2); // 20100/200 = 100+(100/2) = y:150 ???
y &= 0xFFFFFFFE; // even to down
x = (2 * x) + 200 - y; // 2*100 = 200+200-150 = x:250 ???
@@ -112,8 +116,8 @@ static long __fastcall tile_set_center(long tile, long modeFlags) {
fo::var::setInt(FO_VAR_tile_center_tile) = tile;
- long tile_y = tile / 200; // _grid_width
- long tile_x = 200 - (tile % 200) - 1;
+ long tile_y = tile / grid_width;
+ long tile_x = 200 - (tile % grid_width) - 1;
if (tile_x & 1) {
tile_x--;
@@ -155,11 +159,178 @@ static void __declspec(naked) tile_set_center_hack_replacement() {
static void __declspec(naked) tile_scroll_to_hack_replacement() {
__asm {
- //mov edx, 3; // modeFlags is always 2
+ mov edx, 3; // modeFlags is always 2
jmp tile_set_center_hack_replacement;
}
}
+static long __fastcall square_rect_render_floor(long y, long id, long x) {
+ if (x < 0 || x >= square_width || y < 0 || y >= square_length) return -1;
+
+ auto edge = EdgeBorder::CurrentMapEdge();
+ if (EdgeBorder::EdgeVersion() && (x > edge->squareRect.left || x < edge->squareRect.right || y > edge->squareRect.bottom || y < edge->squareRect.top)) {
+ return 1;
+ }
+ return id;
+}
+
+static void __declspec(naked) square_render_floor_hook_art_id() {
+ __asm {
+ mov ecx, [esp + 0x24 + 4];
+ push esi;
+ call square_rect_render_floor;
+ test eax, eax;
+ js skipDraw; // -1
+ mov edx, eax;
+ xor ecx, ecx;
+ mov eax, 4;
+ jmp fo::funcoffs::art_id_;
+
+skipDraw:
+ mov [esp], 0x4B2AD4;
+ retn 4;
+ }
+}
+
+static long __fastcall square_rect_render_roof(long y, long id, long x) {
+ if (x < 0 || x >= square_width || y < 0 || y >= square_length) return -1;
+
+ auto edge = EdgeBorder::CurrentMapEdge();
+ if (EdgeBorder::EdgeVersion() && (x > (edge->squareRect.left + 2) || x < (edge->squareRect.right + 2) ||
+ y > (edge->squareRect.bottom + 3) || y < (edge->squareRect.top + 3)))
+ {
+ return -1;
+ }
+ return id;
+}
+
+static void __declspec(naked) square_render_roof_hook_art_id() {
+ using namespace fo;
+ __asm {
+ mov ecx, [esp + 0x20 + 4];
+ push edi;
+ call square_rect_render_roof;
+ test eax, eax;
+ js skipDraw; // -1
+ mov edx, eax;
+ xor ecx, ecx;
+ mov eax, OBJ_TYPE_TILE;
+ jmp fo::funcoffs::art_id_;
+
+skipDraw:
+ mov eax, esi;
+ retn 4;
+ }
+}
+
+static void __declspec(naked) square_roof_intersect_hook_art_id() {
+ using namespace fo;
+ __asm {
+ mov ecx, [esp + 0x8 + 4];
+ push [esp + 0x4 + 4];
+ call square_rect_render_roof;
+ test eax, eax;
+ js skipDraw; // -1
+ mov edx, eax;
+ xor ecx, ecx;
+ mov eax, OBJ_TYPE_TILE;
+ jmp fo::funcoffs::art_id_;
+
+skipDraw:
+ xor eax, eax;
+ mov [esp], 0x4B2C05;
+ retn 4;
+ }
+}
+
+static void __fastcall square_obj_render(fo::BoundRect* rect, long tag) {
+ if (EdgeBorder::EdgeVersion() == 0) return;
+
+ long x0, y0, x1, y1, x2, y2, x3, y3;
+
+ fo::func::square_xy(rect->x, rect->offy, &x0, &y0);
+ fo::func::square_xy(rect->x, rect->y, &x1, &y1);
+ fo::func::square_xy(rect->offx, rect->y, &x2, &y2);
+ fo::func::square_xy(rect->offx, rect->offy, &x3, &y3);
+
+ if (++x0 > square_width) x0 = square_width - 1;
+ if (--x2 < 0) x2 = 0;
+ if (--y1 < 0) y1 = 0;
+ if (++y3 > square_length) y3 = square_length - 1;
+
+ if (y1 >= y3 || x2 >= x0) return; // top >= bottom / left >= right
+
+ long Y = y1;
+ long sY = square_width * Y;
+
+ auto edge = EdgeBorder::CurrentMapEdge();
+ do {
+ long X = x2;
+ do {
+ if (X > edge->squareRect.left && ((edge->field_48 >> 24) & 1) == tag ||
+ Y < edge->squareRect.top && ((edge->field_48 >> 16) & 1) == tag ||
+ X < edge->squareRect.right && ((edge->field_48 >> 8) & 1) == tag ||
+ Y > edge->squareRect.bottom && (edge->field_48 & 1) == tag)
+ {
+ long s_x, s_y;
+ fo::func::square_coord(X + sY, &s_x, &s_y);
+ __asm {
+ mov ecx, rect;
+ mov ebx, s_y;
+ mov edx, s_x;
+ mov eax, 0x4000001; // tile fid
+ call fo::funcoffs::floor_draw_;
+ }
+ }
+ } while (++X < x0);
+
+ sY += square_width;
+ } while (++Y < y3); // y < bottom
+}
+
+static void __declspec(naked) obj_render_pre_roof_hack_0() {
+ __asm {
+ lea ecx, [esp + 4];
+ mov edx, 0;
+ call square_obj_render;
+ mov edi, [esp + 0x2C + 4];
+ test edi, edi;
+ retn;
+ }
+}
+
+static void __declspec(naked) obj_render_pre_roof_hack_1() {
+ __asm {
+ lea ecx, [esp + 4];
+ mov edx, 1;
+ call square_obj_render;
+ pop eax; // ret addr
+ add esp, 0x44;
+ pop ebp;
+ pop edi;
+ jmp eax;
+ }
+}
+
+// An odd solution to the problem from HRP 3.06 (4.1.8 uses a different solution)
+static void __declspec(naked) obj_render_pre_roof_hack() {
+ __asm {
+ mov ebx, [eax];
+ lea eax, [edx + ebx];
+ cmp eax, 40000; // _grid_size
+ jge capMax;
+ cmp eax, 0;
+ jl capMin;
+ retn;
+capMax:
+ mov eax, 39999;
+ retn;
+capMin:
+ xor eax, eax;
+ retn;
+ }
+}
+
void ViewMap::init() {
if (SCROLL_DIST_X <= 0) SCROLL_DIST_X = 480;
else if (SCROLL_DIST_X < 320) SCROLL_DIST_X = 320;
@@ -170,6 +341,15 @@ void ViewMap::init() {
MakeJump(fo::funcoffs::tile_set_center_, tile_set_center_hack_replacement); // 0x4B12F8
MakeJump(fo::funcoffs::tile_scroll_to_, tile_scroll_to_hack_replacement); // 0x4B3924
+ HookCall(0x4B2AC0, square_render_floor_hook_art_id);
+ HookCall(0x4B2261, square_render_roof_hook_art_id);
+ HookCall(0x4B2BF7, square_roof_intersect_hook_art_id); // need to test object_under_mouse_
+ MakeCall(0x489730, obj_render_pre_roof_hack_0, 1);
+ MakeCall(0x4897E3, obj_render_pre_roof_hack_1);
+
+ // Fix
+ MakeCall(0x489665, obj_render_pre_roof_hack); // find the bug
+
obj_on_screen_rect.width = HRP::ScreenWidth();
obj_on_screen_rect.height = HRP::ScreenHeight(); // maybe take into account the interface bar and be: height - 100?
SafeWrite32(0x45C886, (DWORD)&obj_on_screen_rect); // replace rectangle in op_obj_on_screen_