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

wip-string
Jonathan G Rennison 6 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 :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_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 :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_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} STR_CONFIG_SETTING_TREES_AROUND_SNOWLINE_RANGE :Arctic tree range: {STRING2}

@ -1462,6 +1462,15 @@ static void ViewportMapLandscapeModeChanged(int32 new_value)
MarkAllViewportMapLandscapesDirty(); MarkAllViewportMapLandscapesDirty();
} }
static void MarkAllViewportsDirty(int32 new_value)
{
extern void MarkAllViewportMapLandscapesDirty();
MarkAllViewportMapLandscapesDirty();
extern void MarkWholeNonMapViewportsDirty();
MarkWholeNonMapViewportsDirty();
}
static void UpdateLinkgraphColours(int32 new_value) static void UpdateLinkgraphColours(int32 new_value)
{ {
BuildLinkStatsLegend(); BuildLinkStatsLegend();
@ -1655,6 +1664,35 @@ static void UpdateFreeformEdges(int32 new_value)
MarkWholeScreenDirty(); 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 * Changing the setting "allow multiple NewGRF sets" is not allowed
* if there are vehicles. * if there are vehicles.

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

@ -508,6 +508,7 @@ struct ConstructionSettings {
uint8 industry_platform; ///< the amount of flat land around an industry uint8 industry_platform; ///< the amount of flat land around an industry
bool freeform_edges; ///< allow terraforming the tiles at the map edges bool freeform_edges; ///< allow terraforming the tiles at the map edges
bool flood_from_edges; ///< whether water floods from 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 extra_tree_placement; ///< (dis)allow building extra trees in-game
uint8 trees_around_snow_line_range; ///< range around snowline for mixed and arctic forest. 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 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. */ * No pools are loaded. References are not possible, and thus do not need resolving. */
SlLoadCheckChunks(); SlLoadCheckChunks();
} else { } else {
/* Unconditionally default this to 0 when loading a savegame */
_settings_game.construction.map_edge_mode = 0;
/* Load chunks and resolve references */ /* Load chunks and resolve references */
SlLoadChunks(); SlLoadChunks();
SlFixPointers(); 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 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 /* TTD/TTO savegames have no NewGRFs, TTDP savegame have them
* and if so a new NewGRF list will be made in LoadOldSaveGame. * and if so a new NewGRF list will be made in LoadOldSaveGame.
* Note: this is done here because AfterLoadGame is also called * Note: this is done here because AfterLoadGame is also called

@ -13,8 +13,10 @@
static bool CheckMaxHeightLevel(int32_t &new_value); static bool CheckMaxHeightLevel(int32_t &new_value);
static bool CheckFreeformEdges(int32_t &new_value); static bool CheckFreeformEdges(int32_t &new_value);
static void UpdateFreeformEdges(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 ClimateThresholdModeChanged(int32 new_value);
static void PublicRoadsSettingChange(int32 new_value); static void PublicRoadsSettingChange(int32 new_value);
static void MarkAllViewportsDirty(int32 new_value);
static bool AllowRoadStopsUnderBridgesSettingGUI(SettingOnGuiCtrlData &data); static bool AllowRoadStopsUnderBridgesSettingGUI(SettingOnGuiCtrlData &data);
static bool TreePlacerSettingGUI(SettingOnGuiCtrlData &data); static bool TreePlacerSettingGUI(SettingOnGuiCtrlData &data);
@ -929,6 +931,20 @@ strhelp = STR_CONFIG_SETTING_FLOOD_FROM_EDGES_HELPTEXT
cat = SC_ADVANCED cat = SC_ADVANCED
patxname = ""construction.flood_from_edges"" 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] [SDT_VAR]
var = construction.extra_tree_placement var = construction.extra_tree_placement
type = SLE_UINT8 type = SLE_UINT8

@ -227,7 +227,15 @@ CommandCost CmdTerraformLand(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
assert(t < MapSize()); assert(t < MapSize());
/* MP_VOID tiles can be terraformed but as tunnels and bridges /* MP_VOID tiles can be terraformed but as tunnels and bridges
* cannot go under / over these tiles they don't need checking. */ * 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 */ /* Find new heights of tile corners */
int z_N = TerraformGetHeightOfTile(&ts, t + TileDiffXY(0, 0)); 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, /* 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. */ * 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 ((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) { if (tile_visible) {
@ -3255,34 +3261,39 @@ static inline TileIndex ViewportMapGetMostSignificantTileType(const Viewport * c
return result; 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. */ /** Get the colour of a tile, can be 32bpp RGB or 8bpp palette index. */
template <bool is_32bpp, bool show_slope> template <bool is_32bpp, bool show_slope>
uint32 ViewportMapGetColour(const Viewport * const vp, int x, int y, const uint colour_index) 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. */ /* 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 TileIndex tile_tmp = TileVirtXY(std::max(0, x), std::max(0, y));
const int z = TileHeight(tile_tmp) * 4; const int z = TileHeight(tile_tmp) * 4;
if (x + z < 0 || y + z < 0 || static_cast<uint>(x + z) >= MapSizeX() << 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. */ /* Wrapping of tile X coordinate causes a graphic glitch below south west border. */
return 0; return ViewportMapVoidColour();
} }
TileIndex tile = TileVirtXY(x + z, y + z); TileIndex tile = TileVirtXY(x + z, y + z);
if (tile >= MapSize()) return 0; if (tile >= MapSize()) return ViewportMapVoidColour();
const int z2 = TileHeight(tile) * 4; const int z2 = TileHeight(tile) * 4;
if (unlikely(z2 != z)) { if (unlikely(z2 != z)) {
const int approx_z = (z + z2) / 2; const int approx_z = (z + z2) / 2;
if (x + approx_z < 0 || y + approx_z < 0 || static_cast<uint>(x + approx_z) >= MapSizeX() << 4) { 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. */ /* 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); tile = TileVirtXY(x + approx_z, y + approx_z);
if (tile >= MapSize()) return 0; if (tile >= MapSize()) return ViewportMapVoidColour();
} }
TileType tile_type = MP_VOID; TileType tile_type = MP_VOID;
tile = ViewportMapGetMostSignificantTileType(vp, tile, &tile_type); tile = ViewportMapGetMostSignificantTileType(vp, tile, &tile_type);
if (tile_type == MP_VOID) return 0; if (tile_type == MP_VOID) return ViewportMapVoidColour();
/* Return the colours. */ /* Return the colours. */
switch (vp->map_type) { switch (vp->map_type) {

Loading…
Cancel
Save