diff --git a/src/airport.cpp b/src/airport.cpp index 0e00f3d41e..faef687111 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 86305779ee..0f0e8ed36c 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 5bf5ec97ab..db0f2b8ee1 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 50e5416b15..d97f54ec75 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 84579e113a..0e6c2bc229 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 903c330780..1a271f3161 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 4d13ca4157..b8ca7f312f 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 512d402e90..51b03bc404 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 9a9d6e3220..da5190314b 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 2dc563b542..e294397d3d 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 c5a74d359b..2233c856d4 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 2cc60b4efc..0fe4bebf23 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 9173144026..d2f66fc631 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 03d0cc112b..8bf21dbd43 100644 --- a/src/town.h +++ b/src/town.h @@ -116,6 +116,9 @@ struct Town : PoolItem { * 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 { 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 efe12043e3..e0033155fb 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 46a7e8890e..bf4e630000 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);