mirror of https://github.com/OpenTTD/OpenTTD
Compare commits
4 Commits
e2922cb520
...
e99b0a6163
Author | SHA1 | Date |
---|---|---|
|
e99b0a6163 | |
|
7546c1acab | |
|
a6143eea21 | |
|
bea6f90a7d |
|
@ -43,26 +43,26 @@ SpriteFontCache::SpriteFontCache(FontSize fs) : FontCache(fs)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get SpriteID associated with a GlyphID.
|
* Get SpriteID associated with a character.
|
||||||
* @param key Glyph to find.
|
* @param key Character to find.
|
||||||
* @return SpriteID of glyph, or 0 if not present.
|
* @return SpriteID for character, or 0 if not present.
|
||||||
*/
|
*/
|
||||||
SpriteID SpriteFontCache::GetUnicodeGlyph(GlyphID key)
|
SpriteID SpriteFontCache::GetUnicodeGlyph(char32_t key)
|
||||||
{
|
{
|
||||||
const auto found = this->glyph_to_spriteid_map.find(key & ~SPRITE_GLYPH);
|
const auto found = this->char_map.find(key);
|
||||||
if (found == std::end(this->glyph_to_spriteid_map)) return 0;
|
if (found == std::end(this->char_map)) return 0;
|
||||||
return found->second;
|
return found->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpriteFontCache::SetUnicodeGlyph(char32_t key, SpriteID sprite)
|
void SpriteFontCache::SetUnicodeGlyph(char32_t key, SpriteID sprite)
|
||||||
{
|
{
|
||||||
this->glyph_to_spriteid_map[key] = sprite;
|
this->char_map[key] = sprite;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpriteFontCache::InitializeUnicodeGlyphMap()
|
void SpriteFontCache::InitializeUnicodeGlyphMap()
|
||||||
{
|
{
|
||||||
/* Clear out existing glyph map if it exists */
|
/* Clear out existing glyph map if it exists */
|
||||||
this->glyph_to_spriteid_map.clear();
|
this->char_map.clear();
|
||||||
|
|
||||||
SpriteID base;
|
SpriteID base;
|
||||||
switch (this->fs) {
|
switch (this->fs) {
|
||||||
|
|
|
@ -28,8 +28,8 @@ public:
|
||||||
bool IsBuiltInFont() override { return true; }
|
bool IsBuiltInFont() override { return true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<GlyphID, SpriteID> glyph_to_spriteid_map{}; ///< Mapping of glyphs to sprite IDs.
|
std::unordered_map<char32_t, SpriteID> char_map{}; ///< Mapping of characters to sprite IDs.
|
||||||
SpriteID GetUnicodeGlyph(GlyphID key);
|
SpriteID GetUnicodeGlyph(char32_t key);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SPRITEFONTCACHE_H */
|
#endif /* SPRITEFONTCACHE_H */
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "heightmap.h"
|
#include "heightmap.h"
|
||||||
|
#include "landscape.h"
|
||||||
#include "clear_map.h"
|
#include "clear_map.h"
|
||||||
#include "strings_func.h"
|
#include "strings_func.h"
|
||||||
#include "void_map.h"
|
#include "void_map.h"
|
||||||
|
@ -523,6 +524,10 @@ bool LoadHeightmap(DetailedFileType dft, std::string_view filename)
|
||||||
GrayscaleToMapHeights(x, y, map);
|
GrayscaleToMapHeights(x, y, map);
|
||||||
|
|
||||||
FixSlopes();
|
FixSlopes();
|
||||||
|
|
||||||
|
/* If all map borders are water, we will draw infinite water. */
|
||||||
|
_settings_game.game_creation.water_borders = (CheckWaterBorders(false) ? BORDERFLAGS_ALL : BorderFlag{});
|
||||||
|
|
||||||
MarkWholeScreenDirty();
|
MarkWholeScreenDirty();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -635,6 +635,41 @@ void ClearSnowLine()
|
||||||
_snow_line = nullptr;
|
_snow_line = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if all tiles on the map edge should be considered water borders.
|
||||||
|
* @param allow_non_flat_void Should we allow non-flat void tiles? (if map edge raised, then flattened to sea level)
|
||||||
|
* @return true If the edge of the map is flat and height 0, allowing for infinite water borders.
|
||||||
|
*/
|
||||||
|
bool CheckWaterBorders(bool allow_non_flat_void)
|
||||||
|
{
|
||||||
|
auto check_tile = [allow_non_flat_void](uint x, uint y, Slope inner_edge) -> bool {
|
||||||
|
auto [slope, h] = GetTilePixelSlopeOutsideMap(x, y);
|
||||||
|
|
||||||
|
/* The edge tile is flat. */
|
||||||
|
if ((slope == SLOPE_FLAT) && (h == 0)) return true;
|
||||||
|
if (allow_non_flat_void && h == 0 && (slope & inner_edge) == 0 && IsTileType(TileXY(x, y), MP_VOID)) return true;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Check the map corners. */
|
||||||
|
if (!check_tile(0, 0, SLOPE_S)) return false;
|
||||||
|
if (!check_tile(0, Map::SizeY(), SLOPE_W)) return false;
|
||||||
|
if (!check_tile(Map::SizeX(), 0, SLOPE_E)) return false;
|
||||||
|
if (!check_tile(Map::SizeX(), Map::SizeY(), SLOPE_N)) return false;
|
||||||
|
|
||||||
|
/* Check the map edges.*/
|
||||||
|
for (uint x = 0; x <= Map::SizeX(); x++) {
|
||||||
|
if (!check_tile(x, 0, SLOPE_SE)) return false;
|
||||||
|
if (!check_tile(x, Map::SizeY(), SLOPE_NW)) return false;
|
||||||
|
}
|
||||||
|
for (uint y = 1; y < Map::SizeY(); y++) {
|
||||||
|
if (!check_tile(0, y, SLOPE_SW)) return false;
|
||||||
|
if (!check_tile(Map::SizeX(), y, SLOPE_NE)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear a piece of landscape
|
* Clear a piece of landscape
|
||||||
* @param flags of operation to conduct
|
* @param flags of operation to conduct
|
||||||
|
|
|
@ -33,6 +33,8 @@ uint8_t HighestSnowLine();
|
||||||
uint8_t LowestSnowLine();
|
uint8_t LowestSnowLine();
|
||||||
void ClearSnowLine();
|
void ClearSnowLine();
|
||||||
|
|
||||||
|
bool CheckWaterBorders(bool allow_non_flat_void);
|
||||||
|
|
||||||
int GetSlopeZInCorner(Slope tileh, Corner corner);
|
int GetSlopeZInCorner(Slope tileh, Corner corner);
|
||||||
std::tuple<Slope, int> GetFoundationSlope(TileIndex tile);
|
std::tuple<Slope, int> GetFoundationSlope(TileIndex tile);
|
||||||
|
|
||||||
|
|
|
@ -1024,6 +1024,27 @@ bool AfterLoadGame()
|
||||||
_settings_game.construction.freeform_edges = false;
|
_settings_game.construction.freeform_edges = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handle infinite water borders. */
|
||||||
|
if (IsSavegameVersionBefore(SLV_INFINITE_WATER_BORDERS)) {
|
||||||
|
if (CheckWaterBorders(true)) {
|
||||||
|
/* We passed the water borders check, yay! */
|
||||||
|
_settings_game.game_creation.water_borders = BORDERFLAGS_ALL;
|
||||||
|
|
||||||
|
/* Flatten void tiles, which may have been affected by terraforming near the map edge. */
|
||||||
|
for (uint x = 0; x <= Map::SizeX(); x++) {
|
||||||
|
SetTileHeightOutsideMap(x, 0, 0);
|
||||||
|
SetTileHeightOutsideMap(x, Map::SizeY(), 0);
|
||||||
|
}
|
||||||
|
for (uint y = 1; y < Map::SizeY(); y++) {
|
||||||
|
SetTileHeightOutsideMap(0, y, 0);
|
||||||
|
SetTileHeightOutsideMap(Map::SizeX(), y, 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Not all edges are ocean. */
|
||||||
|
_settings_game.game_creation.water_borders = BorderFlag{};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* From version 9.0, we update the max passengers of a town (was sometimes negative
|
/* From version 9.0, we update the max passengers of a town (was sometimes negative
|
||||||
* before that. */
|
* before that. */
|
||||||
if (IsSavegameVersionBefore(SLV_9)) {
|
if (IsSavegameVersionBefore(SLV_9)) {
|
||||||
|
|
|
@ -405,6 +405,7 @@ enum SaveLoadVersion : uint16_t {
|
||||||
|
|
||||||
SLV_FACE_STYLES, ///< 355 PR#14319 Addition of face styles, replacing gender and ethnicity.
|
SLV_FACE_STYLES, ///< 355 PR#14319 Addition of face styles, replacing gender and ethnicity.
|
||||||
SLV_INDUSTRY_NUM_VALID_HISTORY, ///< 356 PR#14416 Store number of valid history records for industries.
|
SLV_INDUSTRY_NUM_VALID_HISTORY, ///< 356 PR#14416 Store number of valid history records for industries.
|
||||||
|
SLV_INFINITE_WATER_BORDERS, ///< 357 PR#13289 Draw infinite water when all borders are water.
|
||||||
|
|
||||||
SL_MAX_VERSION, ///< Highest possible saveload version
|
SL_MAX_VERSION, ///< Highest possible saveload version
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,10 +24,12 @@
|
||||||
#include "api/script_event.hpp"
|
#include "api/script_event.hpp"
|
||||||
#include "api/script_log.hpp"
|
#include "api/script_log.hpp"
|
||||||
|
|
||||||
#include "../company_base.h"
|
#include "../company_type.h"
|
||||||
#include "../company_func.h"
|
|
||||||
#include "../fileio_func.h"
|
#include "../fileio_func.h"
|
||||||
|
#include "../goal_type.h"
|
||||||
#include "../league_type.h"
|
#include "../league_type.h"
|
||||||
|
#include "../signs_type.h"
|
||||||
|
#include "../story_type.h"
|
||||||
#include "../misc/endian_buffer.hpp"
|
#include "../misc/endian_buffer.hpp"
|
||||||
|
|
||||||
#include "../safeguards.h"
|
#include "../safeguards.h"
|
||||||
|
|
|
@ -12,12 +12,10 @@
|
||||||
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
#include "../signs_func.h"
|
#include "../command_type.h"
|
||||||
#include "../vehicle_func.h"
|
#include "../company_type.h"
|
||||||
|
#include "../rail_type.h"
|
||||||
#include "../road_type.h"
|
#include "../road_type.h"
|
||||||
#include "../group.h"
|
|
||||||
#include "../goal_type.h"
|
|
||||||
#include "../story_type.h"
|
|
||||||
|
|
||||||
#include "script_types.hpp"
|
#include "script_types.hpp"
|
||||||
#include "script_log_types.hpp"
|
#include "script_log_types.hpp"
|
||||||
|
|
|
@ -264,6 +264,7 @@ cat = SC_BASIC
|
||||||
var = game_creation.water_borders
|
var = game_creation.water_borders
|
||||||
type = SLE_UINT8
|
type = SLE_UINT8
|
||||||
from = SLV_111
|
from = SLV_111
|
||||||
|
flags = SettingFlag::NewgameOnly
|
||||||
def = 15
|
def = 15
|
||||||
min = 0
|
min = 0
|
||||||
max = 16
|
max = 16
|
||||||
|
|
|
@ -111,16 +111,25 @@ static std::tuple<CommandCost, TileIndex> TerraformTileHeight(TerraformerState *
|
||||||
*/
|
*/
|
||||||
if (height == TerraformGetHeightOfTile(ts, tile)) return { CMD_ERROR, INVALID_TILE };
|
if (height == TerraformGetHeightOfTile(ts, tile)) return { CMD_ERROR, INVALID_TILE };
|
||||||
|
|
||||||
/* Check "too close to edge of map". Only possible when freeform-edges is off. */
|
/* If the map has infinite water borders, don't allow terraforming the outer ring of tiles to avoid blocking ships in a confusing way. */
|
||||||
uint x = TileX(tile);
|
if (_settings_game.game_creation.water_borders == BORDERFLAGS_ALL) {
|
||||||
uint y = TileY(tile);
|
uint x = TileX(tile);
|
||||||
if (!_settings_game.construction.freeform_edges && ((x <= 1) || (y <= 1) || (x >= Map::MaxX() - 1) || (y >= Map::MaxY() - 1))) {
|
uint y = TileY(tile);
|
||||||
/*
|
|
||||||
* Determine a sensible error tile
|
auto check_tile = [&](uint x_min, uint y_min, uint x_max, uint y_max) -> bool {
|
||||||
*/
|
return ((x <= x_min) || (y <= y_min) || (x >= Map::MaxX() - x_max) || (y >= Map::MaxY() - y_max));
|
||||||
if (x == 1) x = 0;
|
};
|
||||||
if (y == 1) y = 0;
|
|
||||||
return { CommandCost(STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP), TileXY(x, y) };
|
/* If free-form edges is off, distances are a bit different. */
|
||||||
|
if (!_settings_game.construction.freeform_edges && check_tile(1, 1, 1, 1)) {
|
||||||
|
/* Determine a sensible error tile. */
|
||||||
|
if (x == 1) x = 0;
|
||||||
|
if (y == 1) y = 0;
|
||||||
|
return { CommandCost(STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP), TileXY(x, y) };
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Freeform edges are enabled. */
|
||||||
|
if (check_tile(2, 2, 1, 1)) return { CommandCost(STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP), TileXY(x, y) };
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mark incident tiles that are involved in the terraforming. */
|
/* Mark incident tiles that are involved in the terraforming. */
|
||||||
|
@ -209,7 +218,11 @@ std::tuple<CommandCost, Money, TileIndex> CmdTerraformLand(DoCommandFlags flags,
|
||||||
assert(t < Map::Size());
|
assert(t < Map::Size());
|
||||||
/* 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)) {
|
||||||
|
/* All water borders are drawn with infinite water, so don't allow terraforming off the map edge. */
|
||||||
|
if (_settings_game.game_creation.water_borders == BORDERFLAGS_ALL) return { CommandCost(STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP), 0, t };
|
||||||
|
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));
|
||||||
|
|
|
@ -61,6 +61,18 @@ inline void SetTileHeight(Tile tile, uint height)
|
||||||
tile.height() = height;
|
tile.height() = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the height of a tile, also for tiles outside the map (virtual "black" tiles).
|
||||||
|
*
|
||||||
|
* @param tile The tile to change the height
|
||||||
|
* @param height The new height value of the tile
|
||||||
|
* @pre height <= MAX_TILE_HEIGHT
|
||||||
|
*/
|
||||||
|
inline void SetTileHeightOutsideMap(int x, int y, uint height)
|
||||||
|
{
|
||||||
|
SetTileHeight(TileXY(Clamp(x, 0, Map::MaxX()), Clamp(y, 0, Map::MaxY())), height);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the height of a tile in pixels.
|
* Returns the height of a tile in pixels.
|
||||||
*
|
*
|
||||||
|
|
|
@ -21,7 +21,12 @@
|
||||||
|
|
||||||
static void DrawTile_Void(TileInfo *ti)
|
static void DrawTile_Void(TileInfo *ti)
|
||||||
{
|
{
|
||||||
DrawGroundSprite(SPR_FLAT_BARE_LAND + SlopeToSpriteOffset(ti->tileh), PALETTE_ALL_BLACK);
|
/* If all borders are water, draw infinite water off the edges of the map. */
|
||||||
|
if (_settings_game.game_creation.water_borders == BORDERFLAGS_ALL) {
|
||||||
|
DrawGroundSprite(SPR_FLAT_WATER_TILE + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
|
||||||
|
} else {
|
||||||
|
DrawGroundSprite(SPR_FLAT_BARE_LAND + SlopeToSpriteOffset(ti->tileh), PALETTE_ALL_BLACK);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue