mirror of
https://github.com/OpenTTD/OpenTTD
synced 2026-01-18 18:02:37 +01:00
Feature: Draw infinite water when all borders are water (#13289)
This commit is contained in:
@@ -115,7 +115,7 @@ static constexpr NWidgetPart _nested_generate_landscape_widgets[] = {
|
||||
NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_VARIETY_PULLDOWN), SetToolTip(STR_CONFIG_SETTING_VARIETY_HELPTEXT), SetFill(1, 1),
|
||||
NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_SMOOTHNESS_PULLDOWN), SetToolTip(STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_HELPTEXT), SetFill(1, 1),
|
||||
NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_RIVER_PULLDOWN), SetToolTip(STR_CONFIG_SETTING_RIVER_AMOUNT_HELPTEXT), SetFill(1, 1),
|
||||
NWidget(WWT_TEXTBTN, COLOUR_ORANGE, WID_GL_BORDERS_RANDOM), SetToolTip(STR_MAPGEN_BORDER_TYPE_TOOLTIP), SetFill(1, 1),
|
||||
NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_BORDERS_PULLDOWN), SetToolTip(STR_MAPGEN_BORDER_TYPE_TOOLTIP), SetFill(1, 1),
|
||||
EndContainer(),
|
||||
EndContainer(),
|
||||
|
||||
@@ -379,6 +379,7 @@ static DropDownList BuildTownNameDropDown()
|
||||
static const StringID _elevations[] = {STR_TERRAIN_TYPE_VERY_FLAT, STR_TERRAIN_TYPE_FLAT, STR_TERRAIN_TYPE_HILLY, STR_TERRAIN_TYPE_MOUNTAINOUS, STR_TERRAIN_TYPE_ALPINIST, STR_TERRAIN_TYPE_CUSTOM};
|
||||
static const StringID _sea_lakes[] = {STR_SEA_LEVEL_VERY_LOW, STR_SEA_LEVEL_LOW, STR_SEA_LEVEL_MEDIUM, STR_SEA_LEVEL_HIGH, STR_SEA_LEVEL_CUSTOM};
|
||||
static const StringID _rivers[] = {STR_RIVERS_NONE, STR_RIVERS_FEW, STR_RIVERS_MODERATE, STR_RIVERS_LOT};
|
||||
static const StringID _borders[] = {STR_MAPGEN_BORDER_RANDOMIZE, STR_MAPGEN_BORDER_MANUAL, STR_MAPGEN_BORDER_INFINITE_WATER};
|
||||
static const StringID _smoothness[] = {STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH, STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_SMOOTH, STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_ROUGH, STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_ROUGH};
|
||||
static const StringID _rotation[] = {STR_CONFIG_SETTING_HEIGHTMAP_ROTATION_COUNTER_CLOCKWISE, STR_CONFIG_SETTING_HEIGHTMAP_ROTATION_CLOCKWISE};
|
||||
static const StringID _num_towns[] = {STR_NUM_VERY_LOW, STR_NUM_LOW, STR_NUM_NORMAL, STR_NUM_HIGH, STR_NUM_CUSTOM};
|
||||
@@ -471,7 +472,7 @@ struct GenerateLandscapeWindow : public Window {
|
||||
case WID_GL_RIVER_PULLDOWN: return GetString(_rivers[_settings_newgame.game_creation.amount_of_rivers]);
|
||||
case WID_GL_SMOOTHNESS_PULLDOWN: return GetString(_smoothness[_settings_newgame.game_creation.tgen_smoothness]);
|
||||
case WID_GL_VARIETY_PULLDOWN: return GetString(_variety[_settings_newgame.game_creation.variety]);
|
||||
case WID_GL_BORDERS_RANDOM: return GetString((_settings_newgame.game_creation.water_borders == BorderFlag::Random) ? STR_MAPGEN_BORDER_RANDOMIZE : STR_MAPGEN_BORDER_MANUAL);
|
||||
case WID_GL_BORDERS_PULLDOWN: return GetString(_borders[_settings_newgame.game_creation.water_border_presets]);
|
||||
case WID_GL_WATER_NE: return GetString((_settings_newgame.game_creation.water_borders == BorderFlag::Random) ? STR_MAPGEN_BORDER_RANDOM : _settings_newgame.game_creation.water_borders.Test(BorderFlag::NorthEast) ? STR_MAPGEN_BORDER_WATER : STR_MAPGEN_BORDER_FREEFORM);
|
||||
case WID_GL_WATER_NW: return GetString((_settings_newgame.game_creation.water_borders == BorderFlag::Random) ? STR_MAPGEN_BORDER_RANDOM : _settings_newgame.game_creation.water_borders.Test(BorderFlag::NorthWest) ? STR_MAPGEN_BORDER_WATER : STR_MAPGEN_BORDER_FREEFORM);
|
||||
case WID_GL_WATER_SE: return GetString((_settings_newgame.game_creation.water_borders == BorderFlag::Random) ? STR_MAPGEN_BORDER_RANDOM : _settings_newgame.game_creation.water_borders.Test(BorderFlag::SouthEast) ? STR_MAPGEN_BORDER_WATER : STR_MAPGEN_BORDER_FREEFORM);
|
||||
@@ -507,12 +508,10 @@ struct GenerateLandscapeWindow : public Window {
|
||||
if (mode == GLWM_GENERATE) {
|
||||
this->SetWidgetDisabledState(WID_GL_SMOOTHNESS_PULLDOWN, _settings_newgame.game_creation.land_generator == LG_ORIGINAL);
|
||||
this->SetWidgetDisabledState(WID_GL_VARIETY_PULLDOWN, _settings_newgame.game_creation.land_generator == LG_ORIGINAL);
|
||||
this->SetWidgetDisabledState(WID_GL_BORDERS_RANDOM, _settings_newgame.game_creation.land_generator == LG_ORIGINAL || !_settings_newgame.construction.freeform_edges);
|
||||
this->SetWidgetDisabledState(WID_GL_BORDERS_PULLDOWN, _settings_newgame.game_creation.land_generator == LG_ORIGINAL);
|
||||
this->SetWidgetsDisabledState(_settings_newgame.game_creation.land_generator == LG_ORIGINAL || !_settings_newgame.construction.freeform_edges || _settings_newgame.game_creation.water_borders == BorderFlag::Random,
|
||||
WID_GL_WATER_NW, WID_GL_WATER_NE, WID_GL_WATER_SE, WID_GL_WATER_SW);
|
||||
|
||||
this->SetWidgetLoweredState(WID_GL_BORDERS_RANDOM, _settings_newgame.game_creation.water_borders == BorderFlag::Random);
|
||||
|
||||
this->SetWidgetLoweredState(WID_GL_WATER_NW, _settings_newgame.game_creation.water_borders.Test(BorderFlag::NorthWest));
|
||||
this->SetWidgetLoweredState(WID_GL_WATER_NE, _settings_newgame.game_creation.water_borders.Test(BorderFlag::NorthEast));
|
||||
this->SetWidgetLoweredState(WID_GL_WATER_SE, _settings_newgame.game_creation.water_borders.Test(BorderFlag::SouthEast));
|
||||
@@ -622,10 +621,7 @@ struct GenerateLandscapeWindow : public Window {
|
||||
case WID_GL_SMOOTHNESS_PULLDOWN: strs = _smoothness; break;
|
||||
case WID_GL_VARIETY_PULLDOWN: strs = _variety; break;
|
||||
case WID_GL_HEIGHTMAP_ROTATION_PULLDOWN: strs = _rotation; break;
|
||||
case WID_GL_BORDERS_RANDOM:
|
||||
d = maxdim(GetStringBoundingBox(STR_MAPGEN_BORDER_RANDOMIZE), GetStringBoundingBox(STR_MAPGEN_BORDER_MANUAL));
|
||||
break;
|
||||
|
||||
case WID_GL_BORDERS_PULLDOWN: strs = _borders; break;
|
||||
case WID_GL_WATER_NE:
|
||||
case WID_GL_WATER_NW:
|
||||
case WID_GL_WATER_SE:
|
||||
@@ -807,7 +803,11 @@ struct GenerateLandscapeWindow : public Window {
|
||||
ShowDropDownMenu(this, _variety, _settings_newgame.game_creation.variety, WID_GL_VARIETY_PULLDOWN, 0, 0);
|
||||
break;
|
||||
|
||||
/* Freetype map borders */
|
||||
/* Map borders */
|
||||
case WID_GL_BORDERS_PULLDOWN:
|
||||
ShowDropDownMenu(this, _borders, _settings_newgame.game_creation.water_border_presets, WID_GL_BORDERS_PULLDOWN, 0, 0);
|
||||
break;
|
||||
|
||||
case WID_GL_WATER_NW:
|
||||
_settings_newgame.game_creation.water_borders.Flip(BorderFlag::NorthWest);
|
||||
SndClickBeep();
|
||||
@@ -832,16 +832,6 @@ struct GenerateLandscapeWindow : public Window {
|
||||
this->InvalidateData();
|
||||
break;
|
||||
|
||||
case WID_GL_BORDERS_RANDOM:
|
||||
if (_settings_newgame.game_creation.water_borders == BorderFlag::Random) {
|
||||
_settings_newgame.game_creation.water_borders.Reset();
|
||||
} else {
|
||||
_settings_newgame.game_creation.water_borders = BorderFlag::Random;
|
||||
}
|
||||
SndClickBeep();
|
||||
this->InvalidateData();
|
||||
break;
|
||||
|
||||
case WID_GL_AI_BUTTON: ///< AI Settings
|
||||
ShowAIConfigWindow();
|
||||
break;
|
||||
@@ -908,6 +898,25 @@ struct GenerateLandscapeWindow : public Window {
|
||||
break;
|
||||
}
|
||||
|
||||
case WID_GL_BORDERS_PULLDOWN: {
|
||||
switch (index) {
|
||||
case BFP_RANDOM:
|
||||
_settings_newgame.game_creation.water_borders = BorderFlag::Random;
|
||||
_settings_newgame.construction.freeform_edges = true;
|
||||
break;
|
||||
case BFP_MANUAL:
|
||||
_settings_newgame.game_creation.water_borders = {};
|
||||
_settings_newgame.construction.freeform_edges = true;
|
||||
break;
|
||||
case BFP_INFINITE_WATER:
|
||||
_settings_newgame.game_creation.water_borders = BORDERFLAGS_ALL;
|
||||
_settings_newgame.construction.freeform_edges = false;
|
||||
break;
|
||||
}
|
||||
_settings_newgame.game_creation.water_border_presets = static_cast<BorderFlagPresets>(index);
|
||||
break;
|
||||
}
|
||||
|
||||
case WID_GL_WATER_PULLDOWN: {
|
||||
if ((uint)index == CUSTOM_SEA_LEVEL_NUMBER_DIFFICULTY) {
|
||||
this->widget_id = widget;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "heightmap.h"
|
||||
#include "landscape.h"
|
||||
#include "clear_map.h"
|
||||
#include "strings_func.h"
|
||||
#include "void_map.h"
|
||||
@@ -523,6 +524,10 @@ bool LoadHeightmap(DetailedFileType dft, std::string_view filename)
|
||||
GreyscaleToMapHeights(x, y, map);
|
||||
|
||||
FixSlopes();
|
||||
|
||||
/* If all map borders are water, we will draw infinite water. */
|
||||
_settings_game.construction.freeform_edges = !IsMapSurroundedByWater();
|
||||
|
||||
MarkWholeScreenDirty();
|
||||
|
||||
return true;
|
||||
|
||||
@@ -637,6 +637,36 @@ void ClearSnowLine()
|
||||
_snow_line = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if all tiles on the map edge should be considered water borders.
|
||||
* @return true If the edge of the map is flat and height 0, allowing for infinite water borders.
|
||||
*/
|
||||
bool IsMapSurroundedByWater()
|
||||
{
|
||||
auto check_tile = [](uint x, uint y) -> bool {
|
||||
auto [slope, h] = GetTilePixelSlopeOutsideMap(x, y);
|
||||
return ((slope == SLOPE_FLAT) && (h == 0));
|
||||
};
|
||||
|
||||
/* Check the map corners. */
|
||||
if (!check_tile(0, 0)) return false;
|
||||
if (!check_tile(0, Map::SizeY())) return false;
|
||||
if (!check_tile(Map::SizeX(), 0)) return false;
|
||||
if (!check_tile(Map::SizeX(), Map::SizeY())) return false;
|
||||
|
||||
/* Check the map edges.*/
|
||||
for (uint x = 0; x <= Map::SizeX(); x++) {
|
||||
if (!check_tile(x, 0)) return false;
|
||||
if (!check_tile(x, Map::SizeY())) return false;
|
||||
}
|
||||
for (uint y = 1; y < Map::SizeY(); y++) {
|
||||
if (!check_tile(0, y)) return false;
|
||||
if (!check_tile(Map::SizeX(), y)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear a piece of landscape
|
||||
* @param flags of operation to conduct
|
||||
|
||||
@@ -33,6 +33,8 @@ uint8_t HighestSnowLine();
|
||||
uint8_t LowestSnowLine();
|
||||
void ClearSnowLine();
|
||||
|
||||
bool IsMapSurroundedByWater();
|
||||
|
||||
int GetSlopeZInCorner(Slope tileh, Corner corner);
|
||||
std::tuple<Slope, int> GetFoundationSlope(TileIndex tile);
|
||||
|
||||
|
||||
@@ -3428,8 +3428,11 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Southwes
|
||||
STR_MAPGEN_BORDER_FREEFORM :{BLACK}Freeform
|
||||
STR_MAPGEN_BORDER_WATER :{BLACK}Water
|
||||
STR_MAPGEN_BORDER_RANDOM :{BLACK}Random
|
||||
STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Random
|
||||
STR_MAPGEN_BORDER_MANUAL :{BLACK}Manual
|
||||
|
||||
###length 3
|
||||
STR_MAPGEN_BORDER_RANDOMIZE :Random
|
||||
STR_MAPGEN_BORDER_MANUAL :Manual
|
||||
STR_MAPGEN_BORDER_INFINITE_WATER :Infinite Water
|
||||
|
||||
STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Heightmap rotation:
|
||||
STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Heightmap name:
|
||||
|
||||
@@ -253,6 +253,11 @@ CommandCost CmdBuildObject(DoCommandFlags flags, TileIndex tile, ObjectType type
|
||||
Owner o = GetTileOwner(t);
|
||||
if (o != OWNER_NONE && o != OWNER_WATER) cost.AddCost(CheckOwnership(o, t));
|
||||
|
||||
/* If freeform edges are disabled, don't allow building on edge tiles. */
|
||||
if (!_settings_game.construction.freeform_edges && (!IsInsideMM(TileX(t), 1, Map::MaxX() - 1) || !IsInsideMM(TileY(t), 1, Map::MaxY() - 1))) {
|
||||
return CommandCost(STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP);
|
||||
}
|
||||
|
||||
/* However, the tile has to be clear of vehicles. */
|
||||
cost.AddCost(EnsureNoVehicleOnGround(t));
|
||||
}
|
||||
|
||||
@@ -64,6 +64,13 @@ enum IndustryDensity : uint8_t {
|
||||
ID_END, ///< Number of industry density settings.
|
||||
};
|
||||
|
||||
/** Possible options for the Borders pulldown in the Genworld GUI. */
|
||||
enum BorderFlagPresets : uint8_t {
|
||||
BFP_RANDOM = 0,
|
||||
BFP_MANUAL,
|
||||
BFP_INFINITE_WATER,
|
||||
};
|
||||
|
||||
/** Possible values for the "timekeeping_units" setting. */
|
||||
enum TimekeepingUnits : uint8_t {
|
||||
TKU_CALENDAR = 0,
|
||||
@@ -375,6 +382,7 @@ struct GameCreationSettings {
|
||||
uint8_t town_name; ///< the town name generator used for town names
|
||||
LandscapeType landscape; ///< the landscape we're currently in
|
||||
BorderFlags water_borders; ///< bitset of the borders that are water
|
||||
BorderFlagPresets water_border_presets; ///< presets for map border options
|
||||
uint16_t custom_town_number; ///< manually entered number of towns
|
||||
uint16_t custom_industry_number; ///< manually entered number of industries
|
||||
uint8_t variety; ///< variety level applied to TGP
|
||||
|
||||
@@ -268,6 +268,13 @@ def = 15
|
||||
min = 0
|
||||
max = 16
|
||||
|
||||
[SDT_VAR]
|
||||
var = game_creation.water_border_presets
|
||||
type = SLE_UINT8
|
||||
def = BFP_RANDOM
|
||||
min = BFP_RANDOM
|
||||
max = BFP_INFINITE_WATER
|
||||
|
||||
[SDT_VAR]
|
||||
var = game_creation.custom_town_number
|
||||
type = SLE_UINT16
|
||||
|
||||
@@ -21,7 +21,12 @@
|
||||
|
||||
static void DrawTile_Void(TileInfo *ti)
|
||||
{
|
||||
DrawGroundSprite(SPR_FLAT_BARE_LAND + SlopeToSpriteOffset(ti->tileh), PALETTE_ALL_BLACK);
|
||||
/* If freeform edges are off, draw infinite water off the edges of the map. */
|
||||
if (!_settings_game.construction.freeform_edges) {
|
||||
DrawGroundSprite(SPR_FLAT_WATER_TILE + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
|
||||
} else {
|
||||
DrawGroundSprite(SPR_FLAT_BARE_LAND + SlopeToSpriteOffset(ti->tileh), PALETTE_ALL_BLACK);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -454,6 +454,13 @@ CommandCost CmdBuildLock(DoCommandFlags flags, TileIndex tile)
|
||||
DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile));
|
||||
if (dir == INVALID_DIAGDIR) return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
|
||||
|
||||
TileIndex lower_tile = TileAddByDiagDir(tile, ReverseDiagDir(dir));
|
||||
|
||||
/* If freeform edges are disabled, don't allow building on edge tiles. */
|
||||
if (!_settings_game.construction.freeform_edges && (!IsInsideMM(TileX(lower_tile), 1, Map::MaxX() - 1) || !IsInsideMM(TileY(lower_tile), 1, Map::MaxY() - 1))) {
|
||||
return CommandCost(STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP);
|
||||
}
|
||||
|
||||
return DoBuildLock(tile, dir, flags);
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ enum GenerateLandscapeWidgets : WidgetID {
|
||||
WID_GL_SMOOTHNESS_PULLDOWN, ///< Dropdown 'Smoothness'.
|
||||
WID_GL_VARIETY_PULLDOWN, ///< Dropdown 'Variety distribution'.
|
||||
|
||||
WID_GL_BORDERS_RANDOM, ///< 'Random'/'Manual' borders.
|
||||
WID_GL_BORDERS_PULLDOWN, ///< Dropdown 'Map edges'.
|
||||
WID_GL_WATER_NW, ///< NW 'Water'/'Freeform'.
|
||||
WID_GL_WATER_NE, ///< NE 'Water'/'Freeform'.
|
||||
WID_GL_WATER_SE, ///< SE 'Water'/'Freeform'.
|
||||
|
||||
Reference in New Issue
Block a user