diff --git a/src/genworld.cpp b/src/genworld.cpp index d5281a2f81..2499248cb1 100644 --- a/src/genworld.cpp +++ b/src/genworld.cpp @@ -103,6 +103,10 @@ static void _GenerateWorld() IncreaseGeneratingWorldProgress(GWP_MAP_INIT); /* Must start economy early because of the costs. */ StartupEconomy(); + if (!CheckTownRoadTypes()) { + HandleGeneratingWorldAbortion(); + return; + } bool landscape_generated = false; diff --git a/src/lang/english.txt b/src/lang/english.txt index 860915ac3c..6f24305f03 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -5286,6 +5286,11 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Change y STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}No vehicles are available yet STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Start a new game after {DATE_SHORT} or use a NewGRF that provides early vehicles +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_AT_ALL :{WHITE}No town-buildable road types are available +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Change your NewGRF configuration +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_YET :{WHITE}No town-buildable road types are available yet +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_YET_EXPLANATION :{WHITE}Start a new game after {DATE_SHORT} or use a NewGRF that provides early town-buildable road types + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Can't make train pass signal at danger... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Can't reverse direction of train... diff --git a/src/town.h b/src/town.h index 28ffa5047d..2b059dbe59 100644 --- a/src/town.h +++ b/src/town.h @@ -315,5 +315,6 @@ inline uint16_t TownTicksToGameTicks(uint16_t ticks) RoadType GetTownRoadType(); +bool CheckTownRoadTypes(); #endif /* TOWN_H */ diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index fa18e2b422..252e3b2fa0 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -940,6 +940,45 @@ RoadType GetTownRoadType() return best_rt; } +/** + * Get the calendar date of the earliest town-buildable road type. + * @return introduction date of earliest road type, or INT32_MAX if none available. + */ +static TimerGameCalendar::Date GetTownRoadTypeFirstIntroductionDate() +{ + const RoadTypeInfo *best = nullptr; + for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) { + if (RoadTypeIsTram(rt)) continue; + const RoadTypeInfo *rti = GetRoadTypeInfo(rt); + if (rti->label == 0) continue; // Unused road type. + if (!HasBit(rti->flags, ROTF_TOWN_BUILD)) continue; // Town can't build this road type. + + if (best != nullptr && rti->introduction_date >= best->introduction_date) continue; + best = rti; + } + + if (best == nullptr) return INT32_MAX; + return best->introduction_date; +} + +/** + * Check if towns are able to build road. + * @return true iff the towns are currently able to build road. + */ +bool CheckTownRoadTypes() +{ + auto min_date = GetTownRoadTypeFirstIntroductionDate(); + if (min_date <= TimerGameCalendar::date) return true; + + if (min_date < INT32_MAX) { + SetDParam(0, min_date); + ShowErrorMessage(STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_YET, STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_YET_EXPLANATION, WL_CRITICAL); + } else { + ShowErrorMessage(STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_AT_ALL, STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_AT_ALL_EXPLANATION, WL_CRITICAL); + } + return false; +} + /** * Check for parallel road inside a given distance. * Assuming a road from (tile - TileOffsByDiagDir(dir)) to tile,