Added map edge clipping (partial)

This commit is contained in:
NovaRain
2021-11-04 06:57:46 +08:00
parent 49cfe39038
commit eb7aca6595
7 changed files with 226 additions and 31 deletions
+10 -30
View File
@@ -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;
+25 -1
View File
@@ -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);
};
+163
View File
@@ -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);
}
}
+18
View File
@@ -0,0 +1,18 @@
/*
* sfall
* Copyright (C) 2008-2021 The sfall team
*
*/
#pragma once
namespace sfall
{
class EdgeClipping {
public:
static void init();
};
}
+2
View File
@@ -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;
+2
View File
@@ -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" />
+6
View File
@@ -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" />