Merge branch 'master' into jgrpp

# Conflicts:
#	CMakeLists.txt
#	cmake/CompileFlags.cmake
#	src/bridge_gui.cpp
#	src/saveload/afterload.cpp
#	src/saveload/saveload.cpp
#	src/saveload/saveload.h
#	src/saveload/town_sl.cpp
#	src/screenshot.cpp
#	src/screenshot.h
#	src/toolbar_gui.cpp
#	src/town.h
#	src/town_cmd.cpp
pull/167/head
Jonathan G Rennison 4 years ago
commit 3adeff1883

@ -7,6 +7,7 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
endif (CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9)
# Use GNUInstallDirs to allow customisation
# but set our own default data dir
@ -31,27 +32,29 @@ find_package(ZLIB)
find_package(LibLZMA)
find_package(LZO)
find_package(PNG)
if (NOT WIN32)
find_package(SDL2)
if (NOT SDL2_FOUND)
find_package(SDL)
endif( NOT SDL2_FOUND)
find_package(Allegro)
find_package(Fluidsynth)
find_package(Freetype)
find_package(Fontconfig)
find_package(ICU OPTIONAL_COMPONENTS i18n lx)
find_package(XDG_basedir)
if (NOT APPLE)
find_package(SDL2)
if (NOT SDL2_FOUND)
find_package(SDL)
endif( NOT SDL2_FOUND)
find_package(Fluidsynth)
find_package(Freetype)
find_package(Fontconfig)
find_package(ICU OPTIONAL_COMPONENTS i18n lx)
find_package(XDG_basedir)
else (NOT APPLE)
find_package(Iconv)
find_library(AUDIOTOOLBOX_LIBRARY AudioToolbox)
find_library(AUDIOUNIT_LIBRARY AudioUnit)
find_library(COCOA_LIBRARY Cocoa)
find_package(MacUcontext)
endif (NOT APPLE)
endif (NOT WIN32)
if (APPLE)
find_package(Iconv)
find_library(AUDIOTOOLBOX_LIBRARY AudioToolbox)
find_library(AUDIOUNIT_LIBRARY AudioUnit)
find_library(COCOA_LIBRARY Cocoa)
find_package(MacUcontext)
endif (APPLE)
if (MSVC)
find_package(Editbin REQUIRED)

@ -31,8 +31,13 @@ macro(compile_flags)
# it does not appear to support the $<> tags.
add_compile_options(
"$<$<CONFIG:Debug>:-D_DEBUG>"
"$<$<CONFIG:Debug>:-D_FORTIFY_SOURCE=2>"
"$<$<NOT:$<CONFIG:Debug>>:-D_FORTIFY_SOURCE=2>" # FORTIFY_SOURCE should only be used in non-debug builds (requires -O1+)
)
if (MINGW)
add_link_options(
"$<$<NOT:$<CONFIG:Debug>>:-fstack-protector>" # Prevent undefined references when _FORTIFY_SOURCE > 0
)
endif (MINGW)
# Prepare a generator that checks if we are not a debug, and don't have asserts
# on. We need this later on to set some compile options for stable releases.
@ -73,14 +78,34 @@ macro(compile_flags)
add_compile_options(-O2 -DNDEBUG)
endif(NOT CMAKE_BUILD_TYPE)
#add_compile_options(
# When we are a stable release (Release build + USE_ASSERTS not set),
# assertations are off, which trigger a lot of warnings. We disable
# these warnings for these releases.
#"$<${IS_STABLE_RELEASE}:-Wno-unused-variable>"
#"$<${IS_STABLE_RELEASE}:-Wno-unused-but-set-parameter>"
#"$<${IS_STABLE_RELEASE}:-Wno-unused-but-set-variable>"
#)
# When we are a stable release (Release build + USE_ASSERTS not set),
# assertations are off, which trigger a lot of warnings. We disable
# these warnings for these releases.
#if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
# add_compile_options(
# "$<${IS_STABLE_RELEASE}:-Wno-unused-variable>"
# "$<${IS_STABLE_RELEASE}:-Wno-unused-but-set-parameter>"
# "$<${IS_STABLE_RELEASE}:-Wno-unused-but-set-variable>"
# )
#else (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
# add_compile_options(
# "$<${IS_STABLE_RELEASE}:-Wno-unused-variable>"
# "$<${IS_STABLE_RELEASE}:-Wno-unused-parameter>"
# )
#endif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
# Ninja processes the output so the output from the compiler
# isn't directly to a terminal; hence, the default is
# non-coloured output. We can override this to get nicely
# coloured output, but since that might yield odd results with
# IDEs, we extract it to an option.
if (OPTION_FORCE_COLORED_OUTPUT)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
add_compile_options (-fdiagnostics-color=always)
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
add_compile_options (-fcolor-diagnostics)
endif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
endif (OPTION_FORCE_COLORED_OUTPUT)
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
include(CheckCXXCompilerFlag)

@ -58,7 +58,7 @@ elseif(CMAKE_CXX_COMPILER_LOADED)
include(CheckCXXSourceCompiles)
else()
# If neither C nor CXX are loaded, implicit iconv makes no sense.
set(Iconv_IS_BUILT_IN FALSE)
set(Iconv_IS_BUILT_IN NO)
endif()
# iconv can only be provided in libc on a POSIX system.
@ -94,7 +94,7 @@ if(NOT DEFINED Iconv_IS_BUILT_IN)
endif()
cmake_pop_check_state()
else()
set(Iconv_IS_BUILT_IN FALSE)
set(Iconv_IS_BUILT_IN NO)
endif()
endif()

@ -48,6 +48,8 @@ function(set_options)
set(DEFAULT_OPTION_INSTALL_FHS OFF)
endif (UNIX AND NOT APPLE)
option(OPTION_FORCE_COLORED_OUTPUT "Always produce ANSI-colored output (GNU/Clang only)." OFF)
option(OPTION_DEDICATED "Build dedicated server only (no GUI)" OFF)
option(OPTION_INSTALL_FHS "Install with Filesstem Hierarchy Standard folders" ${DEFAULT_OPTION_INSTALL_FHS})
option(OPTION_USE_ASSERTS "Use assertions; leave enabled for nightlies, betas, and RCs" ON)

@ -82,7 +82,7 @@ if (GIT_FOUND AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
set(REV_VERSION "${TAG}")
set(REV_ISTAG 1)
string(REGEX REPLACE "^[0-9.]*$" "" STABLETAG "${TAG}")
string(REGEX REPLACE "^[0-9.]+$" "" STABLETAG "${TAG}")
if (NOT STABLETAG STREQUAL "")
set(REV_ISSTABLETAG 1)
else ()

@ -86,6 +86,9 @@ Last updated: 2011-01-20
Note: not every update type supports every frequency. If in doubt, you can
verify against the data received in `ADMIN_PACKET_SERVER_PROTOCOL`.
Please note the potential gotcha in the "Certain packet information" section below
when using the `ADMIN_UPDATE_FREQUENCY` packet.
The server will not confirm your registered update. However, asking for an
invalid `AdminUpdateType` or a not supported `AdminUpdateFrequency` you will be
disconnected from the server with `NETWORK_ERROR_ILLEGAL_PACKET`.
@ -143,6 +146,9 @@ Last updated: 2011-01-20
- ADMIN_UPDATE_COMPANY_STATS
- ADMIN_UPDATE_CMD_NAMES
Please note the potential gotcha in the "Certain packet information" section below
when using the `ADMIN_POLL` packet.
`ADMIN_UPDATE_CLIENT_INFO` and `ADMIN_UPDATE_COMPANY_INFO` accept an additional
parameter. This parameter is used to specify a certain client or company.
Setting this parameter to `UINT32_MAX (0xFFFFFFFF)` will tell the server you
@ -213,6 +219,14 @@ Last updated: 2011-01-20
## 7.0) Certain packet information
`ADMIN_PACKET_ADMIN_UPDATE_FREQUENCY` and `ADMIN_PACKET_ADMIN_POLL`
Potential gotcha: the AdminUpdateType integer type used is a
uint16 for `UPDATE_FREQUENCY`, and a uint8 for `POLL`.
This is due to boring legacy reasons.
It is safe to cast between the two when sending
(i.e cast from a uint8 to a uint16).
All `ADMIN_PACKET_SERVER_*` packets have an enum value greater 100.
`ADMIN_PACKET_SERVER_WELCOME`

@ -65,9 +65,9 @@ public:
}
NORETURN static void ThrowError(void *ud, const SQChar *s) {
SQCompiler *c = (SQCompiler *)ud;
c->Error(s);
c->Error("%s", s);
}
NORETURN void Error(const SQChar *s, ...)
NORETURN void Error(const SQChar *s, ...) WARN_FORMAT(2, 3)
{
static SQChar temp[256];
va_list vl;
@ -122,7 +122,7 @@ public:
}
Error("expected '%s'", etypename);
}
Error("expected '%c'", tok);
Error("expected '%c'", (char)tok);
}
}
SQObjectPtr ret;

@ -94,7 +94,7 @@ bool SQVM::ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,
if(!StringCat(o1, o2, trg)) return false;
}
else if(!ArithMetaMethod(op,o1,o2,trg)) {
Raise_Error("arith op %c on between '%s' and '%s'",op,GetTypeName(o1),GetTypeName(o2)); return false;
Raise_Error("arith op %c on between '%s' and '%s'",(char)op,GetTypeName(o1),GetTypeName(o2)); return false;
}
}
return true;

@ -81,7 +81,7 @@ public:
SQString *PrintObjVal(const SQObject &o);
void Raise_Error(const SQChar *s, ...);
void Raise_Error(const SQChar *s, ...) WARN_FORMAT(2, 3);
void Raise_Error(SQObjectPtr &desc);
void Raise_IdxError(const SQObject &o);
void Raise_CompareError(const SQObject &o1, const SQObject &o2);

@ -433,9 +433,12 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo
default: break;
}
bool any_available = false;
CommandCost type_check;
/* loop for all bridgetypes */
for (BridgeType brd_type = 0; brd_type != MAX_BRIDGES; brd_type++) {
if (CheckBridgeAvailability(brd_type, bridge_len).Succeeded()) {
type_check = CheckBridgeAvailability(brd_type, bridge_len);
if (type_check.Succeeded()) {
/* Re-check bridge building possibility is initial bridge builindg query indicated a bridge type dependent failure */
if (query_per_bridge_type && DoCommand(end, start, type | brd_type, CommandFlagsToDCFlags(GetCommandFlags(CMD_BUILD_BRIDGE)) | DC_QUERY_COST, CMD_BUILD_BRIDGE).Failed()) continue;
/* bridge is accepted, add to list */
@ -446,8 +449,14 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo
/* Add to terraforming & bulldozing costs the cost of the
* bridge itself (not computed with DC_QUERY_COST) */
item.cost = ret.GetCost() + (((int64)tot_bridgedata_len * _price[PR_BUILD_BRIDGE] * item.spec->price) >> 8) + infra_cost;
any_available = true;
}
}
/* give error cause if no bridges available here*/
if (!any_available)
{
errmsg = type_check.GetErrorMessage();
}
}
if (bl != nullptr && bl->size() != 0) {

@ -42,8 +42,8 @@ void SetupCargoForClimate(LandscapeID l)
assert(l < lengthof(_default_climate_cargo));
/* Reset and disable all cargo types */
memset(CargoSpec::array, 0, sizeof(CargoSpec::array));
for (CargoID i = 0; i < lengthof(CargoSpec::array); i++) {
*CargoSpec::Get(i) = {};
CargoSpec::Get(i)->bitnum = INVALID_CARGO;
/* Set defaults for newer properties, which old GRFs do not know */

@ -151,7 +151,6 @@ static void _GenerateWorld()
}
return;
}
UpdateTownCargoBitmap();
GenerateIndustries();
GenerateObjects();
GenerateTrees();

@ -2688,7 +2688,7 @@ static void ChangeIndustryProduction(Industry *i, bool monthly)
/* Prevent production to overflow or Oil Rig passengers to be over-"produced" */
new_prod = Clamp(new_prod, 1, 255);
if (((indspec->behaviour & INDUSTRYBEH_BUILT_ONWATER) != 0) && j == 1) {
if (((indspec->behaviour & INDUSTRYBEH_BUILT_ONWATER) != 0) && j == 1 && !(indspec->behaviour & INDUSTRYBEH_WATER_NO_CLAMP_PROD)) {
new_prod = Clamp(new_prod, 0, 16);
}

@ -80,6 +80,7 @@ enum IndustryBehaviour {
INDUSTRYBEH_NOBUILT_MAPCREATION = 1 << 16, ///< Do not force one instance of this type to appear on map generation
INDUSTRYBEH_CANCLOSE_LASTINSTANCE = 1 << 17, ///< Allow closing down the last instance of this type
INDUSTRYBEH_CARGOTYPES_UNLIMITED = 1 << 18, ///< Allow produced/accepted cargoes callbacks to supply more than 2 and 3 types
INDUSTRYBEH_WATER_NO_CLAMP_PROD = 1 << 19, ///< Do not clamp production of second cargo for water industries
};
DECLARE_ENUM_AS_BIT_SET(IndustryBehaviour)

@ -109,8 +109,6 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin
RebuildTownKdtree();
RebuildViewportKdtree();
UpdateTownCargoBitmap();
FreeSignalPrograms();
FreeSignalDependencies();

@ -90,7 +90,7 @@ struct CStrA : public CBlobT<char>
}
/** Add formatted string (like vsprintf) at the end of existing contents. */
int AddFormatL(const char *format, va_list args)
int AddFormatL(const char *format, va_list args) WARN_FORMAT(2, 0)
{
size_t addSize = max<size_t>(strlen(format), 16);
addSize += addSize / 2;

@ -134,7 +134,7 @@ protected:
/**
* Register updates to be sent at certain frequencies (as announced in the PROTOCOL packet):
* uint16 Update type (see #AdminUpdateType).
* uint16 Update type (see #AdminUpdateType). Note integer type - see "Certain Packet Information" in docs/admin_network.md.
* uint16 Update frequency (see #AdminUpdateFrequency), setting #ADMIN_FREQUENCY_POLL is always ignored.
* @param p The packet that was just received.
* @return The state the network should have.
@ -143,7 +143,7 @@ protected:
/**
* Poll the server for certain updates, an invalid poll (e.g. not existent id) gets silently dropped:
* uint8 #AdminUpdateType the server should answer for, only if #AdminUpdateFrequency #ADMIN_FREQUENCY_POLL is advertised in the PROTOCOL packet.
* uint8 #AdminUpdateType the server should answer for, only if #AdminUpdateFrequency #ADMIN_FREQUENCY_POLL is advertised in the PROTOCOL packet. Note integer type - see "Certain Packet Information" in docs/admin_network.md.
* uint32 ID relevant to the packet type, e.g.
* - the client ID for #ADMIN_UPDATE_CLIENT_INFO. Use UINT32_MAX to show all clients.
* - the company ID for #ADMIN_UPDATE_COMPANY_INFO. Use UINT32_MAX to show all companies.

@ -1595,7 +1595,7 @@ struct NetworkLobbyWindow : public Window {
NetworkTCPQueryServer(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port)); // company info
NetworkUDPQueryServer(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port)); // general data
/* Clear the information so removed companies don't remain */
memset(this->company_info, 0, sizeof(this->company_info));
for (auto &company : this->company_info) company = {};
break;
}
}

@ -671,6 +671,11 @@ static bool ReadyForNextNewsItem()
/** Move to the next ticker item */
static void MoveToNextTickerItem()
{
/* There is no status bar, so no reason to show news;
* especially important with the end game screen when
* there is no status bar but possible news. */
if (FindWindowById(WC_STATUS_BAR, 0) == nullptr) return;
InvalidateWindowData(WC_STATUS_BAR, 0, SBI_NEWS_DELETED); // invalidate the statusbar
/* if we're not at the last item, then move on */
@ -702,6 +707,11 @@ static void MoveToNextTickerItem()
/** Move to the next news item */
static void MoveToNextNewsItem()
{
/* There is no status bar, so no reason to show news;
* especially important with the end game screen when
* there is no status bar but possible news. */
if (FindWindowById(WC_STATUS_BAR, 0) == nullptr) return;
DeleteWindowById(WC_NEWS_WINDOW, 0); // close the newspapers window if shown
_forced_news = nullptr;
@ -995,11 +1005,6 @@ void NewsLoop()
/* no news item yet */
if (_total_news == 0) return;
/* There is no status bar, so no reason to show news;
* especially important with the end game screen when
* there is no status bar but possible news. */
if (FindWindowById(WC_STATUS_BAR, 0) == nullptr) return;
static byte _last_clean_month = 0;
if (_last_clean_month != _cur_month) {

@ -1368,13 +1368,9 @@ void CheckCaches(bool force_check, std::function<void(const char *)> log)
/* Check the town caches. */
std::vector<TownCache> old_town_caches;
std::vector<CargoTypes> old_town_cargo_accepted_totals;
std::vector<CargoTypes> old_town_cargo_produced;
std::vector<StationList> old_town_stations_nears;
for (const Town *t : Town::Iterate()) {
old_town_caches.push_back(t->cache);
old_town_cargo_accepted_totals.push_back(t->cargo_accepted_total);
old_town_cargo_produced.push_back(t->cargo_produced);
old_town_stations_nears.push_back(t->stations_near);
}
@ -1392,8 +1388,6 @@ void CheckCaches(bool force_check, std::function<void(const char *)> log)
old_industry_stations_nears.push_back(ind->stations_near);
}
const CargoTypes old_town_cargoes_accepted = _town_cargoes_accepted;
extern void RebuildTownCaches(bool cargo_update_required);
RebuildTownCaches(false);
RebuildSubsidisedSourceAndDestinationCache();
@ -1405,20 +1399,11 @@ void CheckCaches(bool force_check, std::function<void(const char *)> log)
if (MemCmpT(old_town_caches.data() + i, &t->cache) != 0) {
CCLOG("town cache mismatch: town %i", (int)t->index);
}
if (old_town_cargo_accepted_totals[i] != t->cargo_accepted_total) {
CCLOG("town cargo_accepted_total mismatch: town %i, old: " OTTD_PRINTFHEX64 ". new: " OTTD_PRINTFHEX64, (int)t->index, old_town_cargo_accepted_totals[i], t->cargo_accepted_total);
}
if (old_town_cargo_produced[i] != t->cargo_produced) {
CCLOG("town cargo_produced mismatch: town %i, old: " OTTD_PRINTFHEX64 ". new: " OTTD_PRINTFHEX64, (int)t->index, old_town_cargo_produced[i], t->cargo_produced);
}
if (old_town_stations_nears[i] != t->stations_near) {
CCLOG("town stations_near mismatch: town %i, (old size: %u, new size: %u)", (int)t->index, (uint)old_town_stations_nears[i].size(), (uint)t->stations_near.size());
}
i++;
}
if (old_town_cargoes_accepted != _town_cargoes_accepted) {
CCLOG("_town_cargoes_accepted mismatch: old: " OTTD_PRINTFHEX64 ". new: " OTTD_PRINTFHEX64, old_town_cargoes_accepted, _town_cargoes_accepted);
}
i = 0;
for (Station *st : Station::Iterate()) {
if (old_station_industries_nears[i] != st->industries_near) {

@ -1671,14 +1671,15 @@ void DrawRoadCatenary(const TileInfo *ti)
* @param dx the offset from the top of the BB of the tile
* @param dy the offset from the top of the BB of the tile
* @param h the height of the sprite to draw
* @param transparent whether the sprite should be transparent (used for roadside trees)
*/
static void DrawRoadDetail(SpriteID img, const TileInfo *ti, int dx, int dy, int h)
static void DrawRoadDetail(SpriteID img, const TileInfo *ti, int dx, int dy, int h, bool transparent)
{
int x = ti->x | dx;
int y = ti->y | dy;
int z = ti->z;
if (ti->tileh != SLOPE_FLAT) z = GetSlopePixelZ(x, y);
AddSortableSpriteToDraw(img, PAL_NONE, x, y, 2, 2, h, z);
AddSortableSpriteToDraw(img, PAL_NONE, x, y, 2, 2, h, z, transparent);
}
/**
@ -1831,9 +1832,12 @@ void DrawRoadBits(TileInfo *ti)
/* If there are no road bits, return, as there is nothing left to do */
if (HasAtMostOneBit(road)) return;
if (roadside == ROADSIDE_TREES && IsInvisibilitySet(TO_TREES)) return;
bool is_transparent = roadside == ROADSIDE_TREES && IsTransparencySet(TO_TREES);
/* Draw extra details. */
for (const DrawRoadTileStruct *drts = _road_display_table[roadside][road | tram]; drts->image != 0; drts++) {
DrawRoadDetail(drts->image, ti, drts->subcoord_x, drts->subcoord_y, 0x10);
DrawRoadDetail(drts->image, ti, drts->subcoord_x, drts->subcoord_y, 0x10, is_transparent);
}
}

@ -3113,22 +3113,6 @@ bool AfterLoadGame()
* which is done by StartupEngines(). */
if (gcf_res != GLC_ALL_GOOD) StartupEngines();
if (SlXvIsFeatureMissing(XSLFI_TOWN_CARGO_MATRIX)) {
/* Update cargo acceptance map of towns. */
for (Town *town : Town::Iterate()) {
town->cargo_accepted.Clear();
}
for (TileIndex t = 0; t < map_size; t++) {
if (!IsTileType(t, MP_HOUSE)) continue;
Town::Get(GetTownIndex(t))->cargo_accepted.Add(t);
}
for (Town *town : Town::Iterate()) {
UpdateTownCargoes(town);
}
UpdateTownCargoBitmap();
}
/* Set some breakdown-related variables to the correct values. */
if (SlXvIsFeatureMissing(XSLFI_IMPROVED_BREAKDOWNS)) {
for (Train *v : Train::Iterate()) {

@ -107,7 +107,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_LINKGRAPH_MODES, XSCF_NULL, 1, 1, "linkgraph_modes", nullptr, nullptr, nullptr },
{ XSLFI_GAME_EVENTS, XSCF_NULL, 1, 1, "game_events", nullptr, nullptr, nullptr },
{ XSLFI_ROAD_LAYOUT_CHANGE_CTR, XSCF_NULL, 1, 1, "road_layout_change_ctr", nullptr, nullptr, nullptr },
{ XSLFI_TOWN_CARGO_MATRIX, XSCF_NULL, 1, 1, "town_cargo_matrix", nullptr, nullptr, nullptr },
{ XSLFI_TOWN_CARGO_MATRIX, XSCF_NULL, 0, 1, "town_cargo_matrix", nullptr, nullptr, nullptr },
{ XSLFI_STATE_CHECKSUM, XSCF_NULL, 1, 1, "state_checksum", nullptr, nullptr, nullptr },
{ XSLFI_DEBUG, XSCF_IGNORABLE_ALL, 1, 1, "debug", nullptr, nullptr, "DBGL,DBGC" },
{ XSLFI_FLOW_STAT_FLAGS, XSCF_NULL, 1, 1, "flow_stat_flags", nullptr, nullptr, nullptr },

@ -72,7 +72,7 @@ enum SlXvFeatureIndex {
XSLFI_LINKGRAPH_MODES, ///< Linkgraph additional distribution modes
XSLFI_GAME_EVENTS, ///< Game event flags
XSLFI_ROAD_LAYOUT_CHANGE_CTR, ///< Road layout change counter
XSLFI_TOWN_CARGO_MATRIX, ///< Town cargo matrix savegame format changes
XSLFI_TOWN_CARGO_MATRIX, ///< Town cargo matrix savegame format changes (now obsolete)
XSLFI_STATE_CHECKSUM, ///< State checksum
XSLFI_DEBUG, ///< Debugging info
XSLFI_FLOW_STAT_FLAGS, ///< FlowStat flags

@ -48,13 +48,7 @@ void RebuildTownCaches(bool cargo_update_required)
/* Update the population and num_house dependent values */
for (Town *town : Town::Iterate()) {
UpdateTownRadius(town);
if (cargo_update_required) {
UpdateTownCargoes(town);
} else {
UpdateTownCargoTotal(town);
}
}
UpdateTownCargoBitmap();
}
/**
@ -215,8 +209,8 @@ static const SaveLoad _town_desc[] = {
SLE_CONDLST(Town, psa_list, REF_STORAGE, SLV_161, SL_MAX_VERSION),
SLE_CONDVAR(Town, cargo_produced, SLE_FILE_U32 | SLE_VAR_U64, SLV_166, SLV_EXTEND_CARGOTYPES),
SLE_CONDVAR(Town, cargo_produced, SLE_UINT64, SLV_EXTEND_CARGOTYPES, SL_MAX_VERSION),
SLE_CONDNULL(4, SLV_166, SLV_EXTEND_CARGOTYPES), ///< cargo_produced, no longer in use
SLE_CONDNULL(8, SLV_EXTEND_CARGOTYPES, SL_MAX_VERSION), ///< cargo_produced, no longer in use
/* reserve extra space in savegame here. (currently 30 bytes) */
SLE_CONDNULL(30, SLV_2, SL_MAX_VERSION),
@ -272,19 +266,6 @@ static void Load_HIDS()
Load_NewGRFMapping(_house_mngr);
}
const SaveLoad *GetTileMatrixDesc()
{
/* Here due to private member vars. */
static const SaveLoad _tilematrix_desc[] = {
SLE_VAR(AcceptanceMatrix, area.tile, SLE_UINT32),
SLE_VAR(AcceptanceMatrix, area.w, SLE_UINT16),
SLE_VAR(AcceptanceMatrix, area.h, SLE_UINT16),
SLE_END()
};
return _tilematrix_desc;
}
static void RealSave_Town(Town *t)
{
SlObjectSaveFiltered(t, _filtered_town_desc.data());
@ -296,11 +277,10 @@ static void RealSave_Town(Town *t)
SlObjectSaveFiltered(&t->received[i], _filtered_town_received_desc.data());
}
SlObjectSaveFiltered(&t->cargo_accepted, GetTileMatrixDesc()); // GetTileMatrixDesc() has no conditionals
if (t->cargo_accepted.area.w != 0) {
uint arr_len = t->cargo_accepted.area.w / AcceptanceMatrix::GRID * t->cargo_accepted.area.h / AcceptanceMatrix::GRID;
SlArray(t->cargo_accepted.data, arr_len, SLE_UINT64);
}
/* Write an empty matrix to avoid bumping savegame version. */
SlWriteUint32(0); // tile
SlWriteUint16(0); // w
SlWriteUint16(0); // h
}
static void Save_TOWN()
@ -339,23 +319,13 @@ static void Load_TOWN()
SlErrorCorrupt("Invalid town name generator");
}
if (!IsSavegameVersionBefore(SLV_166) && SlXvIsFeatureMissing(XSLFI_TOWN_CARGO_MATRIX)) {
if (!IsSavegameVersionBefore(SLV_166) || SlXvIsFeaturePresent(XSLFI_TOWN_CARGO_MATRIX)) {
SlSkipBytes(4); // tile
uint16 w = SlReadUint16();
uint16 h = SlReadUint16();
if (w != 0) {
SlSkipBytes(4 * (w / 4 * h / 4));
}
}
if (SlXvIsFeaturePresent(XSLFI_TOWN_CARGO_MATRIX)) {
SlObjectLoadFiltered(&t->cargo_accepted, GetTileMatrixDesc()); // GetTileMatrixDesc() has no conditionals
if (t->cargo_accepted.area.w != 0) {
uint arr_len = t->cargo_accepted.area.w / AcceptanceMatrix::GRID * t->cargo_accepted.area.h / AcceptanceMatrix::GRID;
t->cargo_accepted.data = MallocT<CargoTypes>(arr_len);
SlArray(t->cargo_accepted.data, arr_len, SLE_UINT64);
SlSkipBytes((SlXvIsFeaturePresent(XSLFI_TOWN_CARGO_MATRIX) ? 8 : 4) * (w / 4 * h / 4));
}
/* Rebuild total cargo acceptance. */
UpdateTownCargoTotal(t);
}
}
}

@ -20,6 +20,7 @@
#include "company_func.h"
#include "strings_func.h"
#include "error.h"
#include "textbuf_gui.h"
#include "window_gui.h"
#include "window_func.h"
#include "tile_map.h"
@ -851,6 +852,45 @@ bool MakeHeightmapScreenshot(const char *filename)
return sf->proc(filename, HeightmapCallback, nullptr, MapSizeX(), MapSizeY(), 8, palette);
}
static ScreenshotType _confirmed_screenshot_type; ///< Screenshot type the current query is about to confirm.
/**
* Callback on the confirmation window for huge screenshots.
* @param w Window with viewport
* @param confirmed true on confirmation
*/
static void ScreenshotConfirmationCallback(Window *w, bool confirmed)
{
if (confirmed) MakeScreenshot(_confirmed_screenshot_type, nullptr);
}
/**
* Make a screenshot.
* Ask for confirmation first if the screenshot will be huge.
* @param t Screenshot type: World, defaultzoom, heightmap or viewport screenshot
* @see MakeScreenshot
*/
void MakeScreenshotWithConfirm(ScreenshotType t)
{
ViewPort vp;
SetupScreenshotViewport(t, &vp);
bool heightmap_or_minimap = t == SC_HEIGHTMAP || t == SC_MINIMAP;
uint64_t width = (heightmap_or_minimap ? MapSizeX() : vp.width);
uint64_t height = (heightmap_or_minimap ? MapSizeY() : vp.height);
if (width * height > 8192 * 8192) {
/* Ask for confirmation */
_confirmed_screenshot_type = t;
SetDParam(0, width);
SetDParam(1, height);
ShowQuery(STR_WARNING_SCREENSHOT_SIZE_CAPTION, STR_WARNING_SCREENSHOT_SIZE_MESSAGE, nullptr, ScreenshotConfirmationCallback);
} else {
/* Less than 64M pixels, just do it */
MakeScreenshot(t, nullptr);
}
}
/**
* Show a a success or failure message indicating the result of a screenshot action
* @param ret whether the screenshot action was successful
@ -866,10 +906,12 @@ static void ShowScreenshotResultMessage(bool ret)
}
/**
* Make an actual screenshot.
* Make a screenshot.
* Unconditionally take a screenshot of the requested type.
* @param t the type of screenshot to make.
* @param name the name to give to the screenshot.
* @return true iff the screenshot was made successfully
* @see MakeScreenshotWithConfirm
*/
bool MakeScreenshot(ScreenshotType t, const char *name)
{

@ -30,6 +30,7 @@ class SmallMapWindow;
void SetupScreenshotViewport(ScreenshotType t, struct ViewPort *vp);
bool MakeHeightmapScreenshot(const char *filename);
bool MakeSmallMapScreenshot(unsigned int width, unsigned int height, SmallMapWindow *window);
void MakeScreenshotWithConfirm(ScreenshotType t);
bool MakeScreenshot(ScreenshotType t, const char *name);
bool MakeMinimapWorldScreenshot(const char *name);
void SetScreenshotAuxiliaryText(const char *key, const char *value);

@ -8,31 +8,26 @@
/** @file screenshot_gui.cpp GUI functions related to screenshots. */
#include "stdafx.h"
#include "gui.h"
#include "viewport_func.h"
#include "window_func.h"
#include "window_gui.h"
#include "screenshot.h"
#include "textbuf_gui.h"
#include "strings_func.h"
#include "widgets/screenshot_widget.h"
#include "table/strings.h"
static ScreenshotType _screenshot_type;
struct ScreenshotWindow : Window {
ScreenshotWindow(WindowDesc *desc) : Window(desc) {
ScreenshotWindow(WindowDesc *desc) : Window(desc)
{
this->CreateNestedTree();
this->FinishInitNested();
}
void OnPaint() override {
void OnPaint() override
{
this->DrawWidgets();
}
void OnClick(Point pt, int widget, int click_count) override {
void OnClick(Point pt, int widget, int click_count) override
{
if (widget < 0) return;
ScreenshotType st;
switch (widget) {
@ -44,37 +39,7 @@ struct ScreenshotWindow : Window {
case WID_SC_TAKE_HEIGHTMAP: st = SC_HEIGHTMAP; break;
case WID_SC_TAKE_MINIMAP: st = SC_MINIMAP; break;
}
TakeScreenshot(st);
}
/**
* Make a screenshot.
* Ask for confirmation if the screenshot will be huge.
* @param t Screenshot type: World, defaultzoom, heightmap or viewport screenshot
*/
static void TakeScreenshot(ScreenshotType st) {
ViewPort vp;
SetupScreenshotViewport(st, &vp);
if ((uint64)vp.width * (uint64)vp.height > 8192 * 8192) {
/* Ask for confirmation */
_screenshot_type = st;
SetDParam(0, vp.width);
SetDParam(1, vp.height);
ShowQuery(STR_WARNING_SCREENSHOT_SIZE_CAPTION, STR_WARNING_SCREENSHOT_SIZE_MESSAGE, nullptr, ScreenshotConfirmationCallback);
}
else {
/* Less than 64M pixels, just do it */
MakeScreenshot(st, nullptr);
}
}
/**
* Callback on the confirmation window for huge screenshots.
* @param w Window with viewport
* @param confirmed true on confirmation
*/
static void ScreenshotConfirmationCallback(Window *w, bool confirmed) {
if (confirmed) MakeScreenshot(_screenshot_type, nullptr);
MakeScreenshotWithConfirm(st);
}
};
@ -102,7 +67,8 @@ static WindowDesc _screenshot_window_desc(
_nested_screenshot, lengthof(_nested_screenshot)
);
void ShowScreenshotWindow() {
void ShowScreenshotWindow()
{
DeleteWindowById(WC_SCREENSHOT, 0);
new ScreenshotWindow(&_screenshot_window_desc);
}

@ -99,7 +99,7 @@ public:
* Types of expenses.
* @api -ai
*/
enum ExpensesType {
enum ExpensesType : byte {
EXPENSES_CONSTRUCTION = ::EXPENSES_CONSTRUCTION, ///< Construction costs.
EXPENSES_NEW_VEHICLES = ::EXPENSES_NEW_VEHICLES, ///< New vehicles.
EXPENSES_TRAIN_RUN = ::EXPENSES_TRAIN_RUN, ///< Running costs trains.

@ -36,7 +36,7 @@ public:
/**
* Goal types that can be given to a goal.
*/
enum GoalType {
enum GoalType : byte {
/* Note: these values represent part of the in-game GoalType enum */
GT_NONE = ::GT_NONE, ///< Destination is not linked.
GT_TILE = ::GT_TILE, ///< Destination is a tile.

@ -40,7 +40,7 @@ public:
/**
* Types of rail known to the game.
*/
enum RailType {
enum RailType : byte {
/* Note: these values represent part of the in-game static values */
RAILTYPE_INVALID = ::INVALID_RAILTYPE, ///< Invalid RailType.
};

@ -60,7 +60,7 @@ public:
/**
* Road/tram types
*/
enum RoadTramTypes {
enum RoadTramTypes : uint8 {
ROADTRAMTYPES_ROAD = ::RTTB_ROAD, ///< Road road types.
ROADTRAMTYPES_TRAM = ::RTTB_TRAM, ///< Tram road types.
};

@ -119,16 +119,16 @@ static inline bool StoryPageElementTypeRequiresText(StoryPageElementType type)
uint32 refid = 0;
TileIndex reftile = 0;
switch (type) {
case SPET_LOCATION:
case ::SPET_LOCATION:
reftile = reference;
break;
case SPET_GOAL:
case SPET_BUTTON_PUSH:
case SPET_BUTTON_TILE:
case SPET_BUTTON_VEHICLE:
case ::SPET_GOAL:
case ::SPET_BUTTON_PUSH:
case ::SPET_BUTTON_TILE:
case ::SPET_BUTTON_VEHICLE:
refid = reference;
break;
case SPET_TEXT:
case ::SPET_TEXT:
break;
default:
NOT_REACHED();

@ -57,7 +57,7 @@ public:
/**
* Story page element types.
*/
enum StoryPageElementType {
enum StoryPageElementType : byte {
SPET_TEXT = ::SPET_TEXT, ///< An element that displays a block of text.
SPET_LOCATION = ::SPET_LOCATION, ///< An element that displays a single line of text along with a button to view the referenced location.
SPET_GOAL = ::SPET_GOAL, ///< An element that displays a goal.
@ -75,7 +75,7 @@ public:
* Formatting and layout flags for story page buttons.
* The SPBF_FLOAT_LEFT and SPBF_FLOAT_RIGHT flags can not be combined.
*/
enum StoryPageButtonFlags {
enum StoryPageButtonFlags : byte {
SPBF_NONE = ::SPBF_NONE, ///< No special formatting for button.
SPBF_FLOAT_LEFT = ::SPBF_FLOAT_LEFT, ///< Button is placed to the left of the following paragraph.
SPBF_FLOAT_RIGHT = ::SPBF_FLOAT_RIGHT, ///< Button is placed to the right of the following paragraph.
@ -84,7 +84,7 @@ public:
/**
* Mouse cursors usable by story page buttons.
*/
enum StoryPageButtonCursor {
enum StoryPageButtonCursor : byte {
SPBC_MOUSE = ::SPBC_MOUSE,
SPBC_ZZZ = ::SPBC_ZZZ,
SPBC_BUOY = ::SPBC_BUOY,

@ -63,12 +63,12 @@ protected:
/**
* If a user runs 'print' inside a script, this function gets the params.
*/
static void PrintFunc(HSQUIRRELVM vm, const SQChar *s, ...);
static void PrintFunc(HSQUIRRELVM vm, const SQChar *s, ...) WARN_FORMAT(2, 3);
/**
* If an error has to be print, this function is called.
*/
static void ErrorPrintFunc(HSQUIRRELVM vm, const SQChar *s, ...);
static void ErrorPrintFunc(HSQUIRRELVM vm, const SQChar *s, ...) WARN_FORMAT(2, 3);
public:
Squirrel(const char *APIName);

@ -35,7 +35,7 @@ char *strecpy(char *dst, const char *src, const char *last, bool quiet_mode = fa
char *stredup(const char *src, const char *last = nullptr);
int CDECL seprintf(char *str, const char *last, const char *format, ...) WARN_FORMAT(3, 4);
int CDECL vseprintf(char *str, const char *last, const char *format, va_list ap);
int CDECL vseprintf(char *str, const char *last, const char *format, va_list ap) WARN_FORMAT(3, 0);
char *CDECL str_fmt(const char *str, ...) WARN_FORMAT(1, 2);
char *str_vfmt(const char *str, va_list ap);

@ -328,20 +328,27 @@ bool FindSubsidyTownCargoRoute()
const Town *src_town = Town::GetRandom();
if (src_town->cache.population < SUBSIDY_CARGO_MIN_POPULATION) return false;
CargoTypes town_cargo_produced = src_town->cargo_produced;
CargoArray town_cargo_produced = GetProductionAroundTiles(src_town->xy, 1, 1, SUBSIDY_TOWN_CARGO_RADIUS);
/* Passenger subsidies are not handled here. */
ClrBit(town_cargo_produced, CT_PASSENGERS);
town_cargo_produced[CT_PASSENGERS] = 0;
uint8 cargo_count = 0;
for (CargoID i = 0; i < NUM_CARGO; i++) {
if (town_cargo_produced[i] > 0) cargo_count++;
}
/* No cargo produced at all? */
if (town_cargo_produced == 0) return false;
if (cargo_count == 0) return false;
/* Choose a random cargo that is produced in the town. */
uint8 cargo_number = RandomRange(CountBits(town_cargo_produced));
uint8 cargo_number = RandomRange(cargo_count);
CargoID cid;
FOR_EACH_SET_CARGO_ID(cid, town_cargo_produced) {
if (cargo_number == 0) break;
cargo_number--;
for (cid = 0; cid < NUM_CARGO; cid++) {
if (town_cargo_produced[cid] > 0) {
if (cargo_number == 0) break;
cargo_number--;
}
}
/* Avoid using invalid NewGRF cargoes. */
@ -416,17 +423,18 @@ bool FindSubsidyIndustryCargoRoute()
*/
bool FindSubsidyCargoDestination(CargoID cid, SourceType src_type, SourceID src)
{
/* Choose a random destination. Only consider towns if they can accept the cargo. */
SourceType dst_type = (HasBit(_town_cargoes_accepted, cid) && Chance16(1, 2)) ? ST_TOWN : ST_INDUSTRY;
/* Choose a random destination. */
SourceType dst_type = Chance16(1, 2) ? ST_TOWN : ST_INDUSTRY;
SourceID dst;
switch (dst_type) {
case ST_TOWN: {
/* Select a random town. */
const Town *dst_town = Town::GetRandom();
CargoArray town_cargo_accepted = GetAcceptanceAroundTiles(dst_town->xy, 1, 1, SUBSIDY_TOWN_CARGO_RADIUS);
/* Check if the town can accept this cargo. */
if (!HasBit(dst_town->cargo_accepted_total, cid)) return false;
if (town_cargo_accepted[cid] < 8) return false;
dst = dst_town->index;
break;

@ -57,5 +57,6 @@ static const uint SUBSIDY_PAX_MIN_POPULATION = 400; ///< Min. population of to
static const uint SUBSIDY_CARGO_MIN_POPULATION = 900; ///< Min. population of destination town for cargo route
static const uint SUBSIDY_MAX_PCT_TRANSPORTED = 42; ///< Subsidy will be created only for towns/industries with less % transported
static const uint SUBSIDY_MAX_DISTANCE = 70; ///< Max. length of subsidised route (DistanceManhattan)
static const uint SUBSIDY_TOWN_CARGO_RADIUS = 6; ///< Extent of a tile area around town center when scanning for town cargo acceptance and production (6 ~= min catchmement + min station / 2)
#endif /* SUBSIDY_BASE_H */

@ -670,18 +670,6 @@ class NIHTown : public NIHelper {
seprintf(buffer, lastof(buffer), " Index: %u", index);
print(buffer);
char *b = buffer;
b += seprintf(b, lastof(buffer), " cargo_produced: ");
SetDParam(0, t->cargo_produced);
b = GetString(b, STR_JUST_CARGO_LIST, lastof(buffer));
print(buffer);
b = buffer;
b += seprintf(b, lastof(buffer), " cargo_accepted_total: ");
SetDParam(0, t->cargo_accepted_total);
b = GetString(b, STR_JUST_CARGO_LIST, lastof(buffer));
print(buffer);
seprintf(buffer, lastof(buffer), " Nearby stations: %u", (uint) t->stations_near.size());
print(buffer);
for (const Station *st : t->stations_near) {

@ -3343,7 +3343,7 @@ type = SLE_UINT8
from = SLV_30
def = 32
min = 12
max = 48
max = 128
str = STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE
strval = STR_CONFIG_SETTING_TILE_LENGTH
strhelp = STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT

@ -68,8 +68,6 @@ RailType _last_built_railtype;
RoadType _last_built_roadtype;
RoadType _last_built_tramtype;
static ScreenshotType _confirmed_screenshot_type; ///< Screenshot type the current query is about to confirm.
/** Toobar modes */
enum ToolbarMode {
TB_NORMAL,
@ -1084,37 +1082,6 @@ static CallBackFunction ToolbarHelpClick(Window *w)
return CBF_NONE;
}
/**
* Callback on the confirmation window for huge screenshots.
* @param w Window with viewport
* @param confirmed true on confirmation
*/
static void ScreenshotConfirmCallback(Window *w, bool confirmed)
{
if (confirmed) MakeScreenshot(_confirmed_screenshot_type, nullptr);
}
/**
* Make a screenshot of the world.
* Ask for confirmation if the screenshot will be huge.
* @param t Screenshot type: World or viewport screenshot
*/
static void MenuClickScreenshot(ScreenshotType t)
{
ViewPort vp;
SetupScreenshotViewport(t, &vp);
if ((uint64)vp.width * (uint64)vp.height > 8192 * 8192) {
/* Ask for confirmation */
SetDParam(0, vp.width);
SetDParam(1, vp.height);
_confirmed_screenshot_type = t;
ShowQuery(STR_WARNING_SCREENSHOT_SIZE_CAPTION, STR_WARNING_SCREENSHOT_SIZE_MESSAGE, nullptr, ScreenshotConfirmCallback);
} else {
/* Less than 64M pixels, just do it */
MakeScreenshot(t, nullptr);
}
}
/**
* Toggle drawing of sprites' bounding boxes.
* @note has only an effect when newgrf_developer_tools are active.
@ -2151,10 +2118,10 @@ struct MainToolbarWindow : Window {
case MTHK_BUILD_TREES: ShowBuildTreesToolbar(); break;
case MTHK_MUSIC: ShowMusicWindow(); break;
case MTHK_AI_DEBUG: ShowAIDebugWindow(); break;
case MTHK_SMALL_SCREENSHOT: MenuClickScreenshot(SC_VIEWPORT); break;
case MTHK_ZOOMEDIN_SCREENSHOT: MenuClickScreenshot(SC_ZOOMEDIN); break;
case MTHK_DEFAULTZOOM_SCREENSHOT: MenuClickScreenshot(SC_DEFAULTZOOM); break;
case MTHK_GIANT_SCREENSHOT: MenuClickScreenshot(SC_WORLD); break;
case MTHK_SMALL_SCREENSHOT: MakeScreenshotWithConfirm(SC_VIEWPORT); break;
case MTHK_ZOOMEDIN_SCREENSHOT: MakeScreenshotWithConfirm(SC_ZOOMEDIN); break;
case MTHK_DEFAULTZOOM_SCREENSHOT: MakeScreenshotWithConfirm(SC_DEFAULTZOOM); break;
case MTHK_GIANT_SCREENSHOT: MakeScreenshotWithConfirm(SC_WORLD); break;
case MTHK_CHEATS: ShowCheatWindow(); break;
case MTHK_TERRAFORM: ShowTerraformToolbar(); break;
case MTHK_EXTRA_VIEWPORT: ShowExtraViewPortWindowForTileUnderCursor(); break;
@ -2528,10 +2495,10 @@ struct ScenarioEditorToolbarWindow : Window {
case MTEHK_SIGN: cbf = ToolbarScenPlaceSign(this); break;
case MTEHK_MUSIC: ShowMusicWindow(); break;
case MTEHK_LANDINFO: cbf = PlaceLandBlockInfo(); break;
case MTEHK_SMALL_SCREENSHOT: MenuClickScreenshot(SC_VIEWPORT); break;
case MTEHK_ZOOMEDIN_SCREENSHOT: MenuClickScreenshot(SC_ZOOMEDIN); break;
case MTEHK_DEFAULTZOOM_SCREENSHOT: MenuClickScreenshot(SC_DEFAULTZOOM); break;
case MTEHK_GIANT_SCREENSHOT: MenuClickScreenshot(SC_WORLD); break;
case MTEHK_SMALL_SCREENSHOT: MakeScreenshotWithConfirm(SC_VIEWPORT); break;
case MTEHK_ZOOMEDIN_SCREENSHOT: MakeScreenshotWithConfirm(SC_ZOOMEDIN); break;
case MTEHK_DEFAULTZOOM_SCREENSHOT: MakeScreenshotWithConfirm(SC_DEFAULTZOOM); break;
case MTEHK_GIANT_SCREENSHOT: MakeScreenshotWithConfirm(SC_WORLD); break;
case MTEHK_ZOOM_IN: ToolbarZoomInClick(this); break;
case MTEHK_ZOOM_OUT: ToolbarZoomOutClick(this); break;
case MTEHK_TERRAFORM: ShowEditorTerraformToolbar(); break;

@ -15,7 +15,6 @@
#include "subsidy_type.h"
#include "newgrf_storage.h"
#include "cargotype.h"
#include "tilematrix_type.hpp"
#include "openttd.h"
#include "table/strings.h"
#include "company_func.h"
@ -29,8 +28,6 @@ struct BuildingCounts {
T class_count[HOUSE_CLASS_MAX];
};
typedef TileMatrix<CargoTypes, 4> AcceptanceMatrix;
static const uint CUSTOM_TOWN_NUMBER_DIFFICULTY = 4; ///< value for custom town number in difficulty settings
static const uint CUSTOM_TOWN_MAX_NUMBER = 5000; ///< this is the maximum number of towns a user can specify in customisation
@ -89,10 +86,6 @@ struct Town : TownPool::PoolItem<&_town_pool> {
inline byte GetPercentTransported(CargoID cid) const { return this->supplied[cid].old_act * 256 / (this->supplied[cid].old_max + 1); }
/* Cargo production and acceptance stats. */
CargoTypes cargo_produced; ///< Bitmap of all cargoes produced by houses in this town.
AcceptanceMatrix cargo_accepted; ///< Bitmap of cargoes accepted by houses for each 4*4 (really 12*12) map square of the town.
CargoTypes cargo_accepted_total; ///< NOSAVE: Bitmap of all cargoes accepted by houses in this town.
StationList stations_near; ///< NOSAVE: List of nearby stations.
uint16 time_until_rebuild; ///< time until we rebuild a house
@ -233,9 +226,6 @@ void ResetHouses();
void ClearTownHouse(Town *t, TileIndex tile);
void UpdateTownMaxPass(Town *t);
void UpdateTownRadius(Town *t);
void UpdateTownCargoes(Town *t);
void UpdateTownCargoTotal(Town *t);
void UpdateTownCargoBitmap();
CommandCost CheckIfAuthorityAllowsNewStation(TileIndex tile, DoCommandFlag flags);
Town *ClosestTownFromTile(TileIndex tile, uint threshold);
void ChangeTownRating(Town *t, int add, int max, DoCommandFlag flags);
@ -344,8 +334,6 @@ static inline uint16 TownTicksToGameTicks(uint16 ticks) {
}
extern CargoTypes _town_cargoes_accepted;
RoadType GetTownRoadType(const Town *t);
#endif /* TOWN_H */

@ -60,7 +60,6 @@
#include "safeguards.h"
TownID _new_town_id;
CargoTypes _town_cargoes_accepted; ///< Bitmap of all cargoes accepted by houses.
/* Initialize the town-pool */
TownPool _town_pool("Town");
@ -939,91 +938,6 @@ static void ChangeTileOwner_Town(TileIndex tile, Owner old_owner, Owner new_owne
/* not used */
}
/** Update the total cargo acceptance of the whole town.
* @param t The town to update.
*/
void UpdateTownCargoTotal(Town *t)
{
t->cargo_accepted_total = 0;
const TileArea &area = t->cargo_accepted.GetArea();
TILE_AREA_LOOP_STEP(tile, area, AcceptanceMatrix::GRID) {
t->cargo_accepted_total |= t->cargo_accepted[tile];
}
}
/**
* Update accepted town cargoes around a specific tile.
* @param t The town to update.
* @param start Update the values around this tile.
* @param update_total Set to true if the total cargo acceptance should be updated.
*/
static void UpdateTownCargoesSingleGridArea(Town *t, TileIndex start, bool update_total = true)
{
CargoArray accepted, produced;
CargoTypes dummy = 0;
/* Gather acceptance for all houses in an area around the start tile. */
TileArea area = AcceptanceMatrix::GetAreaForTile(start, 1);
TILE_AREA_LOOP(tile, area) {
if (!IsTileType(tile, MP_HOUSE) || GetTownIndex(tile) != t->index) continue;
AddAcceptedCargo_Town(tile, accepted, &dummy);
AddProducedCargo_Town(tile, produced);
}
/* Create bitmap of produced and accepted cargoes. */
CargoTypes acc = 0;
for (uint cid = 0; cid < NUM_CARGO; cid++) {
if (accepted[cid] >= 8) SetBit(acc, cid);
if (produced[cid] > 0) SetBit(t->cargo_produced, cid);
}
t->cargo_accepted[start] = acc;
if (update_total) UpdateTownCargoTotal(t);
}
static void UpdateTownCargoesHouse(Town *t, TileIndex start, bool x_two_tiles, bool y_two_tiles, bool update_total = true)
{
TileIndex lower = TileAddSaturating(start, -AcceptanceMatrix::GRID, -AcceptanceMatrix::GRID);
TileIndex upper = TileAddSaturating(start, AcceptanceMatrix::GRID + (x_two_tiles ? 1 : 0), AcceptanceMatrix::GRID + (y_two_tiles ? 1 : 0));
for (uint x = TileX(lower) & ~(AcceptanceMatrix::GRID - 1); x <= TileX(upper); x += AcceptanceMatrix::GRID) {
for (uint y = TileY(lower) & ~(AcceptanceMatrix::GRID - 1); y <= TileY(upper); y += AcceptanceMatrix::GRID) {
UpdateTownCargoesSingleGridArea(t, TileXY(x, y), false);
}
}
if (update_total) UpdateTownCargoTotal(t);
}
/** Update cargo acceptance for the complete town.
* @param t The town to update.
*/
void UpdateTownCargoes(Town *t)
{
t->cargo_produced = 0;
const TileArea &area = t->cargo_accepted.GetArea();
if (area.tile != INVALID_TILE) {
/* Update acceptance for each grid square. */
TILE_AREA_LOOP_STEP(tile, area, AcceptanceMatrix::GRID) {
UpdateTownCargoesSingleGridArea(t, tile, false);
}
}
/* Update the total acceptance. */
UpdateTownCargoTotal(t);
}
/** Updates the bitmap of all cargoes accepted by houses. */
void UpdateTownCargoBitmap()
{
_town_cargoes_accepted = 0;
for (const Town *town : Town::Iterate()) {
_town_cargoes_accepted |= town->cargo_accepted_total;
}
}
static bool GrowTown(Town *t);
static void TownTickHandler(Town *t)
@ -2166,8 +2080,6 @@ CommandCost CmdFoundTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
/* 't' can't be nullptr since 'random' is false outside scenedit */
assert(!random);
UpdateTownCargoBitmap();
if (_current_company == OWNER_DEITY) {
SetDParam(0, t->index);
AddTileNewsItem(STR_NEWS_NEW_TOWN_UNSPONSORED, NT_INDUSTRY_OPEN, tile);
@ -2754,7 +2666,6 @@ static void DoBuildHouse(Town *t, TileIndex tile, HouseID house, byte random_bit
MakeTownHouse(tile, t, construction_counter, construction_stage, house, random_bits);
UpdateTownRadius(t);
UpdateTownGrowthRate(t);
UpdateTownCargoesHouse(t, tile, hs->building_flags & BUILDING_2_TILES_X, hs->building_flags & BUILDING_2_TILES_Y);
}
/**
@ -2961,9 +2872,6 @@ void ClearTownHouse(Town *t, TileIndex tile)
RemoveNearbyStations(t, tile, hs->building_flags);
UpdateTownRadius(t);
/* Update cargo acceptance. */
UpdateTownCargoesHouse(t, tile, hs->building_flags & BUILDING_2_TILES_X, hs->building_flags & BUILDING_2_TILES_Y);
}
/**
@ -4024,10 +3932,8 @@ void TownsMonthlyLoop()
UpdateTownGrowth(t);
UpdateTownRating(t);
UpdateTownUnwanted(t);
UpdateTownCargoes(t);
}
UpdateTownCargoBitmap();
}
void TownsYearlyLoop()

@ -2153,22 +2153,7 @@ void DrawBridgeMiddle(const TileInfo *ti)
if (IsInvisibilitySet(TO_BRIDGES)) return;
psid++;
if (ti->z + 5 == z) {
/* draw poles below for small bridges */
if (psid->sprite != 0) {
SpriteID image = psid->sprite;
SpriteID pal = psid->pal;
if (IsTransparencySet(TO_BRIDGES)) {
SetBit(image, PALETTE_MODIFIER_TRANSPARENT);
pal = PALETTE_TO_TRANSPARENT;
}
DrawGroundSpriteAt(image, pal, x - ti->x, y - ti->y, z - ti->z);
}
} else {
/* draw pillars below for high bridges */
DrawBridgePillars(psid, ti, axis, drawfarpillar, x, y, z);
}
DrawBridgePillars(psid, ti, axis, drawfarpillar, x, y, z);
}

@ -1443,7 +1443,7 @@ void CallVehicleTicks()
if (!IsLocalCompany()) continue;
if (res.Succeeded()) {
if (res.Succeeded() && res.GetCost() != 0) {
ShowCostOrIncomeAnimation(x, y, z, res.GetCost());
continue;
}

Loading…
Cancel
Save