summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/airport.cpp24
-rw-r--r--src/airport.h7
-rw-r--r--src/airport_gui.cpp17
-rw-r--r--src/lang/english.txt6
-rw-r--r--src/misc_cmd.cpp10
-rw-r--r--src/newgrf.cpp2
-rw-r--r--src/openttd.cpp5
-rw-r--r--src/saveload.cpp2
-rw-r--r--src/settings.cpp32
-rw-r--r--src/settings_gui.cpp1
-rw-r--r--src/settings_type.h24
-rw-r--r--src/station_cmd.cpp122
-rw-r--r--src/station_func.h1
-rw-r--r--src/town.h15
-rw-r--r--src/town_cmd.cpp4
-rw-r--r--src/town_gui.cpp33
16 files changed, 279 insertions, 26 deletions
diff --git a/src/airport.cpp b/src/airport.cpp
index 0e00f3d41..faef68711 100644
--- a/src/airport.cpp
+++ b/src/airport.cpp
@@ -43,7 +43,7 @@ void InitializeAirports()
_airport_fta_dummy,
NULL,
0,
- 0, 0,
+ 0, 0, 0,
0,
0
);
@@ -57,7 +57,7 @@ void InitializeAirports()
_airport_fta_country,
_airport_depots_country,
lengthof(_airport_depots_country),
- 4, 3,
+ 4, 3, 3,
0,
4
);
@@ -71,7 +71,7 @@ void InitializeAirports()
_airport_fta_city,
_airport_depots_city,
lengthof(_airport_depots_city),
- 6, 6,
+ 6, 6, 5,
0,
5
);
@@ -85,7 +85,7 @@ void InitializeAirports()
_airport_fta_metropolitan,
_airport_depots_metropolitan,
lengthof(_airport_depots_metropolitan),
- 6, 6,
+ 6, 6, 8,
0,
6
);
@@ -99,7 +99,7 @@ void InitializeAirports()
_airport_fta_international,
_airport_depots_international,
lengthof(_airport_depots_international),
- 7, 7,
+ 7, 7, 17,
0,
8
);
@@ -113,7 +113,7 @@ void InitializeAirports()
_airport_fta_intercontinental,
_airport_depots_intercontinental,
lengthof(_airport_depots_intercontinental),
- 9, 11,
+ 9, 11, 25,
0,
10
);
@@ -127,7 +127,7 @@ void InitializeAirports()
_airport_fta_heliport_oilrig,
NULL,
0,
- 1, 1,
+ 1, 1, 1,
60,
4
);
@@ -141,7 +141,7 @@ void InitializeAirports()
_airport_fta_heliport_oilrig,
NULL,
0,
- 1, 1,
+ 1, 1, 0,
54,
3
);
@@ -155,7 +155,7 @@ void InitializeAirports()
_airport_fta_commuter,
_airport_depots_commuter,
lengthof(_airport_depots_commuter),
- 5, 4,
+ 5, 4, 4,
0,
4
);
@@ -169,7 +169,7 @@ void InitializeAirports()
_airport_fta_helidepot,
_airport_depots_helidepot,
lengthof(_airport_depots_helidepot),
- 2, 2,
+ 2, 2, 2,
0,
4
);
@@ -183,7 +183,7 @@ void InitializeAirports()
_airport_fta_helistation,
_airport_depots_helistation,
lengthof(_airport_depots_helistation),
- 4, 2,
+ 4, 2, 3,
0,
4
);
@@ -225,6 +225,7 @@ AirportFTAClass::AirportFTAClass(
const byte nof_depots_,
uint size_x_,
uint size_y_,
+ byte noise_level_,
byte delta_z_,
byte catchment_
) :
@@ -238,6 +239,7 @@ AirportFTAClass::AirportFTAClass(
entry_points(entry_points_),
size_x(size_x_),
size_y(size_y_),
+ noise_level(noise_level_),
delta_z(delta_z_),
catchment(catchment_)
{
diff --git a/src/airport.h b/src/airport.h
index 86305779e..0f0e8ed36 100644
--- a/src/airport.h
+++ b/src/airport.h
@@ -7,6 +7,7 @@
#include "direction_type.h"
#include "map_type.h"
+#include "tile_type.h"
enum {MAX_TERMINALS = 10};
enum {MAX_HELIPADS = 4};
@@ -144,6 +145,7 @@ struct AirportFTAClass {
byte nof_depots,
uint size_x,
uint size_y,
+ uint8 noise_level,
byte delta_z,
byte catchment
);
@@ -167,6 +169,7 @@ struct AirportFTAClass {
const byte *entry_points; ///< when an airplane arrives at this airport, enter it at position entry_point, index depends on direction
byte size_x;
byte size_y;
+ uint8 noise_level; ///< noise that this airport generates
byte delta_z; ///< Z adjustment for helicopter pads
byte catchment;
};
@@ -194,4 +197,8 @@ const AirportFTAClass *GetAirport(const byte airport_type);
*/
uint32 GetValidAirports();
+
+/* Calculate the noise this type airport will generate */
+uint8 GetAirportNoiseLevelForTown(const AirportFTAClass *afc, TileIndex town_tile, TileIndex tile);
+
#endif /* AIRPORT_H */
diff --git a/src/airport_gui.cpp b/src/airport_gui.cpp
index 5bf5ec97a..db0f2b8ee 100644
--- a/src/airport_gui.cpp
+++ b/src/airport_gui.cpp
@@ -12,6 +12,7 @@
#include "airport.h"
#include "sound_func.h"
#include "window_func.h"
+#include "strings_func.h"
#include "settings_type.h"
#include "viewport_func.h"
#include "gfx_func.h"
@@ -177,12 +178,17 @@ public:
this->SetWidgetLoweredState(BAW_BTN_DOHILIGHT, _station_show_coverage);
this->LowerWidget(_selected_airport_type + BAW_SMALL_AIRPORT);
+ if (_patches.station_noise_level) {
+ ResizeWindowForWidget(this, BAW_BOTTOMPANEL, 0, 10);
+ }
+
this->FindWindowPlacementAndResize(desc);
}
virtual void OnPaint()
{
int i; // airport enabling loop
+ uint16 y_noise_offset = 0;
uint32 avail_airports;
const AirportFTAClass *airport;
@@ -210,8 +216,17 @@ public:
if (_station_show_coverage) SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
this->DrawWidgets();
+
+ /* only show the station (airport) noise, if the noise option is activated */
+ if (_patches.station_noise_level) {
+ /* show the noise of the selected airport */
+ SetDParam(0, airport->noise_level);
+ DrawString(2, 206, STR_STATION_NOISE, 0);
+ y_noise_offset = 10;
+ }
+
/* strings such as 'Size' and 'Coverage Area' */
- int text_end = DrawStationCoverageAreaText(2, 206, SCT_ALL, rad, false);
+ int text_end = DrawStationCoverageAreaText(2, this->widget[BAW_BTN_DOHILIGHT].bottom + 4 + y_noise_offset, SCT_ALL, rad, false);
text_end = DrawStationCoverageAreaText(2, text_end + 4, SCT_ALL, rad, true) + 4;
if (text_end != this->widget[BAW_BOTTOMPANEL].bottom) {
this->SetDirty();
diff --git a/src/lang/english.txt b/src/lang/english.txt
index 50e5416b1..d97f54ec7 100644
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -3553,3 +3553,9 @@ STR_DRAG_SIGNALS_DENSITY_INCREASE_TIP :{BLACK}Increase
STR_OSK_KEYBOARD_LAYOUT :`1234567890-=\qwertyuiop[]asdfghjkl;' zxcvbnm,./ .
STR_OSK_KEYBOARD_LAYOUT_CAPS :~!@#$%^&*()_+|QWERTYUIOP{{}}ASDFGHJKL:" ZXCVBNM<>? .
########
+
+############ town controlled noise level
+STR_CONFIG_PATCHES_NOISE_LEVEL :{LTBLUE}Allow town controlled noise level for airports: {ORANGE}{STRING}
+STR_NOISE_IN_TOWN :{BLACK}Noise limit in town: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA}
+STR_STATION_NOISE :{BLACK}Noise generated: {GOLD}{COMMA}
+########
diff --git a/src/misc_cmd.cpp b/src/misc_cmd.cpp
index 84579e113..0e6c2bc22 100644
--- a/src/misc_cmd.cpp
+++ b/src/misc_cmd.cpp
@@ -22,6 +22,7 @@
#include "player_base.h"
#include "player_gui.h"
#include "settings_type.h"
+#include "station_func.h"
#include "table/strings.h"
@@ -402,6 +403,15 @@ CommandCost CmdChangeDifficultyLevel(TileIndex tile, uint32 flags, uint32 p1, ui
_opt_ptr->diff_level = p2;
}
+ /* Since the tolerance of the town council has a direct impact on the noise generation/tolerance,
+ * launch a re-evaluation of the actual values only when setting has changed */
+ if (p2 == GAME_DIFFICULTY_TOWNCOUNCIL_TOLERANCE && _game_mode == GM_NORMAL) {
+ UpdateAirportsNoise();
+ if (_patches.station_noise_level) {
+ InvalidateWindowClassesData(WC_TOWN_VIEW, 0);
+ }
+ }
+
/* If we are a network-client, update the difficult setting (if it is open).
* Use this instead of just dirtying the window because we need to load in
* the new difficulty settings */
diff --git a/src/newgrf.cpp b/src/newgrf.cpp
index 903c33078..1a271f316 100644
--- a/src/newgrf.cpp
+++ b/src/newgrf.cpp
@@ -5091,7 +5091,7 @@ static void InitializeGRFSpecial()
| (1 << 0x1D) // lowmemory
| (1 << 0x1E); // generalfixes
- _ttdpatch_flags[1] = (0 << 0x07) // moreairports - based on units of noise
+ _ttdpatch_flags[1] = ((_patches.station_noise_level ? 1 : 0) << 0x07) // moreairports - based on units of noise
| ((_patches.mammoth_trains ? 1 : 0) << 0x08) // mammothtrains
| (1 << 0x09) // trainrefit
| (0 << 0x0B) // subsidiaries
diff --git a/src/openttd.cpp b/src/openttd.cpp
index 4d13ca415..b8ca7f312 100644
--- a/src/openttd.cpp
+++ b/src/openttd.cpp
@@ -1345,6 +1345,11 @@ static bool InitializeWindowsAndCaches()
SetCachedEngineCounts();
+ /* Towns have a noise controlled number of airports system
+ * So each airport's noise value must be added to the town->noise_reached value
+ * Reset each town's noise_reached value to '0' before. */
+ UpdateAirportsNoise();
+
return true;
}
diff --git a/src/saveload.cpp b/src/saveload.cpp
index 512d402e9..51b03bc40 100644
--- a/src/saveload.cpp
+++ b/src/saveload.cpp
@@ -35,7 +35,7 @@
#include "table/strings.h"
-extern const uint16 SAVEGAME_VERSION = 95;
+extern const uint16 SAVEGAME_VERSION = 96;
SavegameType _savegame_type; ///< type of savegame we are loading
diff --git a/src/settings.cpp b/src/settings.cpp
index 9a9d6e322..da5190314 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -758,8 +758,11 @@ static void ini_load_settings(IniFile *ini, const SettingDesc *sd, const char *g
break;
case SDT_INTLIST: {
- if (!load_intlist((const char*)p, ptr, sld->length, GetVarMemType(sld->conv)))
+ if (!load_intlist((const char*)p, ptr, sld->length, GetVarMemType(sld->conv))) {
ShowInfoF("ini: error in array '%s'", sdb->name);
+ } else if (sd->desc.proc_cnvt != NULL) {
+ sd->desc.proc_cnvt((const char*)p);
+ }
break;
}
default: NOT_REACHED(); break;
@@ -1054,8 +1057,8 @@ static void ini_save_setting_list(IniFile *ini, const char *grpname, char **list
SDT_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, base, var, lengthof(((base*)8)->var), def, 0, 0, 0, NULL, str, proc, NULL, from, to)
#define SDT_LIST(base, var, type, flags, guiflags, def, str, proc)\
SDT_CONDLIST(base, var, type, 0, SL_MAX_VERSION, flags, guiflags, def, str, proc)
-#define SDT_CONDLISTO(base, var, length, type, from, to, flags, guiflags, def, str, proc)\
- SDT_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, base, var, length, def, 0, 0, 0, NULL, str, proc, NULL, from, to)
+#define SDT_CONDLISTO(base, var, length, type, from, to, flags, guiflags, def, str, proc, load)\
+ SDT_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, base, var, length, def, 0, 0, 0, NULL, str, proc, load, from, to)
#define SDT_CONDSTR(base, var, type, from, to, flags, guiflags, def, str, proc)\
SDT_GENERAL(#var, SDT_STRING, SL_STR, type, flags, guiflags, base, var, lengthof(((base*)8)->var), def, 0, 0, 0, NULL, str, proc, NULL, from, to)
@@ -1161,6 +1164,12 @@ static int32 CloseSignalGUI(int32 p1)
return 0;
}
+static int32 InvalidateTownViewWindow(int32 p1)
+{
+ InvalidateWindowClassesData(WC_TOWN_VIEW, p1);
+ return 0;
+}
+
static int32 UpdateConsists(int32 p1)
{
Vehicle *v;
@@ -1260,6 +1269,21 @@ static int32 ConvertLandscape(const char *value)
return lookup_oneofmany("normal|hilly|desert|candy", value);
}
+/**
+ * Check for decent values been supplied by the user for the noise tolerance setting.
+ * The primary idea is to avoid division by zero in game mode.
+ * The secondary idea is to make it so the values will be somewhat sane and that towns will
+ * not be overcrowed with airports. It would be easy to abuse such a feature
+ * So basically, 200, 400, 800 are the lowest allowed values */
+static int32 CheckNoiseToleranceLevel(const char *value)
+{
+ Patches *patches_ptr = (_game_mode == GM_MENU) ? &_patches_newgame : &_patches;
+ for (uint16 i = 0; i < lengthof(patches_ptr->town_noise_population); i++) {
+ patches_ptr->town_noise_population[i] = max(uint16(200 * (i + 1)), patches_ptr->town_noise_population[i]);
+ }
+ return 0;
+}
+
/* End - Callback Functions */
#ifndef EXTERNAL_PLAYER
@@ -1490,6 +1514,7 @@ const SettingDesc _patch_settings[] = {
SDT_CONDBOOL(Patches, gradual_loading, 40, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_PATCHES_GRADUAL_LOADING, NULL),
SDT_CONDBOOL(Patches, road_stop_on_town_road, 47, SL_MAX_VERSION, 0, 0, false, STR_CONFIG_PATCHES_STOP_ON_TOWN_ROAD, NULL),
SDT_CONDBOOL(Patches, adjacent_stations, 62, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_PATCHES_ADJACENT_STATIONS, NULL),
+ SDT_CONDBOOL(Patches, station_noise_level, 96, SL_MAX_VERSION, 0, 0, false, STR_CONFIG_PATCHES_NOISE_LEVEL, InvalidateTownViewWindow),
/***************************************************************************/
/* Economy section of the GUI-configure patches window */
@@ -1531,6 +1556,7 @@ const SettingDesc _patch_settings[] = {
SDT_VAR(Patches, dist_local_authority,SLE_UINT8, 0, 0, 20, 5, 60, 0, STR_NULL, NULL),
SDT_VAR(Patches, wait_oneway_signal, SLE_UINT8, 0, 0, 15, 2, 100, 0, STR_NULL, NULL),
SDT_VAR(Patches, wait_twoway_signal, SLE_UINT8, 0, 0, 41, 2, 100, 0, STR_NULL, NULL),
+ SDT_CONDLISTO(Patches, town_noise_population, 3, SLE_UINT16, 96, SL_MAX_VERSION, 0, D0, "800,2000,4000", STR_NULL, NULL, CheckNoiseToleranceLevel),
/***************************************************************************/
/* New Pathfinding patch settings */
diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp
index 2dc563b54..e294397d3 100644
--- a/src/settings_gui.cpp
+++ b/src/settings_gui.cpp
@@ -718,6 +718,7 @@ static const char *_patches_stations[] = {
"gradual_loading",
"road_stop_on_town_road",
"adjacent_stations",
+ "station_noise_level",
};
static const char *_patches_economy[] = {
diff --git a/src/settings_type.h b/src/settings_type.h
index c5a74d359..2233c856d 100644
--- a/src/settings_type.h
+++ b/src/settings_type.h
@@ -10,7 +10,27 @@
#include "town_type.h"
#include "transport_type.h"
-#define GAME_DIFFICULTY_NUM 18
+enum {
+ GAME_DIFFICULTY_AI_NUMBER,
+ GAME_DIFFICULTY_AI_STARTTIME,
+ GAME_DIFFICULTY_TOWN_NUMBER,
+ GAME_DIFFICULTY_INDUSTRIE_NUMBER,
+ GAME_DIFFICULTY_MAX_LOAN,
+ GAME_DIFFICULTY_INITIAL_INTEREST,
+ GAME_DIFFICULTY_VEHICLE_COST,
+ GAME_DIFFICULTY_AI_SPEED,
+ GAME_DIFFICULTY_AI_INTELLIGENCE, ///< no longer in use
+ GAME_DIFFICULTY_VEHICLES_BREAKDOWN,
+ GAME_DIFFICULTY_SUBSIDY_MULTIPLIER,
+ GAME_DIFFICULTY_CONSTRUCTION_COST,
+ GAME_DIFFICULTY_TYPE_TERRAIN,
+ GAME_DIFFICULTY_SEALAKE_NUMBER,
+ GAME_DIFFICULTY_ECONOMY,
+ GAME_DIFFICULTY_LINE_REVERSEMODE,
+ GAME_DIFFICULTY_DISASTERS,
+ GAME_DIFFICULTY_TOWNCOUNCIL_TOLERANCE, ///< minimum required town ratings to be allowed to demolish stuff
+ GAME_DIFFICULTY_NUM,
+};
/** Specific type for Game Difficulty to ease changing the type */
typedef uint16 GDType;
@@ -221,6 +241,8 @@ struct Patches {
bool pause_on_newgame; ///< Whether to start new games paused or not.
TownLayoutByte town_layout; ///< Select town layout
+ bool station_noise_level; ///< build new airports when the town noise level is still within accepted limits
+ uint16 town_noise_population[3]; ///< Population to base decision on noise evaluation (@see town_council_tolerance)
bool timetabling; ///< Whether to allow timetabling.
bool timetable_in_ticks; ///< Whether to show the timetable in ticks rather than days.
diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp
index 2cc60b4ef..0fe4bebf2 100644
--- a/src/station_cmd.cpp
+++ b/src/station_cmd.cpp
@@ -1610,6 +1610,88 @@ static const byte * const _airport_sections[] = {
_airport_sections_helistation // Helistation
};
+/** Recalculate the noise generated by the airports of each town */
+void UpdateAirportsNoise()
+{
+ Town *t;
+ const Station *st;
+
+ FOR_ALL_TOWNS(t) t->noise_reached = 0;
+
+ FOR_ALL_STATIONS(st) {
+ if (IsAirport(st->xy)) {
+ st->town->noise_reached += GetAirportNoiseLevelForTown(GetAirport(st->airport_type), st->town->xy, st->xy);
+ }
+ }
+}
+
+/** Get a possible noise reduction factor based on distance from town center.
+ * The further you get, the less noise you generate.
+ * So all those folks at city council can now happily slee... work in their offices
+ * @param afc AirportFTAClass pointer of the class being proposed
+ * @param town_tile TileIndex of town's center, the one who will receive the airport's candidature
+ * @param tile TileIndex where the new airport might be built
+ * @return the noise that will be generated, according to distance
+ */
+uint8 GetAirportNoiseLevelForTown(const AirportFTAClass *afc, TileIndex town_tile, TileIndex tile)
+{
+ struct TileIndexDistance {
+ TileIndex index;
+ uint distance;
+ };
+
+ uint distance;
+
+ /* 0 cannot be accounted, and 1 is the lowest that can be reduced from town.
+ * So no need to go any further*/
+ if (afc->noise_level < 2) return afc->noise_level;
+
+ /* Find the airport-to-be's closest corner to the town */
+ if (afc->size_x == 1 && afc->size_y == 1) {
+ distance = DistanceManhattan(town_tile, tile); // ont tile, one corner, it's THE corner
+ } else {
+ /* calculate manhattan distance to town of each side of the airport */
+ TileIndexDistance dist[4]; ///< Array that will contain all 4 corners in TileIndex and distance
+ uint min_tile = UINT_MAX; ///< Sentinel value
+ uint min_indice = 4;
+
+ /* Based on the size of the airport, establish location of each corner*/
+ dist[0].index = tile; // north tile
+ dist[1].index = TileAddWrap(tile, afc->size_x - 1, afc->size_y - 1); // south tile
+ dist[2].index = TileAddWrap(tile, afc->size_x - 1, 0); // west tile
+ dist[3].index = TileAddWrap(tile, 0, afc->size_y - 1); //east tile
+
+ /* now, go and find the smallest one, thus the closest to town */
+ for (uint i = 0; i < 4; i++) {
+ dist[i].distance = DistanceManhattan(town_tile, dist[i].index);
+
+ if (dist[i].distance < min_tile) {
+ min_tile = dist[i].distance; // here's a new candidate
+ min_indice = i;
+ }
+ }
+
+ distance = dist[min_indice].distance;
+ }
+
+ /* The steps for measuring noise reduction are based on the "magical" (and arbitrary) 8 base distance
+ * adding the town_council_tolerance 4 times, as a way to graduate, depending of the tolerance.
+ * Basically, it says that the less tolerant a town is, the bigger the distance before
+ * an actual decrease can be granted */
+ uint8 town_tolerance_distance = 8 + (_opt.diff.town_council_tolerance * 4);
+
+ /* The airport is in the "inner" distance where there is no noise reduction */
+ if (distance < town_tolerance_distance) return afc->noise_level;
+
+ /* now, we want to have the distance segmented using the distance judged bareable by town
+ * This will give us the coefficient of reduction the distance provides. */
+ uint noise_reduction = min(afc->noise_level, distance / town_tolerance_distance);
+
+ /* If the noise reduction equals the airport noise itself, don't give it for free. Use it all minus 1.
+ * Otherwise, simply reduce the airport's level. */
+ return max(1U, noise_reduction == afc->noise_level ? afc->noise_level - 1 : afc->noise_level - noise_reduction);
+}
+
/** Place an Airport.
* @param tile tile where airport will be built
* @param flags operation to perform
@@ -1641,12 +1723,25 @@ CommandCost CmdBuildAirport(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
CommandCost cost = CheckFlatLandBelow(tile, w, h, flags, 0, NULL);
if (CmdFailed(cost)) return cost;
- /* Check if local auth refuses a new airport */
- uint num = 0;
- FOR_ALL_STATIONS(st) {
- if (st->town == t && st->facilities & FACIL_AIRPORT && st->airport_type != AT_OILRIG) num++;
+ /* Go get the final noise level, that is base noise minus factor from distance to town center */
+ uint newnoise_level = GetAirportNoiseLevelForTown(afc, t->xy, tile);
+
+ /* Check if local auth would allow a new airport */
+ bool autority_refused;
+
+ if (_patches.station_noise_level) {
+ /* do not allow to build a new airport if this raise the town noise over the maximum allowed by town */
+ autority_refused = (t->noise_reached + newnoise_level) > t->MaxTownNoise();
+ } else {
+ uint num = 0;
+ const Station *st;
+ FOR_ALL_STATIONS(st) {
+ if (st->town == t && st->facilities & FACIL_AIRPORT && st->airport_type != AT_OILRIG) num++;
+ }
+ autority_refused = (num >= 2);
}
- if (num >= 2) {
+
+ if (autority_refused) {
SetDParam(0, t->index);
return_cmd_error(STR_2035_LOCAL_AUTHORITY_REFUSES);
}
@@ -1693,6 +1788,9 @@ CommandCost CmdBuildAirport(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
cost.AddCost(_price.build_airport * w * h);
if (flags & DC_EXEC) {
+ /* Always add the noise, so there will be no need to recalculate when option toggles */
+ st->town->noise_reached += newnoise_level;
+
st->airport_tile = tile;
st->AddFacility(FACIL_AIRPORT, tile);
st->airport_type = (byte)p1;
@@ -1722,6 +1820,10 @@ CommandCost CmdBuildAirport(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
UpdateStationAcceptance(st, false);
InvalidateWindowData(WC_STATION_LIST, st->owner, 0);
InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_PLANES);
+
+ if (_patches.station_noise_level) {
+ InvalidateWindow(WC_TOWN_VIEW, st->town->index);
+ }
}
return cost;
@@ -1764,12 +1866,22 @@ static CommandCost RemoveAirport(Station *st, uint32 flags)
);
}
+ /* Go get the final noise level, that is base noise minus factor from distance to town center.
+ * And as for construction, always remove it, even if the patch is not set, in order to avoid the
+ * need of recalculation */
+ st->town->noise_reached -= GetAirportNoiseLevelForTown(afc, st->town->xy, tile);
+
st->rect.AfterRemoveRect(st, tile, w, h);
st->airport_tile = 0;
st->facilities &= ~FACIL_AIRPORT;
InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_PLANES);
+
+ if (_patches.station_noise_level) {
+ InvalidateWindow(WC_TOWN_VIEW, st->town->index);
+ }
+
UpdateStationVirtCoordDirty(st);
DeleteStationIfEmpty(st);
}
diff --git a/src/station_func.h b/src/station_func.h
index 917314402..d2f66fc63 100644
--- a/src/station_func.h
+++ b/src/station_func.h
@@ -47,5 +47,6 @@ bool IsStationTileBlocked(TileIndex tile);
/* Check if a rail station tile is electrifiable. */
bool IsStationTileElectrifiable(TileIndex tile);
+void UpdateAirportsNoise();
#endif /* STATION_FUNC_H */
diff --git a/src/town.h b/src/town.h
index 03d0cc112..8bf21dbd4 100644
--- a/src/town.h
+++ b/src/town.h
@@ -116,6 +116,9 @@ struct Town : PoolItem<Town, TownID, &_Town_pool> {
* bit 2 = STADIUM */
byte flags12;
+ /* level of noise that all the airports are generating */
+ uint16 noise_reached;
+
/* Which players have a statue? */
byte statues;
@@ -184,6 +187,18 @@ struct Town : PoolItem<Town, TownID, &_Town_pool> {
void InitializeLayout();
inline TownLayout GetActiveLayout() const;
+
+ /** Calculate the max town noise
+ * The value is counted using the population divided by the content of the
+ * entry in town_noise_population corespondig to the town's tolerance.
+ * To this result, we add 3, which is the noise of the lowest airport.
+ * So user can at least buld that airport
+ * @return the maximum noise level the town will tolerate */
+ inline uint16 MaxTownNoise() const {
+ if (this->population == 0) return 0; // no population? no noise
+
+ return ((this->population / _patches.town_noise_population[_opt.diff.town_council_tolerance]) + 3);
+ }
};
/**
diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp
index efe12043e..e0033155f 100644
--- a/src/town_cmd.cpp
+++ b/src/town_cmd.cpp
@@ -1490,6 +1490,8 @@ static void DoCreateTown(Town *t, TileIndex tile, uint32 townnameparts, TownSize
break;
}
+ t->noise_reached = 0;
+
t->num_houses += x;
UpdateTownRadius(t);
@@ -1578,7 +1580,7 @@ Town *CreateRandomTown(uint attempts, TownSizeMode mode, uint size)
return NULL;
}
-static const byte _num_initial_towns[4] = {5, 11, 23, 46};
+static const byte _num_initial_towns[4] = {5, 11, 23, 46}; // very low, low, normal, high
bool GenerateTowns()
{
diff --git a/src/town_gui.cpp b/src/town_gui.cpp
index 46a7e8890..bf4e63000 100644
--- a/src/town_gui.cpp
+++ b/src/town_gui.cpp
@@ -280,7 +280,9 @@ private:
enum TownViewWidget {
TVW_CAPTION = 1,
TVW_STICKY,
- TVW_CENTERVIEW = 6,
+ TVW_VIEWPORTPANEL,
+ TVW_INFOPANEL = 5,
+ TVW_CENTERVIEW,
TVW_SHOWAUTORITY,
TVW_CHANGENAME,
TVW_EXPAND,
@@ -310,6 +312,11 @@ public:
this->widget[TVW_CHANGENAME].right = this->widget[TVW_STICKY].right;
}
+ /* Space required for showing noise level information */
+ if (_patches.station_noise_level) {
+ ResizeWindowForWidget(this, TVW_INFOPANEL, 0, 10);
+ }
+
this->FindWindowPlacementAndResize(desc);
}
@@ -334,6 +341,13 @@ public:
DrawString(2, 127, STR_200E_MAIL_LAST_MONTH_MAX, TC_FROMSTRING);
this->DrawViewport();
+
+ /* only show the town noise, if the noise option is activated. */
+ if (_patches.station_noise_level) {
+ SetDParam(0, this->town->noise_reached);
+ SetDParam(1, this->town->MaxTownNoise());
+ DrawString(2, 137, STR_NOISE_IN_TOWN, 0);
+ }
}
virtual void OnClick(Point pt, int widget)
@@ -366,6 +380,22 @@ public:
}
}
+ virtual void OnInvalidateData(int data = 0)
+ {
+ /* Called when setting station noise have changed, in order to resize the window */
+ this->SetDirty(); // refresh display for current size. This will allow to avoid glitches when downgrading
+
+ if (_patches.station_noise_level) { // adjust depending
+ if (this->height == 150) { // window is smaller, needs to be bigger
+ ResizeWindowForWidget(this, TVW_INFOPANEL, 0, 10);
+ }
+ } else {
+ if (this->height != 150) { // window is bigger, needs to be smaller
+ ResizeWindowForWidget(this, TVW_INFOPANEL, 0, -10);
+ }
+ }
+ }
+
virtual void OnQueryTextFinished(char *str)
{
if (!StrEmpty(str)) {
@@ -636,7 +666,6 @@ private:
};
public:
-
ScenarioEditorTownGenerationWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
{
this->LowerWidget(_scengen_town_size + TSEW_SMALLTOWN);