Add setting for map edge behaviour, and how to display area outside map

wip-string
Jonathan G Rennison 5 months ago
parent 540cec2af5
commit 378a545dd4

@ -473,6 +473,11 @@ void FixSlopes()
}
}
}
extern bool CheckMapEdgesAreWater();
if (_settings_game.construction.map_edge_mode != 0 && !CheckMapEdgesAreWater()) {
_settings_game.construction.map_edge_mode = 0;
}
}
/**

@ -566,6 +566,12 @@ STR_CONFIG_SETTING_MIN_LAND_AREA_ZERO :Off
STR_CONFIG_SETTING_FLOOD_FROM_EDGES :Water floods from map edges: {STRING2}
STR_CONFIG_SETTING_FLOOD_FROM_EDGES_HELPTEXT :Whether water floods into edge tiles at sea level from the map edge.
STR_CONFIG_SETTING_MAP_EDGE_MODE :Map edge behaviour: {STRING2}
STR_CONFIG_SETTING_MAP_EDGE_MODE_HELPTEXT :Whether raising the map edges above sea-level is allowed, and how the void area outside the map is displayed
STR_CONFIG_SETTING_MAP_EDGE_MODE_DEFAULT :Default
STR_CONFIG_SETTING_MAP_EDGE_MODE_SEA_LEVEL :Map edges restricted to sea level
STR_CONFIG_SETTING_MAP_EDGE_MODE_SEA_LEVEL_OUTSIDE_WATER :Map edges restricted to sea level, outside map shown as water
STR_CONFIG_SETTING_TREES_AROUND_SNOWLINE :Adjusted arctic tree placement: {STRING2}
STR_CONFIG_SETTING_TREES_AROUND_SNOWLINE_HELPTEXT :Adjust placement of trees around snow line in artic climate. Trees thin out above snowline. Trees are a mix of arctic and temperate just below snowline. Below that trees are temperate.
STR_CONFIG_SETTING_TREES_AROUND_SNOWLINE_RANGE :Arctic tree range: {STRING2}

@ -1462,6 +1462,15 @@ static void ViewportMapLandscapeModeChanged(int32 new_value)
MarkAllViewportMapLandscapesDirty();
}
static void MarkAllViewportsDirty(int32 new_value)
{
extern void MarkAllViewportMapLandscapesDirty();
MarkAllViewportMapLandscapesDirty();
extern void MarkWholeNonMapViewportsDirty();
MarkWholeNonMapViewportsDirty();
}
static void UpdateLinkgraphColours(int32 new_value)
{
BuildLinkStatsLegend();
@ -1655,6 +1664,35 @@ static void UpdateFreeformEdges(int32 new_value)
MarkWholeScreenDirty();
}
bool CheckMapEdgesAreWater()
{
auto check_tile = [&](uint x, uint y) -> bool {
int h = 0;
Slope slope = GetTilePixelSlopeOutsideMap(x, y, &h);
return slope == SLOPE_FLAT && h == 0;
};
for (uint x = 0; x <= MapMaxX(); x++) {
if (!check_tile(x, 0) || !check_tile(x, MapMaxY())) return false;
}
for (uint y = 1; y < MapMaxY(); y++) {
if (!check_tile(0, y) || !check_tile(MapMaxX(), y)) return false;
}
return true;
}
static bool CheckMapEdgeMode(int32 &new_value)
{
if (_game_mode == GM_MENU || !_settings_game.construction.freeform_edges || new_value == 0) return true;
if (!CheckMapEdgesAreWater()) {
ShowErrorMessage(STR_CONFIG_SETTING_EDGES_NOT_WATER, INVALID_STRING_ID, WL_ERROR);
return false;
}
return true;
}
/**
* Changing the setting "allow multiple NewGRF sets" is not allowed
* if there are vehicles.

@ -2414,6 +2414,7 @@ static SettingsContainer &GetSettingsTree()
}
environment->Add(new SettingEntry("construction.flood_from_edges"));
environment->Add(new SettingEntry("construction.map_edge_mode"));
environment->Add(new SettingEntry("economy.day_length_factor"));
environment->Add(new SettingEntry("station.modified_catchment"));
environment->Add(new SettingEntry("station.catchment_increase"));

@ -508,6 +508,7 @@ struct ConstructionSettings {
uint8 industry_platform; ///< the amount of flat land around an industry
bool freeform_edges; ///< allow terraforming the tiles at the map edges
bool flood_from_edges; ///< whether water floods from map edges
uint8 map_edge_mode; ///< map edge mode
uint8 extra_tree_placement; ///< (dis)allow building extra trees in-game
uint8 trees_around_snow_line_range; ///< range around snowline for mixed and arctic forest.
bool trees_around_snow_line_enabled; ///< enable mixed and arctic forest around snowline, and no trees above snowline

@ -3544,6 +3544,9 @@ static SaveOrLoadResult DoLoad(LoadFilter *reader, bool load_check)
* No pools are loaded. References are not possible, and thus do not need resolving. */
SlLoadCheckChunks();
} else {
/* Unconditionally default this to 0 when loading a savegame */
_settings_game.construction.map_edge_mode = 0;
/* Load chunks and resolve references */
SlLoadChunks();
SlFixPointers();
@ -3676,6 +3679,9 @@ SaveOrLoadResult SaveOrLoad(const std::string &filename, SaveLoadOperation fop,
InitializeGame(256, 256, true, true); // set a mapsize of 256x256 for TTDPatch games or it might get confused
/* Unconditionally default this to 0 when loading a savegame */
_settings_game.construction.map_edge_mode = 0;
/* TTD/TTO savegames have no NewGRFs, TTDP savegame have them
* and if so a new NewGRF list will be made in LoadOldSaveGame.
* Note: this is done here because AfterLoadGame is also called

@ -13,8 +13,10 @@
static bool CheckMaxHeightLevel(int32_t &new_value);
static bool CheckFreeformEdges(int32_t &new_value);
static void UpdateFreeformEdges(int32_t new_value);
static bool CheckMapEdgeMode(int32_t &new_value);
static void ClimateThresholdModeChanged(int32 new_value);
static void PublicRoadsSettingChange(int32 new_value);
static void MarkAllViewportsDirty(int32 new_value);
static bool AllowRoadStopsUnderBridgesSettingGUI(SettingOnGuiCtrlData &data);
static bool TreePlacerSettingGUI(SettingOnGuiCtrlData &data);
@ -929,6 +931,20 @@ strhelp = STR_CONFIG_SETTING_FLOOD_FROM_EDGES_HELPTEXT
cat = SC_ADVANCED
patxname = ""construction.flood_from_edges""
[SDT_VAR]
var = construction.map_edge_mode
type = SLE_UINT8
flags = SF_GUI_DROPDOWN | SF_PATCH
def = 0
min = 0
max = 2
str = STR_CONFIG_SETTING_MAP_EDGE_MODE
strhelp = STR_CONFIG_SETTING_MAP_EDGE_MODE_HELPTEXT
strval = STR_CONFIG_SETTING_MAP_EDGE_MODE_DEFAULT
pre_cb = CheckMapEdgeMode
post_cb = MarkAllViewportsDirty
cat = SC_ADVANCED
[SDT_VAR]
var = construction.extra_tree_placement
type = SLE_UINT8

@ -227,7 +227,15 @@ CommandCost CmdTerraformLand(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
assert(t < MapSize());
/* MP_VOID tiles can be terraformed but as tunnels and bridges
* cannot go under / over these tiles they don't need checking. */
if (IsTileType(t, MP_VOID)) continue;
if (IsTileType(t, MP_VOID)) {
if (_settings_game.construction.map_edge_mode != 0) {
CommandCost err(STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP);
err.SetTile(t);
return err;
} else {
continue;
}
}
/* Find new heights of tile corners */
int z_N = TerraformGetHeightOfTile(&ts, t + TileDiffXY(0, 0));

@ -1752,6 +1752,12 @@ static void ViewportAddLandscape()
/* Outside of map. If we are on the north border of the map, there may still be a bridge visible,
* so we need to loop over more rows to possibly find one. */
if ((tilecoord.x <= 0 || tilecoord.y <= 0) && min_visible_height < potential_bridge_height + MAX_TILE_EXTENT_TOP) last_row = false;
if (_settings_game.construction.map_edge_mode == 2 && _cur_ti.tileh == SLOPE_FLAT && _cur_ti.z == 0 && min_visible_height <= 0) {
last_row = false;
AddTileSpriteToDraw(SPR_FLAT_WATER_TILE, PAL_NONE, _cur_ti.x, _cur_ti.y, _cur_ti.z);
continue;
}
}
if (tile_visible) {
@ -3255,34 +3261,39 @@ static inline TileIndex ViewportMapGetMostSignificantTileType(const Viewport * c
return result;
}
static uint32 ViewportMapVoidColour()
{
return (_settings_game.construction.map_edge_mode == 2) ? _vp_map_water_colour[SLOPE_FLAT] : 0;
}
/** Get the colour of a tile, can be 32bpp RGB or 8bpp palette index. */
template <bool is_32bpp, bool show_slope>
uint32 ViewportMapGetColour(const Viewport * const vp, int x, int y, const uint colour_index)
{
if (x >= static_cast<int>(MapMaxX() * TILE_SIZE) || y >= static_cast<int>(MapMaxY() * TILE_SIZE)) return 0;
if (x >= static_cast<int>(MapMaxX() * TILE_SIZE) || y >= static_cast<int>(MapMaxY() * TILE_SIZE)) return ViewportMapVoidColour();
/* Very approximative but fast way to get the tile when taking Z into account. */
const TileIndex tile_tmp = TileVirtXY(std::max(0, x), std::max(0, y));
const int z = TileHeight(tile_tmp) * 4;
if (x + z < 0 || y + z < 0 || static_cast<uint>(x + z) >= MapSizeX() << 4) {
/* Wrapping of tile X coordinate causes a graphic glitch below south west border. */
return 0;
return ViewportMapVoidColour();
}
TileIndex tile = TileVirtXY(x + z, y + z);
if (tile >= MapSize()) return 0;
if (tile >= MapSize()) return ViewportMapVoidColour();
const int z2 = TileHeight(tile) * 4;
if (unlikely(z2 != z)) {
const int approx_z = (z + z2) / 2;
if (x + approx_z < 0 || y + approx_z < 0 || static_cast<uint>(x + approx_z) >= MapSizeX() << 4) {
/* Wrapping of tile X coordinate causes a graphic glitch below south west border. */
return 0;
return ViewportMapVoidColour();
}
tile = TileVirtXY(x + approx_z, y + approx_z);
if (tile >= MapSize()) return 0;
if (tile >= MapSize()) return ViewportMapVoidColour();
}
TileType tile_type = MP_VOID;
tile = ViewportMapGetMostSignificantTileType(vp, tile, &tile_type);
if (tile_type == MP_VOID) return 0;
if (tile_type == MP_VOID) return ViewportMapVoidColour();
/* Return the colours. */
switch (vp->map_type) {

Loading…
Cancel
Save