summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbelugas <belugas@openttd.org>2008-05-24 02:54:47 +0000
committerbelugas <belugas@openttd.org>2008-05-24 02:54:47 +0000
commit08671d2e78d3277511d57236eaa74c0d6cb49fa0 (patch)
tree6e9667beb04ac4a18b43294a74456ab52a123a5a
parentcfc45e97ab94c6d96f32b3397201c003b61ccd75 (diff)
downloadopenttd-08671d2e78d3277511d57236eaa74c0d6cb49fa0.tar.xz
(svn r13226) -Feature: Allow to have more than only two airports per town. The number of airports is now controlled by the noise each of them generates, the distance from town's center and how tolerant the town is.
Initial concept : TTDPatch (moreairpots), Initial code : Pasky Thanks to BigBB (help coding), Smatz Skidd13 and frosch for bugcatches and advices
-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);