mirror of
https://github.com/fallout2-ce/fallout2-ce.git
synced 2026-07-27 16:47:11 -07:00
Compare commits
18
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8751a2551b | ||
|
|
2bf0aecff3 | ||
|
|
2b0c1deebf | ||
|
|
1aa36af8b4 | ||
|
|
d672346a64 | ||
|
|
20e8ff3725 | ||
|
|
811d5de9ac | ||
|
|
14300f3f97 | ||
|
|
3a3675d846 | ||
|
|
036f63ffa8 | ||
|
|
60bf86231a | ||
|
|
608d758864 | ||
|
|
65922b8dd2 | ||
|
|
7c1c9d287e | ||
|
|
9baea460c9 | ||
|
|
9b182e4c25 | ||
|
|
9b490e9627 | ||
|
|
f5d976d199 |
@@ -3153,7 +3153,7 @@ static void opFloatMessage(Program* program)
|
||||
color = _colorTable[31744];
|
||||
backgroundColor = _colorTable[0];
|
||||
font = 103;
|
||||
tileSetCenter(gDude->tile, TILE_SET_CENTER_REFRESH_WINDOW);
|
||||
tileSetCenter(gDude->tile, TILE_SET_CENTER_REFRESH_WINDOW | TILE_SET_CENTER_FLAG_ALLOW_HIRES_TWEAK);
|
||||
break;
|
||||
case FLOATING_MESSAGE_TYPE_NORMAL:
|
||||
case FLOATING_MESSAGE_TYPE_YELLOW:
|
||||
|
||||
+2
-2
@@ -932,7 +932,7 @@ static int mapLoad(File* stream)
|
||||
}
|
||||
|
||||
error = "Error setting tile center";
|
||||
if (tileSetCenter(gEnteringTile, TILE_SET_CENTER_FLAG_IGNORE_SCROLL_RESTRICTIONS) != 0) {
|
||||
if (tileSetCenter(gEnteringTile, TILE_SET_CENTER_FLAG_IGNORE_SCROLL_RESTRICTIONS | TILE_SET_CENTER_FLAG_ALLOW_HIRES_TWEAK) != 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -1293,7 +1293,7 @@ int mapHandleTransition()
|
||||
objectSetRotation(gDude, gMapTransition.rotation, nullptr);
|
||||
}
|
||||
|
||||
if (tileSetCenter(gDude->tile, TILE_SET_CENTER_REFRESH_WINDOW) == -1) {
|
||||
if (tileSetCenter(gDude->tile, TILE_SET_CENTER_REFRESH_WINDOW | TILE_SET_CENTER_FLAG_ALLOW_HIRES_TWEAK) == -1) {
|
||||
debugPrint("\nError: map: attempt to center out-of-bounds!");
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -3723,7 +3723,7 @@ int _obj_load_dude(File* stream)
|
||||
return -1;
|
||||
}
|
||||
|
||||
tileSetCenter(tile, TILE_SET_CENTER_REFRESH_WINDOW | TILE_SET_CENTER_FLAG_IGNORE_SCROLL_RESTRICTIONS);
|
||||
tileSetCenter(tile, TILE_SET_CENTER_REFRESH_WINDOW | TILE_SET_CENTER_FLAG_IGNORE_SCROLL_RESTRICTIONS | TILE_SET_CENTER_FLAG_ALLOW_HIRES_TWEAK);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
+11
@@ -568,6 +568,10 @@ int tileSetCenter(int tile, int flags)
|
||||
if (_obj_scroll_blocking_at(tile, gElevation) == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!tile_hires_stencil_allows_scrolling_to_tile(tile, gCenterTile, gElevation, gTileWindowWidth, gTileWindowHeight)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -604,6 +608,13 @@ int tileSetCenter(int tile, int flags)
|
||||
|
||||
tile_hires_stencil_on_center_tile_or_elevation_change();
|
||||
|
||||
if (flags & TILE_SET_CENTER_FLAG_ALLOW_HIRES_TWEAK) {
|
||||
auto tweaked_center_tile = tile_hires_stencil_get_tweaked_center_tile(gCenterTile, gElevation, gTileWindowWidth, gTileWindowHeight);
|
||||
if (tileIsValid(tweaked_center_tile) && tweaked_center_tile != gCenterTile) {
|
||||
return tileSetCenter(tweaked_center_tile, flags & ~TILE_SET_CENTER_FLAG_ALLOW_HIRES_TWEAK);
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & TILE_SET_CENTER_REFRESH_WINDOW) != 0) {
|
||||
// NOTE: Uninline.
|
||||
tileWindowRefresh();
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace fallout {
|
||||
|
||||
#define TILE_SET_CENTER_REFRESH_WINDOW 0x01
|
||||
#define TILE_SET_CENTER_FLAG_IGNORE_SCROLL_RESTRICTIONS 0x02
|
||||
#define TILE_SET_CENTER_FLAG_ALLOW_HIRES_TWEAK 0x04
|
||||
|
||||
typedef void(TileWindowRefreshProc)(Rect* rect);
|
||||
typedef void(TileWindowRefreshElevationProc)(Rect* rect, int elevation);
|
||||
|
||||
+348
-49
@@ -25,6 +25,15 @@ namespace fallout {
|
||||
/** This holds hex tiles which can be center tile */
|
||||
static bool visited_tiles[ELEVATION_COUNT][HEX_GRID_SIZE];
|
||||
|
||||
struct StencilScreenLimits {
|
||||
int minX;
|
||||
int maxX;
|
||||
int minY;
|
||||
int maxY;
|
||||
bool initialized;
|
||||
};
|
||||
static struct StencilScreenLimits screen_xy_limits[ELEVATION_COUNT];
|
||||
|
||||
static constexpr int pixels_per_horizontal_move = 32;
|
||||
static constexpr int pixels_per_vertical_move = 24;
|
||||
|
||||
@@ -69,11 +78,13 @@ static bool gIsTileHiresStencilEnabled = true;
|
||||
static void clean_cache()
|
||||
{
|
||||
memset(visited_tiles, 0, sizeof(visited_tiles));
|
||||
memset(screen_xy_limits, 0, sizeof(screen_xy_limits));
|
||||
memset(visible_squares, 0, sizeof(visible_squares));
|
||||
}
|
||||
static void clean_cache_for_elevation(int elevation)
|
||||
{
|
||||
memset(visited_tiles[elevation], 0, sizeof(visited_tiles[elevation]));
|
||||
memset(&screen_xy_limits[elevation], 0, sizeof(screen_xy_limits[elevation]));
|
||||
memset(visible_squares[elevation], 0, sizeof(visible_squares[elevation]));
|
||||
}
|
||||
|
||||
@@ -205,6 +216,95 @@ static void mark_screen_tiles_around_as_visible(int center_tile, const Point& sc
|
||||
}
|
||||
}
|
||||
|
||||
static void update_screen_xy_limits(int tileScreenX, int tileScreenY, const Point& screen_diff, int elevation)
|
||||
{
|
||||
auto& limits = screen_xy_limits[elevation];
|
||||
auto candidateMinX = tileScreenX - screen_view_width / 2 - screen_diff.x;
|
||||
auto candidateMaxX = tileScreenX + screen_view_width / 2 - screen_diff.x;
|
||||
auto candidateMinY = tileScreenY - screen_view_height / 2 - screen_diff.y;
|
||||
auto candidateMaxY = tileScreenY + screen_view_height / 2 - screen_diff.y;
|
||||
|
||||
if (!limits.initialized) {
|
||||
limits.minX = candidateMinX;
|
||||
limits.maxX = candidateMaxX;
|
||||
limits.minY = candidateMinY;
|
||||
limits.maxY = candidateMaxY;
|
||||
limits.initialized = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (candidateMinX < limits.minX) {
|
||||
limits.minX = candidateMinX;
|
||||
}
|
||||
if (candidateMaxX > limits.maxX) {
|
||||
limits.maxX = candidateMaxX;
|
||||
}
|
||||
if (candidateMinY < limits.minY) {
|
||||
limits.minY = candidateMinY;
|
||||
}
|
||||
if (candidateMaxY > limits.maxY) {
|
||||
limits.maxY = candidateMaxY;
|
||||
}
|
||||
}
|
||||
|
||||
struct TileScrollNeighbors {
|
||||
int left;
|
||||
int right;
|
||||
int up;
|
||||
int down;
|
||||
};
|
||||
|
||||
static struct TileScrollNeighbors get_tile_scroll_neighbors(int tileScreenX, int tileScreenY)
|
||||
{
|
||||
// tile size is 32 x 18
|
||||
//
|
||||
// / \ ^
|
||||
// | | | 18
|
||||
// \ / v
|
||||
//
|
||||
// <-32->
|
||||
//
|
||||
// Scrolling left-right changes x by 32
|
||||
// But scrolling top-bottom changes y by 24
|
||||
//
|
||||
//
|
||||
// / \
|
||||
// | | <----- tiles on vertical change, 24 px
|
||||
// / \ / \ |
|
||||
// | | | <------ | ----- tiles on horizontal change, 32 px
|
||||
// \ / \ / |
|
||||
// | | <--/
|
||||
// \ /
|
||||
//
|
||||
|
||||
constexpr int tile_center_offset_x = 16;
|
||||
constexpr int tile_center_offset_y = 8;
|
||||
|
||||
struct TileScrollNeighbors r;
|
||||
|
||||
r.left = tileFromScreenXY(
|
||||
tileScreenX - pixels_per_horizontal_move + tile_center_offset_x,
|
||||
tileScreenY + tile_center_offset_y,
|
||||
true);
|
||||
|
||||
r.right = tileFromScreenXY(
|
||||
tileScreenX + pixels_per_horizontal_move + tile_center_offset_x,
|
||||
tileScreenY + tile_center_offset_y,
|
||||
true);
|
||||
|
||||
r.up = tileFromScreenXY(
|
||||
tileScreenX + tile_center_offset_x,
|
||||
tileScreenY - pixels_per_vertical_move + tile_center_offset_y,
|
||||
true);
|
||||
|
||||
r.down = tileFromScreenXY(
|
||||
tileScreenX + tile_center_offset_x,
|
||||
tileScreenY + pixels_per_vertical_move + tile_center_offset_y,
|
||||
true);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void tile_hires_stencil_on_center_tile_or_elevation_change()
|
||||
{
|
||||
if (!gIsTileHiresStencilEnabled) {
|
||||
@@ -216,15 +316,9 @@ void tile_hires_stencil_on_center_tile_or_elevation_change()
|
||||
};
|
||||
|
||||
if (visited_tiles[gElevation][gCenterTile]) {
|
||||
debugPrint("tile_hires_stencil_on_center_tile_or_elevation_change tile was visited gElevation=%i gCenterTile=%i so doing nothing\n",
|
||||
gElevation, gCenterTile);
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
debugPrint("tile_hires_stencil_on_center_tile_or_elevation_change non-visited tile gElevation=%i gCenterTile=%i\n",
|
||||
gElevation, gCenterTile);
|
||||
|
||||
clean_cache_for_elevation(gElevation);
|
||||
|
||||
struct TileToVisit {
|
||||
@@ -245,14 +339,16 @@ void tile_hires_stencil_on_center_tile_or_elevation_change()
|
||||
auto tileInfo = tiles_to_visit.back();
|
||||
tiles_to_visit.pop_back();
|
||||
|
||||
// Ensure tile index is within valid bounds before any array access.
|
||||
if (tileInfo.tile < 0 || tileInfo.tile >= HEX_GRID_SIZE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (visited_tiles[gElevation][tileInfo.tile]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tileInfo.tile != gCenterTile) [[unlikely]] {
|
||||
if (tileInfo.tile < 0 || tileInfo.tile >= HEX_GRID_SIZE) {
|
||||
continue;
|
||||
}
|
||||
if (_obj_scroll_blocking_at(tileInfo.tile, gElevation) == 0) {
|
||||
continue;
|
||||
}
|
||||
@@ -274,53 +370,19 @@ void tile_hires_stencil_on_center_tile_or_elevation_change()
|
||||
int tileScreenY;
|
||||
tileToScreenXY(tileInfo.tile, &tileScreenX, &tileScreenY);
|
||||
|
||||
// tile size is 32 x 18
|
||||
//
|
||||
// / \ ^
|
||||
// | | | 18
|
||||
// \ / v
|
||||
//
|
||||
// <-32->
|
||||
//
|
||||
// Scrolling left-right changes x by 32
|
||||
// But scrolling top-bottom changes y by 24
|
||||
//
|
||||
//
|
||||
// / \
|
||||
// | | <----- tiles on vertical change, 24 px
|
||||
// / \ / \ |
|
||||
// | | | <------ | ----- tiles on horizontal change, 32 px
|
||||
// \ / \ / |
|
||||
// | | <--/
|
||||
// \ /
|
||||
//
|
||||
update_screen_xy_limits(tileScreenX, tileScreenY, screen_diff, gElevation);
|
||||
|
||||
constexpr int tile_center_offset_x = 16;
|
||||
constexpr int tile_center_offset_y = 8;
|
||||
auto neighbors = get_tile_scroll_neighbors(tileScreenX, tileScreenY);
|
||||
|
||||
tiles_to_visit.push_back({ tileFromScreenXY(
|
||||
tileScreenX - pixels_per_horizontal_move + tile_center_offset_x,
|
||||
tileScreenY + tile_center_offset_y,
|
||||
true),
|
||||
tiles_to_visit.push_back({ neighbors.left,
|
||||
MarkOnlyPart::LEFT });
|
||||
tiles_to_visit.push_back({ tileFromScreenXY(
|
||||
tileScreenX + pixels_per_horizontal_move + tile_center_offset_x,
|
||||
tileScreenY + tile_center_offset_y,
|
||||
true),
|
||||
tiles_to_visit.push_back({ neighbors.right,
|
||||
MarkOnlyPart::RIGHT });
|
||||
tiles_to_visit.push_back({ tileFromScreenXY(
|
||||
tileScreenX + tile_center_offset_x,
|
||||
tileScreenY - pixels_per_vertical_move + tile_center_offset_y,
|
||||
true),
|
||||
tiles_to_visit.push_back({ neighbors.up,
|
||||
MarkOnlyPart::UP });
|
||||
tiles_to_visit.push_back({ tileFromScreenXY(
|
||||
tileScreenX + tile_center_offset_x,
|
||||
tileScreenY + pixels_per_vertical_move + tile_center_offset_y,
|
||||
true),
|
||||
tiles_to_visit.push_back({ neighbors.down,
|
||||
MarkOnlyPart::DOWN });
|
||||
}
|
||||
|
||||
debugPrint("tile_hires_stencil_on_center_tile_or_elevation_change visited_tiles_count=%i\n", visited_tiles_count);
|
||||
}
|
||||
|
||||
void tile_hires_stencil_draw(Rect* rect, unsigned char* buffer, int windowWidth, int windowHeight)
|
||||
@@ -403,6 +465,243 @@ void tile_hires_stencil_draw(Rect* rect, unsigned char* buffer, int windowWidth,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Even when we can scroll to the tile according to scrollblocker tiles,
|
||||
* we also want to disallow scrolling on big resolutions if there is nothing to show there
|
||||
*/
|
||||
bool tile_hires_stencil_allows_scrolling_to_tile(int newCenterTile, int currentCenterTile, int elevation, int windowWidth, int windowHeight)
|
||||
{
|
||||
if (!gIsTileHiresStencilEnabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!gTileBorderInitialized) {
|
||||
return true;
|
||||
};
|
||||
|
||||
auto& limits = screen_xy_limits[elevation];
|
||||
if (!limits.initialized) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int currentTileScreenX;
|
||||
int currentTileScreenY;
|
||||
tileToScreenXY(currentCenterTile, ¤tTileScreenX, ¤tTileScreenY);
|
||||
|
||||
int newTileScreenX;
|
||||
int newTileScreenY;
|
||||
tileToScreenXY(newCenterTile, &newTileScreenX, &newTileScreenY);
|
||||
|
||||
auto xDiff = newTileScreenX - currentTileScreenX;
|
||||
auto yDiff = newTileScreenY - currentTileScreenY;
|
||||
|
||||
auto screen_diff = get_screen_diff();
|
||||
|
||||
auto newScreenMinX = newTileScreenX - windowWidth / 2 - screen_diff.x;
|
||||
auto newScreenMaxX = newTileScreenX + windowWidth / 2 - screen_diff.x;
|
||||
auto newScreenMinY = newTileScreenY - windowHeight / 2 - screen_diff.y;
|
||||
auto newScreenMaxY = newTileScreenY + windowHeight / 2 - screen_diff.y;
|
||||
|
||||
if (xDiff < 0) { // Moving left
|
||||
if (newScreenMinX >= limits.minX) {
|
||||
// Scrolling left when there is still something to show is always allowed
|
||||
// [------------------------] <- possible visible area border (limits.maxX and limits.minX)
|
||||
// ( x ) <- hi-res screen with center tile (newScreenMinX, newScreenMaxX)
|
||||
} else if (newScreenMaxX <= limits.maxX) {
|
||||
// Disallow if map is bigger than screen
|
||||
// [------------------------] <- possible visible area border (limits.maxX and limits.minX)
|
||||
// ( x ) <- this clearly disallow
|
||||
return false;
|
||||
} else {
|
||||
// Now we have two cases: when moving left will make map to be more in the center or not
|
||||
// [-----------] <- possible visible area border (limits.maxX and limits.minX)
|
||||
// ( x ) <- allow this, it will move map to the center
|
||||
// ( x ) <- disallow this, it will move map from the center
|
||||
auto leftDiff = limits.minX - newScreenMinX;
|
||||
auto rightDiff = newScreenMaxX - limits.maxX;
|
||||
if (leftDiff > rightDiff) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (xDiff > 0) {
|
||||
if (newScreenMaxX <= limits.maxX) {
|
||||
// Allow
|
||||
} else if (newScreenMinX > limits.minX) {
|
||||
return false;
|
||||
} else {
|
||||
auto leftDiff = limits.minX - newScreenMinX;
|
||||
auto rightDiff = newScreenMaxX - limits.maxX;
|
||||
if (leftDiff < rightDiff) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (yDiff < 0) { // Moving up
|
||||
if (newScreenMinY >= limits.minY) {
|
||||
// Scrolling up when there is still something to show is always allowed
|
||||
} else if (newScreenMaxY <= limits.maxY) {
|
||||
// Disallow if map is taller than screen
|
||||
return false;
|
||||
} else {
|
||||
// Allow only if moving up makes the visible area more centered vertically
|
||||
auto topDiff = limits.minY - newScreenMinY;
|
||||
auto bottomDiff = newScreenMaxY - limits.maxY;
|
||||
if (topDiff > bottomDiff) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (yDiff > 0) { // Moving down
|
||||
if (newScreenMaxY <= limits.maxY) {
|
||||
// Allow
|
||||
} else if (newScreenMinY > limits.minY) {
|
||||
return false;
|
||||
} else {
|
||||
auto topDiff = limits.minY - newScreenMinY;
|
||||
auto bottomDiff = newScreenMaxY - limits.maxY;
|
||||
if (topDiff < bottomDiff) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* In case of hi-res we automatically scroll a little bit until we get overlay hidden
|
||||
*/
|
||||
int tile_hires_stencil_get_tweaked_center_tile(int initialCenterTile, int elevation, int windowWidth, int windowHeight)
|
||||
{
|
||||
if (!gIsTileHiresStencilEnabled || !gTileBorderInitialized) {
|
||||
return initialCenterTile;
|
||||
}
|
||||
|
||||
auto& limits = screen_xy_limits[elevation];
|
||||
if (limits.maxX == 0 && limits.maxY == 0) {
|
||||
return initialCenterTile;
|
||||
}
|
||||
|
||||
auto candidateTile = initialCenterTile;
|
||||
|
||||
int loopBreaker = 1000; // Just in case, to avoid infinite loop
|
||||
|
||||
for (; loopBreaker > 0; loopBreaker--) {
|
||||
int candidateTileScreenX;
|
||||
int candidateTileScreenY;
|
||||
tileToScreenXY(candidateTile, &candidateTileScreenX, &candidateTileScreenY);
|
||||
|
||||
auto screen_diff = get_screen_diff();
|
||||
auto candidateScreenMinX = candidateTileScreenX - windowWidth / 2 - screen_diff.x;
|
||||
auto candidateScreenMaxX = candidateTileScreenX + windowWidth / 2 - screen_diff.x;
|
||||
auto candidateScreenMinY = candidateTileScreenY - windowHeight / 2 - screen_diff.y;
|
||||
auto candidateScreenMaxY = candidateTileScreenY + windowHeight / 2 - screen_diff.y;
|
||||
|
||||
auto leftIsOutOfLimits = candidateScreenMinX < limits.minX;
|
||||
auto rightIsOutOfLimits = candidateScreenMaxX > limits.maxX;
|
||||
auto upIsOutOfLimits = candidateScreenMinY < limits.minY;
|
||||
auto downIsOutOfLimits = candidateScreenMaxY > limits.maxY;
|
||||
|
||||
auto neighbors = get_tile_scroll_neighbors(candidateTileScreenX, candidateTileScreenY);
|
||||
|
||||
auto canScrollLeft = tile_hires_stencil_allows_scrolling_to_tile(
|
||||
neighbors.left, candidateTile, elevation, windowWidth, windowHeight)
|
||||
&& _obj_scroll_blocking_at(neighbors.left, elevation) != 0;
|
||||
|
||||
auto canScrollRight = tile_hires_stencil_allows_scrolling_to_tile(
|
||||
neighbors.right, candidateTile, elevation, windowWidth, windowHeight)
|
||||
&& _obj_scroll_blocking_at(neighbors.right, elevation) != 0;
|
||||
|
||||
auto canScrollUp = tile_hires_stencil_allows_scrolling_to_tile(
|
||||
neighbors.up, candidateTile, elevation, windowWidth, windowHeight)
|
||||
&& _obj_scroll_blocking_at(neighbors.up, elevation) != 0;
|
||||
|
||||
auto canScrollDown = tile_hires_stencil_allows_scrolling_to_tile(
|
||||
neighbors.down, candidateTile, elevation, windowWidth, windowHeight)
|
||||
&& _obj_scroll_blocking_at(neighbors.down, elevation) != 0;
|
||||
|
||||
if (leftIsOutOfLimits && canScrollRight) {
|
||||
candidateTile = neighbors.right;
|
||||
} else if (rightIsOutOfLimits && canScrollLeft) {
|
||||
candidateTile = neighbors.left;
|
||||
} else if (upIsOutOfLimits && canScrollDown) {
|
||||
candidateTile = neighbors.down;
|
||||
} else if (downIsOutOfLimits && canScrollUp) {
|
||||
candidateTile = neighbors.up;
|
||||
} else {
|
||||
return candidateTile;
|
||||
}
|
||||
};
|
||||
|
||||
debugPrint("Warning! tile_hires_stencil_get_tweaked_center_tile: loop breaker reached, something went wrong\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Scrolling in Fallout 2 is controlled by special scrollblocker tiles.
|
||||
|
||||
The game has state variable "gCenterTile" which defines current window scroll position.
|
||||
When player scrolls, game checks if there is a scrollblocker tile in the direction of scroll
|
||||
and if there is, it does not change gCenterTile and does not scroll.
|
||||
|
||||
So maps place scrollblocker tiles not exactly on the edge but on the half of default screen size (640x480).
|
||||
|
||||
|
||||
Example (x = current gCenterTile; + = scrollblocker tile on map):
|
||||
┌───────────────────┐───────────────────┐
|
||||
│ │ │ <- this is the border of possible visible area
|
||||
│ │ │ (usually also border of the map)
|
||||
│ +++++++++++++++++++++++++ │
|
||||
│ +x │ + │
|
||||
│ + │ + <-------- Scrollblocker tile are inside
|
||||
│ + │ + │
|
||||
│ + │ + │
|
||||
└──640x480─window───┘ + │
|
||||
│ + + │
|
||||
│ + + │
|
||||
│ + + │
|
||||
│ + + │
|
||||
│ + + │
|
||||
│ +++++++++++++++++++++++++ │
|
||||
│ │
|
||||
│ │
|
||||
└─────1920x1080─window──────────────────┘
|
||||
<-------> this distance is half of default screen width, i.e. 640/2=320 pixels
|
||||
|
||||
|
||||
But not every map is rectangular.
|
||||
So on every map or elevation change we do a search for all possible accessible
|
||||
center tile values starting from the current one, and for each such possible
|
||||
center tile we mark the 640x380 tile viewport area around as visible (within the
|
||||
overall 640x480 screen). The rest gets covered by a black overlay.
|
||||
|
||||
┌──────────────────┐
|
||||
│ │
|
||||
│ │
|
||||
│ ++++++++++ │
|
||||
│ + + │
|
||||
│ + + │
|
||||
│ + + └─────────────────────────────┐
|
||||
│ + + │
|
||||
│ + + ┌───────────┐ │
|
||||
│ + ++++++│+++++++++++│++++++++++++ │
|
||||
│ + ┌──────────│──┐ │ ┌────────────┐
|
||||
│ + │ │ │ x │ │ + │
|
||||
│ + │ │ │ │ │ + │
|
||||
│ + │ x │ │ │ │ x+ │
|
||||
│ ++++│++++++++++└───────────┘+++│++++++++ │
|
||||
│ │ │ │ │
|
||||
│ └─────────────┘ │ │
|
||||
└───────────────────────────────────└────────────┘
|
||||
|
||||
|
||||
*/
|
||||
void tile_hires_stencil_init()
|
||||
{
|
||||
configGetBool(&gSfallConfig, SFALL_CONFIG_MAIN_KEY, SFALL_CONFIG_ENABLE_HIRES_STENCIL, &gIsTileHiresStencilEnabled);
|
||||
|
||||
@@ -11,6 +11,9 @@ void tile_hires_stencil_on_center_tile_or_elevation_change();
|
||||
|
||||
void tile_hires_stencil_draw(Rect* rect, unsigned char* buffer, int windowWidth, int windowHeight);
|
||||
|
||||
bool tile_hires_stencil_allows_scrolling_to_tile(int newCenterTile, int currentCenterTile, int elevation, int windowWidth, int windowHeight);
|
||||
|
||||
int tile_hires_stencil_get_tweaked_center_tile(int initialCenterTile, int elevation, int windowWidth, int windowHeight);
|
||||
} // namespace fallout
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user