mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Added map edge clipping (partial)
This commit is contained in:
@@ -15,39 +15,19 @@
|
||||
namespace sfall
|
||||
{
|
||||
|
||||
static struct Edge {
|
||||
POINT center; // x/y center of current map screen?
|
||||
RECT borderRect;
|
||||
RECT rect_2;
|
||||
RECT tileRect;
|
||||
RECT squareRect;
|
||||
long field_48; // unknown
|
||||
Edge* prevEdgeData; // unused (used in 3.06)
|
||||
Edge* nextEdgeData;
|
||||
|
||||
void Release() {
|
||||
Edge* edge = nextEdgeData;
|
||||
while (edge) {
|
||||
Edge* edgeNext = edge->nextEdgeData;
|
||||
delete edge;
|
||||
edge = edgeNext;
|
||||
};
|
||||
}
|
||||
|
||||
~Edge() {
|
||||
Release();
|
||||
}
|
||||
} *MapEdgeData;
|
||||
static EdgeBorder::Edge* MapEdgeData;
|
||||
|
||||
// reference
|
||||
Edge* currentMapEdge;
|
||||
EdgeBorder::Edge* currentMapEdge;
|
||||
|
||||
EdgeBorder::Edge* EdgeBorder::CurrentMapEdge() { return currentMapEdge; }
|
||||
|
||||
static long edgeVersion; // 0 - version 1 (obsolete), 1 - version 2 (current)
|
||||
bool isLoadingMapEdge;
|
||||
bool isDefaultSetEdge;
|
||||
|
||||
// Implementation from HRP by Mash
|
||||
static void CalcEdgeData(Edge* edgeData, long w, long h) {
|
||||
static void CalcEdgeData(EdgeBorder::Edge* edgeData, long w, long h) {
|
||||
long x, y;
|
||||
|
||||
ViewMap::GetTileCoordOffset(edgeData->tileRect.left, x, y); // upper left corner?
|
||||
@@ -117,10 +97,10 @@ static void SetDefaultEdgeData() {
|
||||
long w, h;
|
||||
ViewMap::GetWinMapHalfSize(w, h);
|
||||
|
||||
if (MapEdgeData == nullptr) MapEdgeData = new Edge[3];
|
||||
if (MapEdgeData == nullptr) MapEdgeData = new EdgeBorder::Edge[3];
|
||||
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
Edge* edge = &MapEdgeData[i];
|
||||
EdgeBorder::Edge* edge = &MapEdgeData[i];
|
||||
|
||||
edge->tileRect.left = 199;
|
||||
edge->tileRect.top = 0;
|
||||
@@ -180,12 +160,12 @@ static fo::DbFile* LoadMapEdgeFileSub(char* mapName) {
|
||||
MapEdgeData[1].Release();
|
||||
MapEdgeData[2].Release();
|
||||
} else {
|
||||
MapEdgeData = new Edge[3];
|
||||
MapEdgeData = new EdgeBorder::Edge[3];
|
||||
}
|
||||
|
||||
long mapLevel = 0;
|
||||
do {
|
||||
Edge* edgeData = &MapEdgeData[mapLevel];
|
||||
EdgeBorder::Edge* edgeData = &MapEdgeData[mapLevel];
|
||||
|
||||
if (edgeVersion) {
|
||||
// load rectangle data (version 2)
|
||||
@@ -216,7 +196,7 @@ static fo::DbFile* LoadMapEdgeFileSub(char* mapName) {
|
||||
}
|
||||
if (getValue != mapLevel) break; // next level
|
||||
|
||||
Edge *edge = new Edge;
|
||||
EdgeBorder::Edge *edge = new EdgeBorder::Edge;
|
||||
edge->nextEdgeData = nullptr;
|
||||
edge->squareRect = edgeData->squareRect; // rect copy
|
||||
edgeData->nextEdgeData = edge;
|
||||
|
||||
@@ -11,8 +11,32 @@ namespace sfall
|
||||
|
||||
class EdgeBorder {
|
||||
public:
|
||||
static void init();
|
||||
struct Edge {
|
||||
POINT center; // x/y center of current map screen?
|
||||
RECT borderRect;
|
||||
RECT rect_2;
|
||||
RECT tileRect;
|
||||
RECT squareRect;
|
||||
long field_48; // unknown
|
||||
Edge* prevEdgeData; // unused (used in 3.06)
|
||||
Edge* nextEdgeData;
|
||||
|
||||
void Release() {
|
||||
Edge* edge = nextEdgeData;
|
||||
while (edge) {
|
||||
Edge* edgeNext = edge->nextEdgeData;
|
||||
delete edge;
|
||||
edge = edgeNext;
|
||||
};
|
||||
}
|
||||
|
||||
~Edge() {
|
||||
Release();
|
||||
}
|
||||
};
|
||||
|
||||
static void init();
|
||||
static Edge* CurrentMapEdge();
|
||||
static long GetCenterTile(long tile, long mapLevel);
|
||||
static long CheckBorder(long tile);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* sfall
|
||||
* Copyright (C) 2008-2021 The sfall team
|
||||
*
|
||||
*/
|
||||
|
||||
#include "..\..\main.h"
|
||||
#include "..\..\FalloutEngine\Fallout2.h"
|
||||
|
||||
#include "EdgeBorder.h"
|
||||
#include "ViewMap.h"
|
||||
|
||||
#include "EdgeClipping.h"
|
||||
|
||||
namespace sfall
|
||||
{
|
||||
|
||||
// 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 (inRect->right < srcRect->left ||
|
||||
inRect->left > srcRect->right ||
|
||||
inRect->bottom < srcRect->top ||
|
||||
inRect->top > srcRect->bottom)
|
||||
{
|
||||
return -1; // srcRect is not within the boundaries of the rectangle of inRect
|
||||
}
|
||||
|
||||
// sets the size so that the boundaries of outRect(srcRect) do not go beyond the boundaries of inRect?
|
||||
if (inRect->left > srcRect->left) outRect->left = inRect->left;
|
||||
if (inRect->right < srcRect->right) outRect->right = inRect->right;
|
||||
if (inRect->top > srcRect->top) outRect->top = inRect->top;
|
||||
if (inRect->bottom < srcRect->bottom) outRect->bottom = inRect->bottom;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Implementation from HRP by Mash
|
||||
static long sub_1000BA60(RECT* rect) {
|
||||
const long gridWidth = 200;
|
||||
const long gridLength = 200;
|
||||
|
||||
long cX, cY;
|
||||
ViewMap::GetTileCoordOffset(fo::var::getInt(FO_VAR_tile_center_tile), cX, cY);
|
||||
|
||||
long width = fo::var::getInt(FO_VAR_buf_width_2) >> 1;
|
||||
long height = fo::var::getInt(FO_VAR_buf_length_2) >> 1;
|
||||
|
||||
long v6 = (cX + width) - rect->left;
|
||||
long v7 = (cY + rect->top) - height;
|
||||
|
||||
long v8 = (cX + width) - rect->right;
|
||||
long v9 = (cY + rect->bottom) - height;
|
||||
|
||||
long x = v6;
|
||||
long y = v7;
|
||||
ViewMap::GetCoordFromOffset(x, y);
|
||||
|
||||
if (x < 0 || x >= gridLength || y < 0 || y >= gridWidth) return 1;
|
||||
|
||||
x = v8;
|
||||
y = v7;
|
||||
ViewMap::GetCoordFromOffset(x, y);
|
||||
|
||||
if (x < 0 || x >= gridLength || y < 0 || y >= gridWidth) return 1;
|
||||
|
||||
x = v6;
|
||||
y = v9;
|
||||
ViewMap::GetCoordFromOffset(x, y);
|
||||
|
||||
if (x < 0 || x >= gridLength || y < 0 || y >= gridWidth) return 1;
|
||||
|
||||
x = v8;
|
||||
y = v9;
|
||||
ViewMap::GetCoordFromOffset(x, y);
|
||||
|
||||
if (x >= 0 && x < gridLength && y >= 0 && y < gridWidth) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Implementation from HRP by Mash
|
||||
static long __fastcall rect_inside_bound_clip(RECT* srcRect, RECT* inRect, RECT* outRect) {
|
||||
if (rect_inside_bound(srcRect, inRect, outRect)) return -1;
|
||||
|
||||
if (ViewMap::EDGE_CLIPPING_ON) {
|
||||
long x, y;
|
||||
ViewMap::GetTileCoordOffset(fo::var::getInt(FO_VAR_tile_center_tile), x, y);
|
||||
|
||||
EdgeBorder::Edge* cEdge = EdgeBorder::CurrentMapEdge();
|
||||
|
||||
RECT visibleRect;
|
||||
visibleRect.left = x + ViewMap::mapModWidth - cEdge->rect_2.left;
|
||||
visibleRect.right = x + ViewMap::mapModWidth - cEdge->rect_2.right;
|
||||
|
||||
visibleRect.top = ViewMap::mapModHeight + cEdge->rect_2.top - y;
|
||||
visibleRect.bottom = ViewMap::mapModHeight + cEdge->rect_2.bottom - y;
|
||||
|
||||
if (sub_1000BA60(outRect)) {
|
||||
long height = (outRect->bottom - outRect->top) + 1;
|
||||
if (height > 0) {
|
||||
long mapWinWidth = fo::var::getInt(FO_VAR_buf_width_2);
|
||||
//long mapWinHeight = fo::var::getInt(FO_VAR_buf_length_2);
|
||||
BYTE* dst = (BYTE*)fo::var::getInt(FO_VAR_display_buf) + (outRect->top * mapWinWidth) + outRect->left;
|
||||
|
||||
long width = outRect->right - outRect->left + 1;
|
||||
long h = height;
|
||||
do {
|
||||
std::memset(dst, 0, width);
|
||||
dst += mapWinWidth;
|
||||
} while (--h);
|
||||
}
|
||||
}
|
||||
return rect_inside_bound(outRect, &visibleRect, outRect);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __declspec(naked) refresh_game_hook_rect_inside_bound() {
|
||||
__asm {
|
||||
push ecx;
|
||||
push ebx; // outRect
|
||||
mov ecx, eax;
|
||||
call rect_inside_bound_clip;
|
||||
pop ecx;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
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 mapWinWidth = fo::var::getInt(FO_VAR_buf_width_2);
|
||||
BYTE* dst = (BYTE*)fo::var::getInt(FO_VAR_display_buf) + (srcRect->top * mapWinWidth) + srcRect->left;
|
||||
|
||||
long width = (srcRect->right - srcRect->left) + 1;
|
||||
long h = height;
|
||||
do {
|
||||
std::memset(dst, 0, width);
|
||||
dst += mapWinWidth;
|
||||
} while (--h);
|
||||
}
|
||||
return rect_inside_bound_clip(srcRect, inRect, outRect);
|
||||
}
|
||||
|
||||
static void __declspec(naked) map_scroll_refresh_game_hook_rect_inside_bound() {
|
||||
__asm {
|
||||
push ecx;
|
||||
push ebx; // outRect
|
||||
mov ecx, eax;
|
||||
call rect_inside_bound_scroll_clip;
|
||||
pop ecx;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
void EdgeClipping::init() {
|
||||
HookCall(0x4B15F6, refresh_game_hook_rect_inside_bound);
|
||||
HookCall(0x483EF0, map_scroll_refresh_game_hook_rect_inside_bound);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* sfall
|
||||
* Copyright (C) 2008-2021 The sfall team
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace sfall
|
||||
{
|
||||
|
||||
class EdgeClipping {
|
||||
|
||||
public:
|
||||
static void init();
|
||||
};
|
||||
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "..\Init.h"
|
||||
#include "EdgeBorder.h"
|
||||
#include "EdgeClipping.h"
|
||||
|
||||
#include "ViewMap.h"
|
||||
|
||||
@@ -174,6 +175,7 @@ void ViewMap::init() {
|
||||
SafeWrite32(0x45C886, (DWORD)&obj_on_screen_rect); // replace rectangle in op_obj_on_screen_
|
||||
|
||||
EdgeBorder::init();
|
||||
EdgeClipping::init();
|
||||
|
||||
LoadGameHook::OnAfterGameInit() += []() {
|
||||
if (IGNORE_PLAYER_SCROLL_LIMITS) fo::var::setInt(FO_VAR_scroll_limiting_on) = 0;
|
||||
|
||||
@@ -315,6 +315,7 @@
|
||||
<ClInclude Include="HRP\MainMenu.h" />
|
||||
<ClInclude Include="HRP\SplashScreen.h" />
|
||||
<ClInclude Include="HRP\ViewMap\EdgeBorder.h" />
|
||||
<ClInclude Include="HRP\ViewMap\EdgeClipping.h" />
|
||||
<ClInclude Include="HRP\ViewMap\ViewMap.h" />
|
||||
<ClInclude Include="IniReader.h" />
|
||||
<ClInclude Include="Modules\CritterPoison.h" />
|
||||
@@ -440,6 +441,7 @@
|
||||
<ClCompile Include="HRP\MainMenu.cpp" />
|
||||
<ClCompile Include="HRP\SplashScreen.cpp" />
|
||||
<ClCompile Include="HRP\ViewMap\EdgeBorder.cpp" />
|
||||
<ClCompile Include="HRP\ViewMap\EdgeClipping.cpp" />
|
||||
<ClCompile Include="HRP\ViewMap\ViewMap.cpp" />
|
||||
<ClCompile Include="IniReader.cpp" />
|
||||
<ClCompile Include="Modules\CritterPoison.cpp" />
|
||||
|
||||
@@ -398,6 +398,9 @@
|
||||
<ClInclude Include="HRP\InterfaceBar.h">
|
||||
<Filter>HRP</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HRP\ViewMap\EdgeClipping.h">
|
||||
<Filter>HRP\ViewMap</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp" />
|
||||
@@ -731,6 +734,9 @@
|
||||
<ClCompile Include="HRP\InterfaceBar.cpp">
|
||||
<Filter>HRP</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HRP\ViewMap\EdgeClipping.cpp">
|
||||
<Filter>HRP\ViewMap</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="version.rc" />
|
||||
|
||||
Reference in New Issue
Block a user