From 832e392855c652766de1bdd15851f81d651eb9d6 Mon Sep 17 00:00:00 2001 From: smatz Date: Wed, 4 Feb 2009 20:17:25 +0000 Subject: [PATCH] (svn r15340) -Fix [FS#2121]: changing town road layout in-game caused ugly road networks -Fix: use a flag instead of TL_NO_ROADS to forbid towns to build roads. The flag is ignored during world generation, so there won't be 'ghost' towns anymore -Feature: town layout is now stored per town, so it is possible to (manually) set different layout for each town --- src/genworld_gui.cpp | 12 +---- src/lang/english.txt | 9 ++-- src/newgrf.cpp | 2 +- src/saveload/afterload.cpp | 32 ++++++++++- src/saveload/saveload.cpp | 2 +- src/saveload/saveload_internal.h | 1 - src/saveload/town_sl.cpp | 7 +-- src/settings.cpp | 20 +------ src/settings_gui.cpp | 1 + src/settings_type.h | 1 + src/town.h | 18 ++----- src/town_cmd.cpp | 92 +++++++++++++------------------- src/town_type.h | 6 +-- 13 files changed, 85 insertions(+), 118 deletions(-) diff --git a/src/genworld_gui.cpp b/src/genworld_gui.cpp index 4be385a72c..1146894e87 100644 --- a/src/genworld_gui.cpp +++ b/src/genworld_gui.cpp @@ -443,13 +443,7 @@ struct GenerateLandscapeWindow : public QueryStringBaseWindow { case GLAND_GENERATE_BUTTON: // Generate MakeNewgameSettingsLive(); - if (_settings_game.economy.town_layout == TL_NO_ROADS) { - ShowQuery( - STR_TOWN_LAYOUT_WARNING_CAPTION, - STR_TOWN_LAYOUT_WARNING_MESSAGE, - this, - LandscapeGenerationCallback); - } else if (mode == GLWP_HEIGHTMAP && + if (mode == GLWP_HEIGHTMAP && (this->x * 2 < (1U << _settings_newgame.game_creation.map_x) || this->x / 2 > (1U << _settings_newgame.game_creation.map_x) || this->y * 2 < (1U << _settings_newgame.game_creation.map_y) || @@ -685,10 +679,6 @@ void ShowHeightmapLoad() void StartScenarioEditor() { - if (_settings_newgame.economy.town_layout == TL_NO_ROADS) { - _settings_newgame.economy.town_layout = TL_ORIGINAL; - } - StartGeneratingLandscape(GLWP_SCENARIO); } diff --git a/src/lang/english.txt b/src/lang/english.txt index 2cefac1ef2..785cfa4252 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1191,14 +1191,13 @@ STR_CONFIG_PATCHES_CYCLE_SIGNAL_NORMAL :Block signals o STR_CONFIG_PATCHES_CYCLE_SIGNAL_PBS :Path signals only STR_CONFIG_PATCHES_CYCLE_SIGNAL_ALL :All -STR_CONFIG_PATCHES_TOWN_LAYOUT_INVALID :{WHITE}The town layout "no more roads" isn't valid in the scenario editor -STR_CONFIG_PATCHES_TOWN_LAYOUT :{LTBLUE}Select town-road layout: {ORANGE}{STRING1} -STR_CONFIG_PATCHES_TOWN_LAYOUT_NO_ROADS :no more roads -STR_CONFIG_PATCHES_TOWN_LAYOUT_DEFAULT :default +STR_CONFIG_PATCHES_TOWN_LAYOUT :{LTBLUE}Road layout for new towns: {ORANGE}{STRING1} +STR_CONFIG_PATCHES_TOWN_LAYOUT_DEFAULT :original STR_CONFIG_PATCHES_TOWN_LAYOUT_BETTER_ROADS :better roads STR_CONFIG_PATCHES_TOWN_LAYOUT_2X2_GRID :2x2 grid STR_CONFIG_PATCHES_TOWN_LAYOUT_3X3_GRID :3x3 grid STR_CONFIG_PATCHES_TOWN_LAYOUT_RANDOM :random +STR_CONFIG_PATCHES_ALLOW_TOWN_ROADS :{LTBLUE}Towns are allowed to build roads: {ORANGE}{STRING1} STR_CONFIG_PATCHES_TOOLBAR_POS :{LTBLUE}Position of main toolbar: {ORANGE}{STRING1} STR_CONFIG_PATCHES_TOOLBAR_POS_LEFT :Left @@ -3470,8 +3469,6 @@ STR_SNOW_LINE_QUERY_CAPT :{WHITE}Change s STR_START_DATE_QUERY_CAPT :{WHITE}Change starting year STR_HEIGHTMAP_SCALE_WARNING_CAPTION :{WHITE}Scale warning STR_HEIGHTMAP_SCALE_WARNING_MESSAGE :{YELLOW}Resizing source map too much is not recommended. Continue with the generation? -STR_TOWN_LAYOUT_WARNING_CAPTION :{WHITE}Town layout warning -STR_TOWN_LAYOUT_WARNING_MESSAGE :{YELLOW}The town layout "no more roads" is not recommended. Continue with the generation? STR_HEIGHTMAP_NAME :{BLACK}Heightmap name: STR_HEIGHTMAP_SIZE :{BLACK}Size: {ORANGE}{NUM} x {NUM} STR_GENERATION_WORLD :{WHITE}Generating world... diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 7fcfa17cf2..dae87a9222 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -5307,7 +5307,7 @@ static void InitializeGRFSpecial() _ttdpatch_flags[3] = (0 << 0x00) // newcargodistribution | (1 << 0x01) // windowsnap - | ((_settings_game.economy.town_layout == TL_NO_ROADS ? 1 : 0) << 0x02) // townbuildnoroad + | ((_settings_game.economy.allow_town_roads || _generating_world ? 0 : 1) << 0x02) // townbuildnoroad | (1 << 0x03) // pathbasedsignalling | (0 << 0x04) // aichoosechance | (1 << 0x05) // resolutionwidth diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 2b34622fc4..f34d5fda0d 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -482,8 +482,6 @@ bool AfterLoadGame() /* Update all waypoints */ if (CheckSavegameVersion(12)) FixOldWaypoints(); - AfterLoadTown(); - /* make sure there is a town in the game */ if (_game_mode == GM_NORMAL && !ClosestTownFromTile(0, UINT_MAX)) { SetSaveLoadError(STR_NO_TOWN_IN_SCENARIO); @@ -1694,6 +1692,36 @@ bool AfterLoadGame() } } + if (CheckSavegameVersion(113)) { + /* allow_town_roads is added, set it if town_layout wasn't TL_NO_ROADS */ + if (_settings_game.economy.town_layout == 0) { // was TL_NO_ROADS + _settings_game.economy.allow_town_roads = false; + _settings_game.economy.town_layout = TL_BETTER_ROADS; + } else { + _settings_game.economy.allow_town_roads = true; + _settings_game.economy.town_layout = _settings_game.economy.town_layout - 1; + } + + /* Initialize layout of all towns. Older versions were using different + * generator for random town layout, use it if needed. */ + Town *t; + FOR_ALL_TOWNS(t) { + if (_settings_game.economy.town_layout != TL_RANDOM) { + t->layout = _settings_game.economy.town_layout; + continue; + } + + /* Use old layout randomizer code */ + byte layout = TileHash(TileX(t->xy), TileY(t->xy)) % 6; + switch (layout) { + default: break; + case 5: layout = 1; break; + case 0: layout = 2; break; + } + t->layout = layout - 1; + } + } + GamelogPrintDebug(1); bool ret = InitializeWindowsAndCaches(); diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 43b0616f52..2044eb9b40 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -38,7 +38,7 @@ #include "saveload_internal.h" -extern const uint16 SAVEGAME_VERSION = 112; +extern const uint16 SAVEGAME_VERSION = 113; SavegameType _savegame_type; ///< type of savegame we are loading diff --git a/src/saveload/saveload_internal.h b/src/saveload/saveload_internal.h index d364bebab5..19a5b5cbff 100644 --- a/src/saveload/saveload_internal.h +++ b/src/saveload/saveload_internal.h @@ -21,7 +21,6 @@ void FixOldWaypoints(); void AfterLoadWaypoints(); void AfterLoadVehicles(bool part_of_load); void AfterLoadStations(); -void AfterLoadTown(); void UpdateHousesAndTowns(); void UpdateOldAircraft(); diff --git a/src/saveload/town_sl.cpp b/src/saveload/town_sl.cpp index c1b59876e6..2b25356a71 100644 --- a/src/saveload/town_sl.cpp +++ b/src/saveload/town_sl.cpp @@ -127,6 +127,7 @@ static const SaveLoad _town_desc[] = { SLE_CONDVAR(Town, exclusive_counter, SLE_UINT8, 2, SL_MAX_VERSION), SLE_CONDVAR(Town, larger_town, SLE_BOOL, 56, SL_MAX_VERSION), + SLE_CONDVAR(Town, layout, SLE_UINT8, 113, SL_MAX_VERSION), /* reserve extra space in savegame here. (currently 30 bytes) */ SLE_CONDNULL(30, 2, SL_MAX_VERSION), @@ -195,12 +196,6 @@ static void Load_TOWN() _cur_town_ctr = 0; } -void AfterLoadTown() -{ - Town *t; - FOR_ALL_TOWNS(t) t->InitializeLayout(); -} - extern const ChunkHandler _town_chunk_handlers[] = { { 'HIDS', Save_HOUSEIDS, Load_HOUSEIDS, CH_ARRAY }, { 'CITY', Save_TOWN, Load_TOWN, CH_ARRAY | CH_LAST}, diff --git a/src/settings.cpp b/src/settings.cpp index ac58114616..d2e149629d 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1030,23 +1030,6 @@ static bool DifficultyNoiseChange(int32 i) return DifficultyChange(i); } -/** - * Check for right TownLayout usage in editor mode. - * The No Road mode is not desirable since towns have to be - * able to grow. If a user desires to have a town with no road, - * he can easily remove them himself. This would create less confusion - * @param p1 unused - * @return always true - */ -static bool CheckTownLayout(int32 p1) -{ - if (_settings_game.economy.town_layout == TL_NO_ROADS && _game_mode == GM_EDITOR) { - ShowErrorMessage(INVALID_STRING_ID, STR_CONFIG_PATCHES_TOWN_LAYOUT_INVALID, 0, 0); - _settings_game.economy.town_layout = TL_ORIGINAL; - } - return true; -} - /** * Check whether the road side may be changed. * @param p1 unused @@ -1322,7 +1305,8 @@ const SettingDesc _patch_settings[] = { SDT_BOOL(GameSettings, construction.longbridges, 0,NN, true, STR_CONFIG_PATCHES_LONGBRIDGES, NULL), SDT_BOOL(GameSettings, construction.signal_side, N,NN, true, STR_CONFIG_PATCHES_SIGNALSIDE, RedrawScreen), SDT_BOOL(GameSettings, station.always_small_airport, 0,NN, false, STR_CONFIG_PATCHES_SMALL_AIRPORTS, NULL), - SDT_CONDVAR(GameSettings, economy.town_layout, SLE_UINT8, 59, SL_MAX_VERSION, 0,MS,TL_ORIGINAL,TL_NO_ROADS,NUM_TLS-1,1, STR_CONFIG_PATCHES_TOWN_LAYOUT, CheckTownLayout), + SDT_CONDVAR(GameSettings, economy.town_layout, SLE_UINT8, 59, SL_MAX_VERSION, 0,MS,TL_BETTER_ROADS,TL_BEGIN,NUM_TLS-1,1, STR_CONFIG_PATCHES_TOWN_LAYOUT, NULL), + SDT_CONDBOOL(GameSettings, economy.allow_town_roads, 113, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_PATCHES_ALLOW_TOWN_ROADS, NULL), SDT_VAR(GameSettings, vehicle.train_acceleration_model, SLE_UINT8, 0,MS, 0, 0, 1, 1, STR_CONFIG_PATCHES_TRAIN_ACCELERATION_MODEL, TrainAccelerationModelChanged), SDT_BOOL(GameSettings, pf.forbid_90_deg, 0, 0, false, STR_CONFIG_PATCHES_FORBID_90_DEG, NULL), diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 9cae1373f5..f341af58af 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -1097,6 +1097,7 @@ static PatchEntry _patches_economy_towns[] = { PatchEntry("economy.bribe"), PatchEntry("economy.exclusive_rights"), PatchEntry("economy.town_layout"), + PatchEntry("economy.allow_town_roads"), PatchEntry("economy.mod_road_rebuild"), PatchEntry("economy.town_growth_rate"), PatchEntry("economy.larger_towns"), diff --git a/src/settings_type.h b/src/settings_type.h index c7fec6d4c2..d40e2b9c6a 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -320,6 +320,7 @@ struct EconomySettings { uint8 larger_towns; ///< the number of cities to build. These start off larger and grow twice as fast uint8 initial_city_size; ///< multiplier for the initial size of the cities compared to towns TownLayoutByte town_layout; ///< select town layout + bool allow_town_roads; ///< towns are allowed to build roads (always allowed when generating world / in SE) 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) }; diff --git a/src/town.h b/src/town.h index 6b80762bfa..62a6b25242 100644 --- a/src/town.h +++ b/src/town.h @@ -166,6 +166,7 @@ struct Town : PoolItem { /* If this is a larger town, and should grow more quickly. */ bool larger_town; + TownLayoutByte layout; ///< town specific road layout /* NOSAVE: UpdateTownRadius updates this given the house count. */ uint32 squared_town_zone_radius[HZB_END]; @@ -173,9 +174,6 @@ struct Town : PoolItem { /* NOSAVE: The number of each type of building in the town. */ BuildingCounts building_counts; - /* NOSAVE: The town specific road layout */ - TownLayout layout; - /** * Creates a new town */ @@ -188,30 +186,20 @@ 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 { + inline uint16 MaxTownNoise() const + { if (this->population == 0) return 0; // no population? no noise return ((this->population / _settings_game.economy.town_noise_population[_settings_game.difficulty.town_council_tolerance]) + 3); } }; -/** - * Get the current valid layout for the town - * @return the active layout for this town - */ -inline TownLayout Town::GetActiveLayout() const -{ - return (_settings_game.economy.town_layout == TL_RANDOM) ? this->layout : _settings_game.economy.town_layout; -} - struct HouseSpec { /* Standard properties */ Year min_year; ///< introduction year of the house diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 4d00a9e913..4a5600d034 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -113,20 +113,16 @@ Town::~Town() } /** - * Generate a random town road layout. - * - * The layout is based on the TileHash. + * Assigns town layout. If Random, generates one based on TileHash. */ void Town::InitializeLayout() { - this->layout = (TownLayout)(TileHash(TileX(this->xy), TileY(this->xy)) % NUM_TLS); - - /* Set invalid layouts to valid ones */ - switch (this->layout) { - default: break; - case TL_RANDOM: this->layout = TL_ORIGINAL; break; - case TL_NO_ROADS: this->layout = TL_BETTER_ROADS; break; + if (_settings_game.economy.town_layout != TL_RANDOM) { + this->layout = _settings_game.economy.town_layout; + return; } + + this->layout = TileHash(TileX(this->xy), TileY(this->xy)) % (NUM_TLS - 1); } Money HouseSpec::GetRemovalCost() const @@ -785,7 +781,7 @@ static bool IsRoadAllowedHere(Town *t, TileIndex tile, DiagDirection dir) if (cur_slope == SLOPE_FLAT) { no_slope: /* Tile has no slope */ - switch (t->GetActiveLayout()) { + switch (t->layout) { default: NOT_REACHED(); case TL_ORIGINAL: // Disallow the road if any neighboring tile has a road (distance: 1) @@ -858,7 +854,7 @@ static RoadBits GetTownRoadGridElement(Town *t, TileIndex tile, DiagDirection di TileIndexDiffC grid_pos = TileIndexToTileIndexDiffC(t->xy, tile); // Vector from downtown to the tile RoadBits rcmd = ROAD_NONE; - switch (t->GetActiveLayout()) { + switch (t->layout) { default: NOT_REACHED(); case TL_2X2_GRID: @@ -1018,7 +1014,6 @@ static bool GrowTownWithBridge(const Town *t, const TileIndex tile, const DiagDi * @li TL_2X2_GRID * @li TL_3X3_GRID * @li Forbid roads, only build houses - * @li TL_NO_ROADS * * @param tile_ptr The current tile * @param cur_rb The current tiles RoadBits @@ -1037,16 +1032,15 @@ static void GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, DiagDirection t * to say that this is the last iteration. */ _grow_town_result = GROWTH_SEARCH_STOPPED; + if (!_settings_game.economy.allow_town_roads && !_generating_world) return; + /* Remove hills etc */ if (!_settings_game.construction.build_on_slopes || Chance16(1, 6)) LevelTownLand(tile); /* Is a road allowed here? */ - switch (t1->GetActiveLayout()) { + switch (t1->layout) { default: NOT_REACHED(); - case TL_NO_ROADS: /* Disallow Roads */ - return; - case TL_3X3_GRID: case TL_2X2_GRID: rcmd = GetTownRoadGridElement(t1, tile, target_dir); @@ -1089,11 +1083,10 @@ static void GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, DiagDirection t * the fitting RoadBits */ _grow_town_result = GROWTH_SEARCH_STOPPED; - switch (t1->GetActiveLayout()) { - default: NOT_REACHED(); + if (!_settings_game.economy.allow_town_roads && !_generating_world) return; - case TL_NO_ROADS: /* Disallow Roads */ - return; + switch (t1->layout) { + default: NOT_REACHED(); case TL_3X3_GRID: case TL_2X2_GRID: @@ -1106,7 +1099,7 @@ static void GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, DiagDirection t break; } } else { - bool allow_house = false; // Value which decides if we want to construct a house + bool allow_house = true; // Value which decides if we want to construct a house /* Reached a tunnel/bridge? Then continue at the other side of it. */ if (IsTileType(tile, MP_TUNNELBRIDGE)) { @@ -1129,32 +1122,30 @@ static void GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, DiagDirection t if (!IsValidTile(house_tile) || !IsValidTile(house_tile + TileOffsByDiagDir(target_dir))) return; - switch (t1->GetActiveLayout()) { - default: NOT_REACHED(); - - case TL_NO_ROADS: - allow_house = true; - break; + if (_settings_game.economy.allow_town_roads || _generating_world) { + switch (t1->layout) { + default: NOT_REACHED(); - case TL_3X3_GRID: /* Use 2x2 grid afterwards! */ - GrowTownWithExtraHouse(t1, TileAddByDiagDir(house_tile, target_dir)); - /* FALL THROUGH */ + case TL_3X3_GRID: /* Use 2x2 grid afterwards! */ + GrowTownWithExtraHouse(t1, TileAddByDiagDir(house_tile, target_dir)); + /* FALL THROUGH */ - case TL_2X2_GRID: - rcmd = GetTownRoadGridElement(t1, house_tile, target_dir); - allow_house = (rcmd == ROAD_NONE); - break; + case TL_2X2_GRID: + rcmd = GetTownRoadGridElement(t1, house_tile, target_dir); + allow_house = (rcmd == ROAD_NONE); + break; - case TL_BETTER_ROADS: /* Use original afterwards! */ - GrowTownWithExtraHouse(t1, TileAddByDiagDir(house_tile, target_dir)); - /* FALL THROUGH */ + case TL_BETTER_ROADS: /* Use original afterwards! */ + GrowTownWithExtraHouse(t1, TileAddByDiagDir(house_tile, target_dir)); + /* FALL THROUGH */ - case TL_ORIGINAL: - /* Allow a house at the edge. 60% chance or - * always ok if no road allowed. */ - rcmd = DiagDirToRoadBits(target_dir); - allow_house = (!IsRoadAllowedHere(t1, house_tile, target_dir) || Chance16(6, 10)); - break; + case TL_ORIGINAL: + /* Allow a house at the edge. 60% chance or + * always ok if no road allowed. */ + rcmd = DiagDirToRoadBits(target_dir); + allow_house = (!IsRoadAllowedHere(t1, house_tile, target_dir) || Chance16(6, 10)); + break; + } } if (allow_house) { @@ -1207,7 +1198,7 @@ static int GrowTownAtRoad(Town *t, TileIndex tile) /* Number of times to search. * Better roads, 2X2 and 3X3 grid grow quite fast so we give * them a little handicap. */ - switch (t->GetActiveLayout()) { + switch (t->layout) { case TL_BETTER_ROADS: _grow_town_result = 10 + t->num_houses * 2 / 9; break; @@ -1279,13 +1270,6 @@ static RoadBits GenRandomRoadBits() */ static bool GrowTown(Town *t) { - /* Let the town be a ghost town - * The player wanted it in such a way. Thus there he has it. ;) - * Never reached in editor mode. */ - if (_settings_game.economy.town_layout == TL_NO_ROADS && _generating_world) { - return false; - } - static const TileIndexDiffC _town_coord_mod[] = { {-1, 0}, { 1, 1}, @@ -1794,7 +1778,7 @@ static inline bool TownLayoutAllowsHouseHere(Town *t, TileIndex tile) { TileIndexDiffC grid_pos = TileIndexToTileIndexDiffC(t->xy, tile); - switch (t->GetActiveLayout()) { + switch (t->layout) { case TL_2X2_GRID: if ((grid_pos.x % 3) == 0 || (grid_pos.y % 3) == 0) return false; break; @@ -1825,7 +1809,7 @@ static inline bool TownLayoutAllows2x2HouseHere(Town *t, TileIndex tile) uint dx = MapSize() + TileX(t->xy) - TileX(tile); uint dy = MapSize() + TileY(t->xy) - TileY(tile); - switch (t->GetActiveLayout()) { + switch (t->layout) { case TL_2X2_GRID: if ((dx % 3) != 0 || (dy % 3) != 0) return false; break; diff --git a/src/town_type.h b/src/town_type.h index 817e19df7a..b863741b95 100644 --- a/src/town_type.h +++ b/src/town_type.h @@ -65,8 +65,8 @@ enum { * Town Layouts */ enum TownLayout { - TL_NO_ROADS = 0, ///< Build no more roads, but still build houses - TL_ORIGINAL, ///< Original algorithm (min. 1 distance between roads) + TL_BEGIN = 0, + TL_ORIGINAL = 0, ///< Original algorithm (min. 1 distance between roads) TL_BETTER_ROADS, ///< Extended original algorithm (min. 2 distance between roads) TL_2X2_GRID, ///< Geometric 2x2 grid algorithm TL_3X3_GRID, ///< Geometric 3x3 grid algorithm @@ -78,7 +78,7 @@ enum TownLayout { /* It needs to be 8bits, because we save and load it as such */ /** Define basic enum properties */ -template <> struct EnumPropsT : MakeEnumPropsT {}; +template <> struct EnumPropsT : MakeEnumPropsT {}; typedef TinyEnumT TownLayoutByte; //typedefing-enumification of TownLayout enum {