diff --git a/src/cheat_gui.cpp b/src/cheat_gui.cpp index 27211daa56..5e5c97c98b 100644 --- a/src/cheat_gui.cpp +++ b/src/cheat_gui.cpp @@ -105,7 +105,7 @@ static int32_t ClickChangeDateCheat(int32_t new_value, int32_t change_direction) { /* Don't allow changing to an invalid year, or the current year. */ auto new_year = Clamp(TimerGameCalendar::Year(new_value), MIN_YEAR, MAX_YEAR); - if (new_year == TimerGameCalendar::year) return TimerGameCalendar::year; + if (new_year == TimerGameCalendar::year) return static_cast(TimerGameCalendar::year); TimerGameCalendar::YearMonthDay ymd; TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date, &ymd); @@ -125,7 +125,7 @@ static int32_t ClickChangeDateCheat(int32_t new_value, int32_t change_direction) InvalidateWindowClassesData(WC_TRUCK_STATION, 0); InvalidateWindowClassesData(WC_BUILD_OBJECT, 0); ResetSignalVariant(); - return TimerGameCalendar::year; + return static_cast(TimerGameCalendar::year); } /** diff --git a/src/company_gui.cpp b/src/company_gui.cpp index 94509c7a62..409c57a276 100644 --- a/src/company_gui.cpp +++ b/src/company_gui.cpp @@ -437,7 +437,7 @@ struct CompanyFinancesWindow : Window { auto age = std::min(TimerGameCalendar::year - c->inaugurated_year, TimerGameCalendar::Year(2)); int wid_offset = widget - WID_CF_EXPS_PRICE1; if (wid_offset <= age) { - DrawYearColumn(r, TimerGameCalendar::year - (age - wid_offset), c->yearly_expenses[age - wid_offset]); + DrawYearColumn(r, TimerGameCalendar::year - (age - wid_offset), c->yearly_expenses[static_cast(age - wid_offset)]); } break; } diff --git a/src/core/format.hpp b/src/core/format.hpp index f701ea6dfe..97abe7951c 100644 --- a/src/core/format.hpp +++ b/src/core/format.hpp @@ -28,8 +28,8 @@ struct fmt::formatter::value>> : fmt:: }; template -struct fmt::formatter::value>> : fmt::formatter { - using underlying_type = typename T::Type; +struct fmt::formatter::value>> : fmt::formatter { + using underlying_type = typename T::BaseType; using parent = typename fmt::formatter; constexpr fmt::format_parse_context::iterator parse(fmt::format_parse_context &ctx) { diff --git a/src/core/math_func.hpp b/src/core/math_func.hpp index 1b0908db32..9596433e7b 100644 --- a/src/core/math_func.hpp +++ b/src/core/math_func.hpp @@ -10,6 +10,7 @@ #ifndef MATH_FUNC_HPP #define MATH_FUNC_HPP +#include "strong_typedef_type.hpp" /** * Returns the absolute value of (scalar) variable. @@ -162,7 +163,7 @@ static inline uint ClampU(const uint a, const uint min, const uint max) * for the return type. * @see Clamp(int, int, int) */ -template +template ::value, int> = 0> constexpr To ClampTo(From value) { static_assert(std::numeric_limits::is_integer, "Do not clamp from non-integer values"); @@ -213,6 +214,15 @@ constexpr To ClampTo(From value) return static_cast(std::min(value, std::numeric_limits::max())); } +/** + * Specialization of ClampTo for #StrongType::Typedef. + */ +template ::value, int> = 0> +constexpr To ClampTo(From value) +{ + return ClampTo(static_cast(value)); +} + /** * Returns the (absolute) difference between two (scalar) variables * @@ -254,10 +264,14 @@ static inline bool IsInsideBS(const T x, const size_t base, const size_t size) * @param max The maximum of the interval * @see IsInsideBS() */ -template +template , std::is_base_of>, int> = 0> static constexpr inline bool IsInsideMM(const T x, const size_t min, const size_t max) noexcept { - return (size_t)(x - min) < (max - min); + if constexpr (std::is_base_of_v) { + return (size_t)(static_cast(x) - min) < (max - min); + } else { + return (size_t)(x - min) < (max - min); + } } /** diff --git a/src/core/strong_typedef_type.hpp b/src/core/strong_typedef_type.hpp index ec639688bb..0c1abe9843 100644 --- a/src/core/strong_typedef_type.hpp +++ b/src/core/strong_typedef_type.hpp @@ -10,74 +10,199 @@ #ifndef STRONG_TYPEDEF_TYPE_HPP #define STRONG_TYPEDEF_TYPE_HPP -/** Non-templated base for #StrongTypedef for use with type trait queries. */ +#include "../3rdparty/fmt/format.h" + +/** Non-templated base for #StrongType::Typedef for use with type trait queries. */ struct StrongTypedefBase {}; -/** - * Templated helper to make a type-safe 'typedef' representing a single POD value. - * A normal 'typedef' is not distinct from its base type and will be treated as - * identical in many contexts. This class provides a distinct type that can still - * be assign from and compared to values of its base type. - * - * @note This is meant to be used as a base class, not directly. - * @tparam T Storage type - * @tparam Tthis Type of the derived class (i.e. the concrete usage of this class). - */ -template -struct StrongTypedef : StrongTypedefBase { - using Type = T; +namespace StrongType { + /** + * Mix-in which makes the new Typedef comparable with itself and its base type. + */ + struct Compare { + template + struct mixin { + friend constexpr bool operator ==(const TType &lhs, const TType &rhs) { return lhs.value == rhs.value; } + friend constexpr bool operator ==(const TType &lhs, const TBaseType &rhs) { return lhs.value == rhs; } - T value{}; ///< Backing storage field. + friend constexpr bool operator !=(const TType &lhs, const TType &rhs) { return lhs.value != rhs.value; } + friend constexpr bool operator !=(const TType &lhs, const TBaseType &rhs) { return lhs.value != rhs; } - debug_inline constexpr StrongTypedef() = default; - debug_inline constexpr StrongTypedef(const StrongTypedef &o) = default; - debug_inline constexpr StrongTypedef(StrongTypedef &&o) = default; + friend constexpr bool operator <=(const TType &lhs, const TType &rhs) { return lhs.value <= rhs.value; } + friend constexpr bool operator <=(const TType &lhs, const TBaseType &rhs) { return lhs.value <= rhs; } - debug_inline constexpr StrongTypedef(const T &value) : value(value) {} + friend constexpr bool operator <(const TType &lhs, const TType &rhs) { return lhs.value < rhs.value; } + friend constexpr bool operator <(const TType &lhs, const TBaseType &rhs) { return lhs.value < rhs; } - debug_inline constexpr Tthis &operator =(const Tthis &rhs) { this->value = rhs.value; return static_cast(*this); } - debug_inline constexpr Tthis &operator =(Tthis &&rhs) { this->value = std::move(rhs.value); return static_cast(*this); } - debug_inline constexpr Tthis &operator =(const T &rhs) { this->value = rhs; return static_cast(*this); } + friend constexpr bool operator >=(const TType &lhs, const TType &rhs) { return lhs.value >= rhs.value; } + friend constexpr bool operator >=(const TType &lhs, const TBaseType &rhs) { return lhs.value >= rhs; } - explicit constexpr operator T() const { return this->value; } + friend constexpr bool operator >(const TType &lhs, const TType &rhs) { return lhs.value > rhs.value; } + friend constexpr bool operator >(const TType &lhs, const TBaseType &rhs) { return lhs.value > rhs; } + }; + }; - constexpr bool operator ==(const Tthis &rhs) const { return this->value == rhs.value; } - constexpr bool operator !=(const Tthis &rhs) const { return this->value != rhs.value; } - constexpr bool operator ==(const T &rhs) const { return this->value == rhs; } - constexpr bool operator !=(const T &rhs) const { return this->value != rhs; } -}; + /** + * Mix-in which makes the new Typedef behave more like an integer. This means you can add and subtract from it. + * + * Operators like divide, multiply and module are explicitly denied, as that often makes little sense for the + * new type. If you want to do these actions on the new Typedef, you are better off first casting it to the + * base type. + */ + struct Integer { + template + struct mixin { + friend constexpr TType &operator ++(TType &lhs) { lhs.value++; return lhs; } + friend constexpr TType &operator --(TType &lhs) { lhs.value--; return lhs; } + friend constexpr TType operator ++(TType &lhs, int) { TType res = lhs; lhs.value++; return res; } + friend constexpr TType operator --(TType &lhs, int) { TType res = lhs; lhs.value--; return res; } -/** - * Extension of #StrongTypedef with operators for addition and subtraction. - * @tparam T Storage type - * @tparam Tthis Type of the derived class (i.e. the concrete usage of this class). - */ -template -struct StrongIntegralTypedef : StrongTypedef { - using StrongTypedef::StrongTypedef; + friend constexpr TType &operator +=(TType &lhs, const TType &rhs) { lhs.value += rhs.value; return lhs; } + friend constexpr TType operator +(const TType &lhs, const TType &rhs) { return TType{ lhs.value + rhs.value }; } + friend constexpr TType operator +(const TType &lhs, const TBaseType &rhs) { return TType{ lhs.value + rhs }; } - debug_inline constexpr StrongIntegralTypedef() = default; - debug_inline constexpr StrongIntegralTypedef(const StrongIntegralTypedef &o) = default; - debug_inline constexpr StrongIntegralTypedef(StrongIntegralTypedef &&o) = default; + friend constexpr TType &operator -=(TType &lhs, const TType &rhs) { lhs.value -= rhs.value; return lhs; } + friend constexpr TType operator -(const TType &lhs, const TType &rhs) { return TType{ lhs.value - rhs.value }; } + friend constexpr TType operator -(const TType &lhs, const TBaseType &rhs) { return TType{ lhs.value - rhs }; } - debug_inline constexpr StrongIntegralTypedef(const T &value) : StrongTypedef(value) {} + /* For most new types, the rest of the operators make no sense. For example, + * what does it actually mean to multiply a Year with a value. Or to do a + * bitwise OR on a Date. Or to divide a TileIndex by 2. Conceptually, they + * don't really mean anything. So force the user to first cast it to the + * base type, so the operation no longer returns the new Typedef. */ - debug_inline constexpr Tthis &operator =(const Tthis &rhs) { this->value = rhs.value; return static_cast(*this); } - debug_inline constexpr Tthis &operator =(Tthis &&rhs) { this->value = std::move(rhs.value); return static_cast(*this); } - debug_inline constexpr Tthis &operator =(const T &rhs) { this->value = rhs; return static_cast(*this); } + constexpr TType &operator *=(const TType &rhs) = delete; + constexpr TType operator *(const TType &rhs) = delete; + constexpr TType operator *(const TBaseType &rhs) = delete; - constexpr Tthis &operator ++() { this->value++; return static_cast(*this); } - constexpr Tthis &operator --() { this->value--; return static_cast(*this); } - constexpr Tthis operator ++(int) { auto res = static_cast(*this); this->value++; return res; } - constexpr Tthis operator --(int) { auto res = static_cast(*this); this->value--; return res; } + constexpr TType &operator /=(const TType &rhs) = delete; + constexpr TType operator /(const TType &rhs) = delete; + constexpr TType operator /(const TBaseType &rhs) = delete; - constexpr Tthis &operator +=(const Tthis &rhs) { this->value += rhs.value; return *static_cast(this); } - constexpr Tthis &operator -=(const Tthis &rhs) { this->value -= rhs.value; return *static_cast(this); } + constexpr TType &operator %=(const TType &rhs) = delete; + constexpr TType operator %(const TType &rhs) = delete; + constexpr TType operator %(const TBaseType &rhs) = delete; - constexpr Tthis operator +(const Tthis &rhs) const { return Tthis{ this->value + rhs.value }; } - constexpr Tthis operator -(const Tthis &rhs) const { return Tthis{ this->value - rhs.value }; } - constexpr Tthis operator +(const T &rhs) const { return Tthis{ this->value + rhs }; } - constexpr Tthis operator -(const T &rhs) const { return Tthis{ this->value - rhs }; } -}; + constexpr TType &operator &=(const TType &rhs) = delete; + constexpr TType operator &(const TType &rhs) = delete; + constexpr TType operator &(const TBaseType &rhs) = delete; + + constexpr TType &operator |=(const TType &rhs) = delete; + constexpr TType operator |(const TType &rhs) = delete; + constexpr TType operator |(const TBaseType &rhs) = delete; + + constexpr TType &operator ^=(const TType &rhs) = delete; + constexpr TType operator ^(const TType &rhs) = delete; + constexpr TType operator ^(const TBaseType &rhs) = delete; + + constexpr TType &operator <<=(const TType &rhs) = delete; + constexpr TType operator <<(const TType &rhs) = delete; + constexpr TType operator <<(const TBaseType &rhs) = delete; + + constexpr TType &operator >>=(const TType &rhs) = delete; + constexpr TType operator >>(const TType &rhs) = delete; + constexpr TType operator >>(const TBaseType &rhs) = delete; + + constexpr TType operator ~() = delete; + constexpr TType operator -() = delete; + }; + }; + + /** + * Mix-in which makes the new Typedef compatible with another type (which is not the base type). + * + * @note The base type of the new Typedef will be cast to the other type; so make sure they are compatible. + * + * @tparam TCompatibleType The other type to be compatible with. + */ + template + struct Compatible { + template + struct mixin { + friend constexpr bool operator ==(const TType &lhs, TCompatibleType rhs) { return lhs.value == static_cast(rhs); } + friend constexpr bool operator !=(const TType &lhs, TCompatibleType rhs) { return lhs.value != static_cast(rhs); } + + friend constexpr bool operator <=(const TType &lhs, TCompatibleType rhs) { return lhs.value <= static_cast(rhs); } + friend constexpr bool operator <(const TType &lhs, TCompatibleType rhs) { return lhs.value < static_cast(rhs); } + friend constexpr bool operator >=(const TType &lhs, TCompatibleType rhs) { return lhs.value >= static_cast(rhs); } + friend constexpr bool operator >(const TType &lhs, TCompatibleType rhs) { return lhs.value > static_cast(rhs); } + + friend constexpr TType operator +(const TType &lhs, TCompatibleType rhs) { return { static_cast(lhs.value + rhs) }; } + friend constexpr TType operator -(const TType &lhs, TCompatibleType rhs) { return { static_cast(lhs.value - rhs) }; } + }; + }; + + /** + * Mix-in which makes the new Typedef implicitly convertible to its base type. + * + * Be careful: when allowing implicit conversion, you won't notice if this type is assigned to a compatible, but different, type. + * For example: + * + * StrongType::Typedef a = 1; + * StrongType::Typedef b = 2; + * a = b; // OK + */ + struct Implicit { + template + struct mixin { + constexpr operator TBaseType () const { return static_cast(*this).value; } + }; + }; + + /** + * Mix-in which makes the new Typedef explicitly convertible to its base type. + */ + struct Explicit { + template + struct mixin { + explicit constexpr operator TBaseType () const { return static_cast(*this).value; } + }; + }; + + /** + * Templated helper to make a type-safe 'typedef' representing a single POD value. + * A normal 'typedef' is not distinct from its base type and will be treated as + * identical in many contexts. This class provides a distinct type that can still + * be assign from and compared to values of its base type. + * + * Example usage: + * + * using MyType = StrongType::Typedef; + * + * @tparam TBaseType Type of the derived class (i.e. the concrete usage of this class). + * @tparam TTag An unique struct to keep types of the same TBaseType distinct. + * @tparam TProperties A list of mixins to add to the class. + */ + template + struct EMPTY_BASES Typedef : public StrongTypedefBase, public TProperties::template mixin, TBaseType>... { + using BaseType = TBaseType; + + constexpr Typedef() = default; + constexpr Typedef(const Typedef &) = default; + constexpr Typedef(Typedef &&) = default; + + constexpr Typedef(const TBaseType &value) : value(value) {} + + constexpr Typedef &operator =(const Typedef &rhs) { this->value = rhs.value; return *this; } + constexpr Typedef &operator =(Typedef &&rhs) { this->value = std::move(rhs.value); return *this; } + constexpr Typedef &operator =(const TBaseType &rhs) { this->value = rhs; return *this; } + + /* Only allow TProperties classes access to the internal value. Everyone else needs to do an explicit cast. */ + friend struct Explicit; + friend struct Implicit; + friend struct Compare; + friend struct Integer; + template friend struct Compatible; + +/* GCC / MSVC don't pick up on the "friend struct" above, where CLang does. + * As in our CI we compile for all three targets, it is sufficient to have one + * that errors on this; but nobody should be using "value" directly. Instead, + * use a static_cast<> to convert to the base type. */ +#ifdef __clang__ + protected: +#endif /* __clang__ */ + TBaseType value{}; + }; +} #endif /* STRONG_TYPEDEF_TYPE_HPP */ diff --git a/src/date_gui.cpp b/src/date_gui.cpp index fcb872f51a..febf505836 100644 --- a/src/date_gui.cpp +++ b/src/date_gui.cpp @@ -91,9 +91,9 @@ struct SetDateWindow : Window { case WID_SD_YEAR: for (TimerGameCalendar::Year i = this->min_year; i <= this->max_year; i++) { SetDParam(0, i); - list.emplace_back(new DropDownListStringItem(STR_JUST_INT, i, false)); + list.emplace_back(new DropDownListStringItem(STR_JUST_INT, static_cast(i), false)); } - selected = this->date.year; + selected = static_cast(this->date.year); break; } diff --git a/src/date_type.h b/src/date_type.h index 3f69f6050b..412fcd275e 100644 --- a/src/date_type.h +++ b/src/date_type.h @@ -58,9 +58,10 @@ static constexpr TimerGameCalendar::Year ORIGINAL_MAX_YEAR = 2090; */ static constexpr TimerGameCalendar::Date DateAtStartOfYear(TimerGameCalendar::Year year) { - uint number_of_leap_years = (year == 0) ? 0 : ((year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400 + 1); + int32_t year_as_int = static_cast(year); + uint number_of_leap_years = (year == 0) ? 0 : ((year_as_int - 1) / 4 - (year_as_int - 1) / 100 + (year_as_int - 1) / 400 + 1); - return (DAYS_IN_YEAR * year) + number_of_leap_years; + return (DAYS_IN_YEAR * year_as_int) + number_of_leap_years; } /** @@ -70,7 +71,7 @@ static constexpr TimerGameCalendar::Date DateAtStartOfYear(TimerGameCalendar::Ye */ static inline TimerGameCalendar::Year DateToYear(TimerGameCalendar::Date date) { - return date / DAYS_IN_LEAP_YEAR; + return static_cast(date) / DAYS_IN_LEAP_YEAR; } /** diff --git a/src/depot_gui.cpp b/src/depot_gui.cpp index 50101fb9db..b7fb593a45 100644 --- a/src/depot_gui.cpp +++ b/src/depot_gui.cpp @@ -360,7 +360,7 @@ struct DepotWindow : Window { DrawSpriteIgnorePadding((v->vehstatus & VS_STOPPED) ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, PAL_NONE, flag, false, SA_CENTER); SetDParam(0, v->unitnumber); - DrawString(text, STR_JUST_COMMA, (uint16_t)(v->max_age - DAYS_IN_LEAP_YEAR) >= v->age ? TC_BLACK : TC_RED); + DrawString(text, STR_JUST_COMMA, (v->max_age - DAYS_IN_LEAP_YEAR) >= v->age ? TC_BLACK : TC_RED); } } diff --git a/src/economy.cpp b/src/economy.cpp index a7e36ba172..5af92821c7 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -928,7 +928,7 @@ void StartupEconomy() if (_settings_game.economy.inflation) { /* Apply inflation that happened before our game start year. */ - int months = (std::min(TimerGameCalendar::year, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR) * 12; + int months = static_cast(std::min(TimerGameCalendar::year, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR) * 12; for (int i = 0; i < months; i++) { AddInflation(false); } diff --git a/src/engine.cpp b/src/engine.cpp index 28f0054d8e..a66bc501da 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -662,7 +662,7 @@ void SetYearEngineAgingStops() /* Base year ending date on half the model life */ TimerGameCalendar::YearMonthDay ymd; - TimerGameCalendar::ConvertDateToYMD(ei->base_intro + DateAtStartOfYear(ei->lifelength) / 2, &ymd); + TimerGameCalendar::ConvertDateToYMD(ei->base_intro + static_cast(DateAtStartOfYear(ei->lifelength)) / 2, &ymd); _year_engine_aging_stops = std::max(_year_engine_aging_stops, ymd.year); } @@ -688,7 +688,7 @@ void StartupOneEngine(Engine *e, TimerGameCalendar::Date aging_date, uint32_t se SavedRandomSeeds saved_seeds; SaveRandomSeeds(&saved_seeds); SetRandomSeed(_settings_game.game_creation.generation_seed ^ seed ^ - ei->base_intro ^ + static_cast(ei->base_intro) ^ e->type ^ e->GetGRFID()); uint32_t r = Random(); @@ -698,7 +698,7 @@ void StartupOneEngine(Engine *e, TimerGameCalendar::Date aging_date, uint32_t se * Note: TTDP uses fixed 1922 */ e->intro_date = ei->base_intro <= TimerGameCalendar::ConvertYMDToDate(_settings_game.game_creation.starting_year + 2, 0, 1) ? ei->base_intro : (TimerGameCalendar::Date)GB(r, 0, 9) + ei->base_intro; if (e->intro_date <= TimerGameCalendar::date) { - e->age = (aging_date - e->intro_date) >> 5; + e->age = static_cast(aging_date - e->intro_date) >> 5; e->company_avail = MAX_UVALUE(CompanyMask); e->flags |= ENGINE_AVAILABLE; } @@ -710,8 +710,8 @@ void StartupOneEngine(Engine *e, TimerGameCalendar::Date aging_date, uint32_t se } SetRandomSeed(_settings_game.game_creation.generation_seed ^ seed ^ - (re->index << 16) ^ (re->info.base_intro << 12) ^ (re->info.decay_speed << 8) ^ - (re->info.lifelength << 4) ^ re->info.retire_early ^ + (re->index << 16) ^ (static_cast(re->info.base_intro) << 12) ^ (re->info.decay_speed << 8) ^ + (static_cast(re->info.lifelength) << 4) ^ re->info.retire_early ^ e->type ^ e->GetGRFID()); @@ -722,7 +722,7 @@ void StartupOneEngine(Engine *e, TimerGameCalendar::Date aging_date, uint32_t se r = Random(); e->reliability_final = GB(r, 16, 14) + 0x3FFF; e->duration_phase_1 = GB(r, 0, 5) + 7; - e->duration_phase_2 = GB(r, 5, 4) + ei->base_life * 12 - 96; + e->duration_phase_2 = GB(r, 5, 4) + static_cast(ei->base_life) * 12 - 96; e->duration_phase_3 = GB(r, 9, 7) + 120; RestoreRandomSeeds(saved_seeds); diff --git a/src/genworld_gui.cpp b/src/genworld_gui.cpp index b24811fe05..669e597f78 100644 --- a/src/genworld_gui.cpp +++ b/src/genworld_gui.cpp @@ -968,7 +968,7 @@ struct GenerateLandscapeWindow : public Window { /* An empty string means revert to the default */ switch (this->widget_id) { case WID_GL_HEIGHTMAP_HEIGHT_TEXT: value = MAP_HEIGHT_LIMIT_AUTO_MINIMUM; break; - case WID_GL_START_DATE_TEXT: value = DEF_START_YEAR; break; + case WID_GL_START_DATE_TEXT: value = static_cast(DEF_START_YEAR); break; case WID_GL_SNOW_COVERAGE_TEXT: value = DEF_SNOW_COVERAGE; break; case WID_GL_DESERT_COVERAGE_TEXT: value = DEF_DESERT_COVERAGE; break; case WID_GL_TOWN_PULLDOWN: value = 1; break; diff --git a/src/landscape.cpp b/src/landscape.cpp index b43b09e599..a4a0a3a051 100644 --- a/src/landscape.cpp +++ b/src/landscape.cpp @@ -787,7 +787,7 @@ void RunTileLoop() _tile_type_procs[GetTileType(tile)]->tile_loop_proc(tile); /* Get the next tile in sequence using a Galois LFSR. */ - tile = (tile >> 1) ^ (-(int32_t)(tile & 1) & feedback); + tile = (static_cast(tile) >> 1) ^ (-(int32_t)(static_cast(tile) & 1) & feedback); } _cur_tileloop_tile = tile; @@ -935,11 +935,11 @@ static void GenerateTerrain(int type, uint flag) static void CreateDesertOrRainForest(uint desert_tropic_line) { - TileIndex update_freq = Map::Size() / 4; + uint update_freq = Map::Size() / 4; const TileIndexDiffC *data; for (TileIndex tile = 0; tile != Map::Size(); ++tile) { - if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); + if ((static_cast(tile) % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); if (!IsValidTile(tile)) continue; @@ -960,7 +960,7 @@ static void CreateDesertOrRainForest(uint desert_tropic_line) } for (TileIndex tile = 0; tile != Map::Size(); ++tile) { - if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); + if ((static_cast(tile) % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); if (!IsValidTile(tile)) continue; diff --git a/src/linkgraph/flowmapper.cpp b/src/linkgraph/flowmapper.cpp index 497aacb62b..b27719dc52 100644 --- a/src/linkgraph/flowmapper.cpp +++ b/src/linkgraph/flowmapper.cpp @@ -50,9 +50,9 @@ void FlowMapper::Run(LinkGraphJob &job) const /* Scale by time the graph has been running without being compressed. Add 1 to avoid * division by 0 if spawn date == last compression date. This matches * LinkGraph::Monthly(). */ - uint runtime = job.JoinDate() - job.Settings().recalc_time / SECONDS_PER_DAY - job.LastCompression() + 1; + auto runtime = job.JoinDate() - job.Settings().recalc_time / SECONDS_PER_DAY - job.LastCompression() + 1; for (auto &it : flows) { - it.second.ScaleToMonthly(runtime); + it.second.ScaleToMonthly(static_cast(runtime)); } } /* Clear paths. */ diff --git a/src/linkgraph/linkgraph.cpp b/src/linkgraph/linkgraph.cpp index f0e0597189..33d2adbad6 100644 --- a/src/linkgraph/linkgraph.cpp +++ b/src/linkgraph/linkgraph.cpp @@ -65,7 +65,7 @@ void LinkGraph::ShiftDates(TimerGameCalendar::Date interval) void LinkGraph::Compress() { - this->last_compression = (TimerGameCalendar::date + this->last_compression) / 2; + this->last_compression = static_cast(TimerGameCalendar::date + this->last_compression) / 2; for (NodeID node1 = 0; node1 < this->Size(); ++node1) { this->nodes[node1].supply /= 2; for (BaseEdge &edge : this->nodes[node1].edges) { diff --git a/src/linkgraph/linkgraph.h b/src/linkgraph/linkgraph.h index 59bbcb758e..6ca1a04b29 100644 --- a/src/linkgraph/linkgraph.h +++ b/src/linkgraph/linkgraph.h @@ -186,7 +186,7 @@ public: */ inline static uint Scale(uint val, TimerGameCalendar::Date target_age, TimerGameCalendar::Date orig_age) { - return val > 0 ? std::max(1U, val * target_age / orig_age) : 0; + return val > 0 ? std::max(1U, val * static_cast(target_age) / static_cast(orig_age)) : 0; } /** Bare constructor, only for save/load. */ @@ -249,7 +249,7 @@ public: */ inline uint Monthly(uint base) const { - return base * 30 / (TimerGameCalendar::date - this->last_compression + 1); + return base * 30 / static_cast(TimerGameCalendar::date - this->last_compression + 1); } NodeID AddNode(const Station *st); diff --git a/src/linkgraph/linkgraphschedule.cpp b/src/linkgraph/linkgraphschedule.cpp index ffdd54e7f3..4a2af43d02 100644 --- a/src/linkgraph/linkgraphschedule.cpp +++ b/src/linkgraph/linkgraphschedule.cpp @@ -178,7 +178,7 @@ void StateGameLoop_LinkGraphPauseControl() } } else if (_pause_mode == PM_UNPAUSED && TimerGameCalendar::date_fract == LinkGraphSchedule::SPAWN_JOIN_TICK - 2 && - TimerGameCalendar::date % (_settings_game.linkgraph.recalc_interval / SECONDS_PER_DAY) == (_settings_game.linkgraph.recalc_interval / SECONDS_PER_DAY) / 2 && + static_cast(TimerGameCalendar::date) % (_settings_game.linkgraph.recalc_interval / SECONDS_PER_DAY) == (_settings_game.linkgraph.recalc_interval / SECONDS_PER_DAY) / 2 && LinkGraphSchedule::instance.IsJoinWithUnfinishedJobDue()) { /* Perform check two TimerGameCalendar::date_fract ticks before we would join, to make * sure it also works in multiplayer. */ @@ -205,7 +205,7 @@ void AfterLoad_LinkGraphPauseControl() void OnTick_LinkGraph() { if (TimerGameCalendar::date_fract != LinkGraphSchedule::SPAWN_JOIN_TICK) return; - TimerGameCalendar::Date offset = TimerGameCalendar::date % (_settings_game.linkgraph.recalc_interval / SECONDS_PER_DAY); + TimerGameCalendar::Date offset = static_cast(TimerGameCalendar::date) % (_settings_game.linkgraph.recalc_interval / SECONDS_PER_DAY); if (offset == 0) { LinkGraphSchedule::instance.SpawnNext(); } else if (offset == (_settings_game.linkgraph.recalc_interval / SECONDS_PER_DAY) / 2) { diff --git a/src/misc/endian_buffer.hpp b/src/misc/endian_buffer.hpp index c0deea38d6..8422ebb4d3 100644 --- a/src/misc/endian_buffer.hpp +++ b/src/misc/endian_buffer.hpp @@ -53,7 +53,7 @@ public: if constexpr (std::is_enum_v) { this->Write(static_cast>(data)); } else if constexpr (std::is_base_of_v) { - this->Write(static_cast(data)); + this->Write(static_cast(data)); } else { this->Write(data); } @@ -146,7 +146,7 @@ public: if constexpr (std::is_enum_v) { data = static_cast(this->Read>()); } else if constexpr (std::is_base_of_v) { - data = this->Read(); + data = this->Read(); } else { data = this->Read(); } diff --git a/src/network/core/game_info.cpp b/src/network/core/game_info.cpp index bfbfc25716..fd95fe1dfb 100644 --- a/src/network/core/game_info.cpp +++ b/src/network/core/game_info.cpp @@ -227,8 +227,8 @@ void SerializeNetworkGameInfo(Packet *p, const NetworkServerGameInfo *info, bool } /* NETWORK_GAME_INFO_VERSION = 3 */ - p->Send_uint32(info->game_date); - p->Send_uint32(info->start_date); + p->Send_uint32(static_cast(info->game_date)); + p->Send_uint32(static_cast(info->start_date)); /* NETWORK_GAME_INFO_VERSION = 2 */ p->Send_uint8 (info->companies_max); @@ -323,8 +323,8 @@ void DeserializeNetworkGameInfo(Packet *p, NetworkGameInfo *info, const GameInfo } case 3: - info->game_date = Clamp(p->Recv_uint32(), 0, MAX_DATE); - info->start_date = Clamp(p->Recv_uint32(), 0, MAX_DATE); + info->game_date = Clamp(p->Recv_uint32(), 0, static_cast(MAX_DATE)); + info->start_date = Clamp(p->Recv_uint32(), 0, static_cast(MAX_DATE)); FALLTHROUGH; case 2: diff --git a/src/network/network_admin.cpp b/src/network/network_admin.cpp index f92ec0920a..2ad53d972e 100644 --- a/src/network/network_admin.cpp +++ b/src/network/network_admin.cpp @@ -178,7 +178,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendWelcome() p->Send_string(""); // Used to be map-name. p->Send_uint32(_settings_game.game_creation.generation_seed); p->Send_uint8 (_settings_game.game_creation.landscape); - p->Send_uint32(TimerGameCalendar::ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1)); + p->Send_uint32(static_cast(TimerGameCalendar::ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1))); p->Send_uint16(Map::SizeX()); p->Send_uint16(Map::SizeY()); @@ -208,7 +208,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendDate() { Packet *p = new Packet(ADMIN_PACKET_SERVER_DATE); - p->Send_uint32(TimerGameCalendar::date); + p->Send_uint32(static_cast(TimerGameCalendar::date)); this->SendPacket(p); return NETWORK_RECV_STATUS_OKAY; @@ -244,7 +244,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientInfo(const NetworkC p->Send_string(cs == nullptr ? "" : const_cast(cs->client_address).GetHostname()); p->Send_string(ci->client_name); p->Send_uint8 (0); // Used to be language - p->Send_uint32(ci->join_date); + p->Send_uint32(static_cast(ci->join_date)); p->Send_uint8 (ci->client_playas); this->SendPacket(p); @@ -329,7 +329,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyInfo(const Company p->Send_string(GetString(STR_PRESIDENT_NAME)); p->Send_uint8 (c->colour); p->Send_bool (NetworkCompanyIsPassworded(c->index)); - p->Send_uint32(c->inaugurated_year); + p->Send_uint32(static_cast(c->inaugurated_year)); p->Send_bool (c->is_ai); p->Send_uint8 (CeilDiv(c->months_of_bankruptcy, 3)); // send as quarters_of_bankruptcy diff --git a/src/newgrf.cpp b/src/newgrf.cpp index d14f20a904..a94b003763 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -6512,18 +6512,18 @@ bool GetGlobalVariable(byte param, uint32_t *value, const GRFFile *grffile) { switch (param) { case 0x00: // current date - *value = std::max(TimerGameCalendar::date - DAYS_TILL_ORIGINAL_BASE_YEAR, TimerGameCalendar::Date(0)); + *value = static_cast(std::max(TimerGameCalendar::date - DAYS_TILL_ORIGINAL_BASE_YEAR, TimerGameCalendar::Date(0))); return true; case 0x01: // current year - *value = Clamp(TimerGameCalendar::year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR; + *value = static_cast(Clamp(TimerGameCalendar::year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR); return true; case 0x02: { // detailed date information: month of year (bit 0-7), day of month (bit 8-12), leap year (bit 15), day of year (bit 16-24) TimerGameCalendar::YearMonthDay ymd; TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date, &ymd); TimerGameCalendar::Date start_of_year = TimerGameCalendar::ConvertYMDToDate(ymd.year, 0, 1); - *value = ymd.month | (ymd.day - 1) << 8 | (TimerGameCalendar::IsLeapYear(ymd.year) ? 1 << 15 : 0) | (TimerGameCalendar::date - start_of_year) << 16; + *value = ymd.month | (ymd.day - 1) << 8 | (TimerGameCalendar::IsLeapYear(ymd.year) ? 1 << 15 : 0) | static_cast(TimerGameCalendar::date - start_of_year) << 16; return true; } @@ -6629,11 +6629,11 @@ bool GetGlobalVariable(byte param, uint32_t *value, const GRFFile *grffile) return true; case 0x23: // long format date - *value = TimerGameCalendar::date; + *value = static_cast(TimerGameCalendar::date); return true; case 0x24: // long format year - *value = TimerGameCalendar::year; + *value = static_cast(TimerGameCalendar::year); return true; default: return false; @@ -7228,7 +7228,7 @@ static uint32_t GetPatchVariable(uint8_t param) { switch (param) { /* start year - 1920 */ - case 0x0B: return std::max(_settings_game.game_creation.starting_year, ORIGINAL_BASE_YEAR) - ORIGINAL_BASE_YEAR; + case 0x0B: return static_cast(std::max(_settings_game.game_creation.starting_year, ORIGINAL_BASE_YEAR) - ORIGINAL_BASE_YEAR); /* freight trains weight factor */ case 0x0E: return _settings_game.vehicle.freight_trains; diff --git a/src/newgrf_engine.cpp b/src/newgrf_engine.cpp index 6007860861..d0e9685df9 100644 --- a/src/newgrf_engine.cpp +++ b/src/newgrf_engine.cpp @@ -572,7 +572,7 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec } case 0x48: return v->GetEngine()->flags; // Vehicle Type Info - case 0x49: return v->build_year; + case 0x49: return static_cast(v->build_year); case 0x4A: switch (v->type) { @@ -597,7 +597,7 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec } case 0x4B: // Long date of last service - return v->date_of_last_service_newgrf; + return static_cast(v->date_of_last_service_newgrf); case 0x4C: // Current maximum speed in NewGRF units if (!v->IsPrimaryVehicle()) return 0; @@ -829,7 +829,7 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec case 0x41: return GB(ClampTo(v->age), 8, 8); case 0x42: return ClampTo(v->max_age); case 0x43: return GB(ClampTo(v->max_age), 8, 8); - case 0x44: return Clamp(v->build_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR; + case 0x44: return static_cast(Clamp(v->build_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR); case 0x45: return v->unitnumber; case 0x46: return v->GetEngine()->grf_prop.local_id; case 0x47: return GB(v->GetEngine()->grf_prop.local_id, 8, 8); @@ -972,11 +972,11 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec } } case 0x48: return Engine::Get(this->self_type)->flags; // Vehicle Type Info - case 0x49: return TimerGameCalendar::year; // 'Long' format build year - case 0x4B: return TimerGameCalendar::date; // Long date of last service + case 0x49: return static_cast(TimerGameCalendar::year); // 'Long' format build year + case 0x4B: return static_cast(TimerGameCalendar::date); // Long date of last service case 0x92: return ClampTo(TimerGameCalendar::date - DAYS_TILL_ORIGINAL_BASE_YEAR); // Date of last service case 0x93: return GB(ClampTo(TimerGameCalendar::date - DAYS_TILL_ORIGINAL_BASE_YEAR), 8, 8); - case 0xC4: return Clamp(TimerGameCalendar::year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR; // Build year + case 0xC4: return static_cast(Clamp(TimerGameCalendar::year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR); // Build year case 0xC6: return Engine::Get(this->self_type)->grf_prop.local_id; case 0xC7: return GB(Engine::Get(this->self_type)->grf_prop.local_id, 8, 8); case 0xDA: return INVALID_VEHICLE; // Next vehicle diff --git a/src/newgrf_house.cpp b/src/newgrf_house.cpp index 4520cfaff5..7d82cc83b7 100644 --- a/src/newgrf_house.cpp +++ b/src/newgrf_house.cpp @@ -296,7 +296,7 @@ static uint32_t GetDistanceFromNearbyHouse(uint8_t parameter, TileIndex tile, Ho case 0x40: return (IsTileType(this->tile, MP_HOUSE) ? GetHouseBuildingStage(this->tile) : 0) | TileHash2Bit(TileX(this->tile), TileY(this->tile)) << 2; /* Building age. */ - case 0x41: return IsTileType(this->tile, MP_HOUSE) ? GetHouseAge(this->tile) : 0; + case 0x41: return static_cast(IsTileType(this->tile, MP_HOUSE) ? GetHouseAge(this->tile) : 0); /* Town zone */ case 0x42: return GetTownRadiusGroup(this->town, this->tile); diff --git a/src/newgrf_industries.cpp b/src/newgrf_industries.cpp index b9612fb311..047102e620 100644 --- a/src/newgrf_industries.cpp +++ b/src/newgrf_industries.cpp @@ -163,7 +163,7 @@ static uint32_t GetCountAndDistanceOfClosestInstance(byte param_setID, byte layo switch (variable) { case 0x80: return this->tile; - case 0x81: return GB(this->tile, 8, 8); + case 0x81: return GB(static_cast(this->tile), 8, 8); /* Pointer to the town the industry is associated with */ case 0x82: return this->industry->town->index; @@ -247,7 +247,7 @@ static uint32_t GetCountAndDistanceOfClosestInstance(byte param_setID, byte layo return this->industry->founder | (is_ai ? 0x10000 : 0) | (colours << 24); } - case 0x46: return this->industry->construction_date; // Date when built - long format - (in days) + case 0x46: return static_cast(this->industry->construction_date); // Date when built - long format - (in days) /* Override flags from GS */ case 0x47: return this->industry->ctlflags; @@ -338,7 +338,7 @@ static uint32_t GetCountAndDistanceOfClosestInstance(byte param_setID, byte layo if (!IsValidCargoID(cargo)) return 0; auto it = this->industry->GetCargoAccepted(cargo); if (it == std::end(this->industry->accepted)) return 0; // invalid cargo - if (variable == 0x6E) return it->last_accepted; + if (variable == 0x6E) return static_cast(it->last_accepted); if (variable == 0x6F) return it->waiting; NOT_REACHED(); } @@ -348,7 +348,7 @@ static uint32_t GetCountAndDistanceOfClosestInstance(byte param_setID, byte layo /* Industry structure access*/ case 0x80: return this->industry->location.tile; - case 0x81: return GB(this->industry->location.tile, 8, 8); + case 0x81: return GB(static_cast(this->industry->location.tile), 8, 8); /* Pointer to the town the industry is associated with */ case 0x82: return this->industry->town->index; case 0x83: diff --git a/src/newgrf_object.cpp b/src/newgrf_object.cpp index ee65ac6359..6442041c60 100644 --- a/src/newgrf_object.cpp +++ b/src/newgrf_object.cpp @@ -277,7 +277,7 @@ static uint32_t GetCountAndDistanceOfClosestInstance(byte local_id, uint32_t grf break; /* Construction date */ - case 0x42: return TimerGameCalendar::date; + case 0x42: return static_cast(TimerGameCalendar::date); /* Object founder information */ case 0x44: return _current_company; @@ -315,7 +315,7 @@ static uint32_t GetCountAndDistanceOfClosestInstance(byte local_id, uint32_t grf case 0x41: return GetTileSlope(this->tile) << 8 | GetTerrainType(this->tile); /* Construction date */ - case 0x42: return this->obj->build_date; + case 0x42: return static_cast(this->obj->build_date); /* Animation counter */ case 0x43: return GetAnimationFrame(this->tile); diff --git a/src/newgrf_railtype.cpp b/src/newgrf_railtype.cpp index 9f074e4b4d..6b7bfd763c 100644 --- a/src/newgrf_railtype.cpp +++ b/src/newgrf_railtype.cpp @@ -30,7 +30,7 @@ case 0x40: return 0; case 0x41: return 0; case 0x42: return 0; - case 0x43: return TimerGameCalendar::date; + case 0x43: return static_cast(TimerGameCalendar::date); case 0x44: return HZB_TOWN_EDGE; } } @@ -40,8 +40,8 @@ case 0x41: return 0; case 0x42: return IsLevelCrossingTile(this->tile) && IsCrossingBarred(this->tile); case 0x43: - if (IsRailDepotTile(this->tile)) return Depot::GetByTile(this->tile)->build_date; - return TimerGameCalendar::date; + if (IsRailDepotTile(this->tile)) return static_cast(Depot::GetByTile(this->tile)->build_date); + return static_cast(TimerGameCalendar::date); case 0x44: { const Town *t = nullptr; if (IsRailDepotTile(this->tile)) { diff --git a/src/newgrf_roadtype.cpp b/src/newgrf_roadtype.cpp index 1be5b7585a..ab2897deaf 100644 --- a/src/newgrf_roadtype.cpp +++ b/src/newgrf_roadtype.cpp @@ -30,7 +30,7 @@ case 0x40: return 0; case 0x41: return 0; case 0x42: return 0; - case 0x43: return TimerGameCalendar::date; + case 0x43: return static_cast(TimerGameCalendar::date); case 0x44: return HZB_TOWN_EDGE; } } @@ -40,8 +40,8 @@ case 0x41: return 0; case 0x42: return IsLevelCrossingTile(this->tile) && IsCrossingBarred(this->tile); case 0x43: - if (IsRoadDepotTile(this->tile)) return Depot::GetByTile(this->tile)->build_date; - return TimerGameCalendar::date; + if (IsRoadDepotTile(this->tile)) return static_cast(Depot::GetByTile(this->tile)->build_date); + return static_cast(TimerGameCalendar::date); case 0x44: { const Town *t = nullptr; if (IsRoadDepotTile(this->tile)) { diff --git a/src/newgrf_town.cpp b/src/newgrf_town.cpp index f8fae8d2f0..ace57b5eeb 100644 --- a/src/newgrf_town.cpp +++ b/src/newgrf_town.cpp @@ -44,7 +44,7 @@ /* Town properties */ case 0x80: return this->t->xy; - case 0x81: return GB(this->t->xy, 8, 8); + case 0x81: return GB(static_cast(this->t->xy), 8, 8); case 0x82: return ClampTo(this->t->cache.population); case 0x83: return GB(ClampTo(this->t->cache.population), 8, 8); case 0x8A: return this->t->grow_counter / TOWN_GROWTH_TICKS; diff --git a/src/openttd.cpp b/src/openttd.cpp index bb54a7168a..2155d827cd 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -430,7 +430,7 @@ struct AfterNewGRFScan : NewGRFScanCallback { MusicDriver::GetInstance()->SetVolume(_settings_client.music.music_vol); SetEffectVolume(_settings_client.music.effect_vol); - if (startyear != INVALID_YEAR) IConsoleSetSetting("game_creation.starting_year", startyear); + if (startyear != INVALID_YEAR) IConsoleSetSetting("game_creation.starting_year", static_cast(startyear)); if (generation_seed != GENERATE_NEW_SEED) _settings_newgame.game_creation.generation_seed = generation_seed; if (!dedicated_host.empty()) { @@ -1389,7 +1389,7 @@ void StateGameLoop() CallWindowGameTickEvent(); NewsLoop(); } else { - if (_debug_desync_level > 2 && TimerGameCalendar::date_fract == 0 && (TimerGameCalendar::date & 0x1F) == 0) { + if (_debug_desync_level > 2 && TimerGameCalendar::date_fract == 0 && (static_cast(TimerGameCalendar::date) & 0x1F) == 0) { /* Save the desync savegame if needed. */ std::string name = fmt::format("dmp_cmds_{:08x}_{:08x}.sav", _settings_game.game_creation.generation_seed, TimerGameCalendar::date); SaveOrLoad(name, SLO_SAVE, DFT_GAME_FILE, AUTOSAVE_DIR, false); diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index 8c6f0ae892..b6bf5c5bc0 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -1922,6 +1922,12 @@ static bool OrderConditionCompare(OrderConditionComparator occ, int variable, in } } +template ::value, int> = 0> +static bool OrderConditionCompare(OrderConditionComparator occ, T variable, int value) +{ + return OrderConditionCompare(occ, static_cast(variable), value); +} + /** * Process a conditional order and determine the next order. * @param order the order the vehicle currently has diff --git a/src/pathfinder/yapf/yapf_node.hpp b/src/pathfinder/yapf/yapf_node.hpp index ce4ba3b289..9d079ae918 100644 --- a/src/pathfinder/yapf/yapf_node.hpp +++ b/src/pathfinder/yapf/yapf_node.hpp @@ -25,7 +25,7 @@ struct CYapfNodeKeyExitDir { inline int CalcHash() const { - return m_exitdir | (m_tile << 2); + return m_exitdir | (static_cast(m_tile) << 2); } inline bool operator==(const CYapfNodeKeyExitDir &other) const @@ -45,7 +45,7 @@ struct CYapfNodeKeyTrackDir : public CYapfNodeKeyExitDir { inline int CalcHash() const { - return m_td | (m_tile << 4); + return m_td | (static_cast(m_tile) << 4); } inline bool operator==(const CYapfNodeKeyTrackDir &other) const diff --git a/src/rail.cpp b/src/rail.cpp index 8f05c09785..d8991f0a4b 100644 --- a/src/rail.cpp +++ b/src/rail.cpp @@ -225,7 +225,7 @@ RailTypes AddDateIntroducedRailTypes(RailTypes current, TimerGameCalendar::Date if (rti->label == 0) continue; /* Not date introduced. */ - if (!IsInsideMM(rti->introduction_date, 0, MAX_DATE)) continue; + if (!IsInsideMM(rti->introduction_date, 0, static_cast(MAX_DATE))) continue; /* Not yet introduced at this date. */ if (rti->introduction_date > date) continue; diff --git a/src/road.cpp b/src/road.cpp index 1d3ec4d43d..de16bdf947 100644 --- a/src/road.cpp +++ b/src/road.cpp @@ -115,7 +115,7 @@ bool HasRoadTypeAvail(const CompanyID company, RoadType roadtype) if (rti->label == 0) return false; /* Not yet introduced at this date. */ - if (IsInsideMM(rti->introduction_date, 0, MAX_DATE) && rti->introduction_date > TimerGameCalendar::date) return false; + if (IsInsideMM(rti->introduction_date, 0, static_cast(MAX_DATE)) && rti->introduction_date > TimerGameCalendar::date) return false; /* * Do not allow building hidden road types, except when a town may build it. @@ -173,7 +173,7 @@ RoadTypes AddDateIntroducedRoadTypes(RoadTypes current, TimerGameCalendar::Date if (rti->label == 0) continue; /* Not date introduced. */ - if (!IsInsideMM(rti->introduction_date, 0, MAX_DATE)) continue; + if (!IsInsideMM(rti->introduction_date, 0, static_cast(MAX_DATE))) continue; /* Not yet introduced at this date. */ if (rti->introduction_date > date) continue; diff --git a/src/saveload/map_sl.cpp b/src/saveload/map_sl.cpp index 528bd359cb..ed33a7e624 100644 --- a/src/saveload/map_sl.cpp +++ b/src/saveload/map_sl.cpp @@ -169,7 +169,7 @@ struct MAP2ChunkHandler : ChunkHandler { std::array buf; TileIndex size = Map::Size(); - SlSetLength(size * sizeof(uint16_t)); + SlSetLength(static_cast(size) * sizeof(uint16_t)); for (TileIndex i = 0; i != size;) { for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = Tile(i++).m2(); SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16); @@ -344,7 +344,7 @@ struct MAP8ChunkHandler : ChunkHandler { std::array buf; TileIndex size = Map::Size(); - SlSetLength(size * sizeof(uint16_t)); + SlSetLength(static_cast(size) * sizeof(uint16_t)); for (TileIndex i = 0; i != size;) { for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = Tile(i++).m8(); SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16); diff --git a/src/saveload/oldloader.h b/src/saveload/oldloader.h index d4a2d3d260..09f143db16 100644 --- a/src/saveload/oldloader.h +++ b/src/saveload/oldloader.h @@ -93,9 +93,6 @@ struct OldChunks { OldChunkProc *proc; ///< Pointer to function that is called with OC_CHUNK }; -/* If it fails, check lines above.. */ -static_assert(sizeof(TileIndex) == 4); - extern uint _bump_assert_value; byte ReadByte(LoadgameState *ls); bool LoadChunk(LoadgameState *ls, void *base, const OldChunks *chunks); diff --git a/src/saveload/oldloader_sl.cpp b/src/saveload/oldloader_sl.cpp index db847cded7..d1349c99a6 100644 --- a/src/saveload/oldloader_sl.cpp +++ b/src/saveload/oldloader_sl.cpp @@ -57,8 +57,8 @@ static void FixTTDMapArray() /* _old_map3 is moved to _m::m3 and _m::m4 */ for (TileIndex t = 0; t < OLD_MAP_SIZE; t++) { Tile tile(t); - tile.m3() = _old_map3[t * 2]; - tile.m4() = _old_map3[t * 2 + 1]; + tile.m3() = _old_map3[static_cast(t) * 2]; + tile.m4() = _old_map3[static_cast(t) * 2 + 1]; } for (TileIndex t = 0; t < OLD_MAP_SIZE; t++) { @@ -416,7 +416,7 @@ static bool FixTTOEngines() if (TimerGameCalendar::date >= e->intro_date && HasBit(e->info.climates, 0)) { e->flags |= ENGINE_AVAILABLE; e->company_avail = MAX_UVALUE(CompanyMask); - e->age = TimerGameCalendar::date > e->intro_date ? (TimerGameCalendar::date - e->intro_date) / 30 : 0; + e->age = TimerGameCalendar::date > e->intro_date ? static_cast(TimerGameCalendar::date - e->intro_date) / 30 : 0; } } else { /* Using data from TTO savegame */ diff --git a/src/script/api/script_basestation.cpp b/src/script/api/script_basestation.cpp index 1863ea8554..caa5cf8034 100644 --- a/src/script/api/script_basestation.cpp +++ b/src/script/api/script_basestation.cpp @@ -63,5 +63,5 @@ { if (!IsValidBaseStation(station_id)) return ScriptDate::DATE_INVALID; - return (ScriptDate::Date)::BaseStation::Get(station_id)->build_date; + return (ScriptDate::Date)(int32_t)::BaseStation::Get(station_id)->build_date; } diff --git a/src/script/api/script_client.cpp b/src/script/api/script_client.cpp index 87f90d65c8..5445698913 100644 --- a/src/script/api/script_client.cpp +++ b/src/script/api/script_client.cpp @@ -50,5 +50,5 @@ static NetworkClientInfo *FindClientInfo(ScriptClient::ClientID client) { NetworkClientInfo *ci = FindClientInfo(client); if (ci == nullptr) return ScriptDate::DATE_INVALID; - return (ScriptDate::Date)ci->join_date; + return (ScriptDate::Date)(int32_t)ci->join_date; } diff --git a/src/script/api/script_date.cpp b/src/script/api/script_date.cpp index 56ad8b8827..1fbf80999e 100644 --- a/src/script/api/script_date.cpp +++ b/src/script/api/script_date.cpp @@ -22,7 +22,7 @@ /* static */ ScriptDate::Date ScriptDate::GetCurrentDate() { - return (ScriptDate::Date)TimerGameCalendar::date; + return (ScriptDate::Date)(int32_t)TimerGameCalendar::date; } /* static */ SQInteger ScriptDate::GetYear(ScriptDate::Date date) @@ -31,7 +31,7 @@ ::TimerGameCalendar::YearMonthDay ymd; ::TimerGameCalendar::ConvertDateToYMD(date, &ymd); - return ymd.year; + return (int32_t)ymd.year; } /* static */ SQInteger ScriptDate::GetMonth(ScriptDate::Date date) @@ -58,7 +58,7 @@ if (day_of_month < 1 || day_of_month > 31) return DATE_INVALID; if (year < 0 || year > MAX_YEAR) return DATE_INVALID; - return (ScriptDate::Date)::TimerGameCalendar::ConvertYMDToDate(year, month - 1, day_of_month); + return (ScriptDate::Date)(int32_t)::TimerGameCalendar::ConvertYMDToDate(year, month - 1, day_of_month); } /* static */ SQInteger ScriptDate::GetSystemTime() diff --git a/src/script/api/script_date.hpp b/src/script/api/script_date.hpp index 4373706aa7..6fa2053cc4 100644 --- a/src/script/api/script_date.hpp +++ b/src/script/api/script_date.hpp @@ -31,7 +31,7 @@ public: * compose valid date values for a known year, month and day. */ enum Date { - DATE_INVALID = ::INVALID_DATE, ///< A value representing an invalid date. + DATE_INVALID = (int32_t)::INVALID_DATE, ///< A value representing an invalid date. }; /** diff --git a/src/script/api/script_engine.cpp b/src/script/api/script_engine.cpp index d833a91a33..9797b863c4 100644 --- a/src/script/api/script_engine.cpp +++ b/src/script/api/script_engine.cpp @@ -139,7 +139,7 @@ if (!IsValidEngine(engine_id)) return -1; if (GetVehicleType(engine_id) == ScriptVehicle::VT_RAIL && IsWagon(engine_id)) return -1; - return ::Engine::Get(engine_id)->GetLifeLengthInDays(); + return (int32_t)::Engine::Get(engine_id)->GetLifeLengthInDays(); } /* static */ Money ScriptEngine::GetRunningCost(EngineID engine_id) @@ -179,7 +179,7 @@ { if (!IsValidEngine(engine_id)) return ScriptDate::DATE_INVALID; - return (ScriptDate::Date)::Engine::Get(engine_id)->intro_date; + return (ScriptDate::Date)(int32_t)::Engine::Get(engine_id)->intro_date; } /* static */ ScriptVehicle::VehicleType ScriptEngine::GetVehicleType(EngineID engine_id) diff --git a/src/script/api/script_industry.cpp b/src/script/api/script_industry.cpp index eea5714f24..b332accc02 100644 --- a/src/script/api/script_industry.cpp +++ b/src/script/api/script_industry.cpp @@ -53,7 +53,7 @@ { Industry *i = Industry::GetIfValid(industry_id); if (i == nullptr) return ScriptDate::DATE_INVALID; - return (ScriptDate::Date)i->construction_date; + return (ScriptDate::Date)(int32_t)i->construction_date; } /* static */ bool ScriptIndustry::SetText(IndustryID industry_id, Text *text) @@ -222,7 +222,7 @@ { Industry *i = Industry::GetIfValid(industry_id); if (i == nullptr) return 0; - return i->last_prod_year; + return (int32_t)i->last_prod_year; } /* static */ ScriptDate::Date ScriptIndustry::GetCargoLastAcceptedDate(IndustryID industry_id, CargoID cargo_type) @@ -232,11 +232,11 @@ if (!::IsValidCargoID(cargo_type)) { auto it = std::max_element(std::begin(i->accepted), std::end(i->accepted), [](const auto &a, const auto &b) { return a.last_accepted < b.last_accepted; }); - return (ScriptDate::Date)it->last_accepted; + return (ScriptDate::Date)(int32_t)it->last_accepted; } else { auto it = i->GetCargoAccepted(cargo_type); if (it == std::end(i->accepted)) return ScriptDate::DATE_INVALID; - return (ScriptDate::Date)it->last_accepted; + return (ScriptDate::Date)(int32_t)it->last_accepted; } } diff --git a/src/script/api/script_story_page.cpp b/src/script/api/script_story_page.cpp index bd83125c25..4a049f540c 100644 --- a/src/script/api/script_story_page.cpp +++ b/src/script/api/script_story_page.cpp @@ -182,7 +182,7 @@ static inline bool StoryPageElementTypeRequiresText(StoryPageElementType type) EnforcePrecondition(ScriptDate::DATE_INVALID, IsValidStoryPage(story_page_id)); EnforceDeityMode(ScriptDate::DATE_INVALID); - return (ScriptDate::Date)StoryPage::Get(story_page_id)->date; + return (ScriptDate::Date)(int32_t)StoryPage::Get(story_page_id)->date; } /* static */ bool ScriptStoryPage::SetDate(StoryPageID story_page_id, ScriptDate::Date date) diff --git a/src/script/api/script_vehicle.cpp b/src/script/api/script_vehicle.cpp index 7db46acc5d..76f4f282b0 100644 --- a/src/script/api/script_vehicle.cpp +++ b/src/script/api/script_vehicle.cpp @@ -311,7 +311,7 @@ { if (!IsValidVehicle(vehicle_id)) return -1; - return ::Vehicle::Get(vehicle_id)->age; + return (int32_t)::Vehicle::Get(vehicle_id)->age; } /* static */ SQInteger ScriptVehicle::GetWagonAge(VehicleID vehicle_id, SQInteger wagon) @@ -323,21 +323,21 @@ if (v->type == VEH_TRAIN) { while (wagon-- > 0) v = ::Train::From(v)->GetNextUnit(); } - return v->age; + return (int32_t)v->age; } /* static */ SQInteger ScriptVehicle::GetMaxAge(VehicleID vehicle_id) { if (!IsPrimaryVehicle(vehicle_id)) return -1; - return ::Vehicle::Get(vehicle_id)->max_age; + return (int32_t)::Vehicle::Get(vehicle_id)->max_age; } /* static */ SQInteger ScriptVehicle::GetAgeLeft(VehicleID vehicle_id) { if (!IsPrimaryVehicle(vehicle_id)) return -1; - return ::Vehicle::Get(vehicle_id)->max_age - ::Vehicle::Get(vehicle_id)->age; + return (int32_t)(::Vehicle::Get(vehicle_id)->max_age - ::Vehicle::Get(vehicle_id)->age); } /* static */ SQInteger ScriptVehicle::GetCurrentSpeed(VehicleID vehicle_id) diff --git a/src/settings_internal.h b/src/settings_internal.h index 9e07bacf13..5bee8ba84b 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -149,12 +149,46 @@ struct IntSettingDesc : SettingDesc { */ typedef void PostChangeCallback(int32_t value); - IntSettingDesc(const SaveLoad &save, SettingFlag flags, bool startup, int32_t def, - int32_t min, uint32_t max, int32_t interval, StringID str, StringID str_help, StringID str_val, + template < + typename Tdef, + typename Tmin, + typename Tmax, + typename Tinterval, + std::enable_if_t, std::is_base_of>, int> = 0, + std::enable_if_t, std::is_base_of>, int> = 0, + std::enable_if_t, std::is_base_of>, int> = 0, + std::enable_if_t, std::is_base_of>, int> = 0 + > + IntSettingDesc(const SaveLoad &save, SettingFlag flags, bool startup, Tdef def, + Tmin min, Tmax max, Tinterval interval, StringID str, StringID str_help, StringID str_val, SettingCategory cat, PreChangeCheck pre_check, PostChangeCallback post_callback) : - SettingDesc(save, flags, startup), def(def), min(min), max(max), interval(interval), + SettingDesc(save, flags, startup), str(str), str_help(str_help), str_val(str_val), cat(cat), pre_check(pre_check), - post_callback(post_callback) {} + post_callback(post_callback) { + if constexpr (std::is_base_of_v) { + this->def = static_cast(def); + } else { + this->def = def; + } + + if constexpr (std::is_base_of_v) { + this->min = static_cast(min); + } else { + this->min = min; + } + + if constexpr (std::is_base_of_v) { + this->max = static_cast(max); + } else { + this->max = max; + } + + if constexpr (std::is_base_of_v) { + this->interval = static_cast(interval); + } else { + this->interval = interval; + } + } int32_t def; ///< default value given when none is present int32_t min; ///< minimum values @@ -193,7 +227,7 @@ struct BoolSettingDesc : IntSettingDesc { BoolSettingDesc(const SaveLoad &save, SettingFlag flags, bool startup, bool def, StringID str, StringID str_help, StringID str_val, SettingCategory cat, PreChangeCheck pre_check, PostChangeCallback post_callback) : - IntSettingDesc(save, flags, startup, def, 0, 1, 0, str, str_help, str_val, cat, + IntSettingDesc(save, flags, startup, def ? 1 : 0, 0, 1, 0, str, str_help, str_val, cat, pre_check, post_callback) {} static std::optional ParseSingleValue(const char *str); diff --git a/src/stdafx.h b/src/stdafx.h index ae6805efe6..d727aa2891 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -126,6 +126,13 @@ # define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #endif +#if defined(_MSC_VER) + // See https://learn.microsoft.com/en-us/cpp/cpp/empty-bases?view=msvc-170 +# define EMPTY_BASES __declspec(empty_bases) +#else +# define EMPTY_BASES +#endif + /* Stuff for MSVC */ #if defined(_MSC_VER) # pragma once diff --git a/src/strings_func.h b/src/strings_func.h index 175e5556e3..03fb1becb2 100644 --- a/src/strings_func.h +++ b/src/strings_func.h @@ -15,6 +15,7 @@ #include "gfx_type.h" #include "core/bitmath_func.hpp" #include "core/span_type.hpp" +#include "core/strong_typedef_type.hpp" #include "vehicle_type.h" /** @@ -82,6 +83,18 @@ void SetDParam(size_t n, uint64_t v); void SetDParamMaxValue(size_t n, uint64_t max_value, uint min_count = 0, FontSize size = FS_NORMAL); void SetDParamMaxDigits(size_t n, uint count, FontSize size = FS_NORMAL); +template ::value, int> = 0> +void SetDParam(size_t n, T v) +{ + SetDParam(n, static_cast(v)); +} + +template ::value, int> = 0> +void SetDParamMaxValue(size_t n, T max_value, uint min_count = 0, FontSize size = FS_NORMAL) +{ + SetDParamMaxValue(n, static_cast(max_value), min_count, size); +} + void SetDParamStr(size_t n, const char *str); void SetDParamStr(size_t n, const std::string &str); void SetDParamStr(size_t n, std::string &&str); diff --git a/src/strings_internal.h b/src/strings_internal.h index 875c82f053..c85b179ca5 100644 --- a/src/strings_internal.h +++ b/src/strings_internal.h @@ -153,6 +153,12 @@ public: this->parameters[n].string_view = nullptr; } + template ::value, int> = 0> + void SetParam(size_t n, T v) + { + SetParam(n, static_cast(v)); + } + void SetParam(size_t n, const char *str) { assert(n < this->parameters.size()); diff --git a/src/table/roadtypes.h b/src/table/roadtypes.h index d11573d632..c59965d53c 100644 --- a/src/table/roadtypes.h +++ b/src/table/roadtypes.h @@ -82,7 +82,7 @@ static const RoadTypeInfo _original_roadtypes[] = { 0x01, /* introduction date */ - MIN_YEAR, + static_cast(MIN_YEAR), /* roadtypes required for this to be introduced */ ROADTYPES_NONE, diff --git a/src/tile_type.h b/src/tile_type.h index 87bbcc9f95..b7e80dedc9 100644 --- a/src/tile_type.h +++ b/src/tile_type.h @@ -81,36 +81,13 @@ enum TropicZone { /** * The index/ID of a Tile. + * + * It is compatible with int32 / int64 for easy math throughout the code. */ -struct TileIndex : StrongIntegralTypedef { - using StrongIntegralTypedef::StrongIntegralTypedef; +using TileIndex = StrongType::Typedef, StrongType::Compatible>; - debug_inline constexpr TileIndex() = default; - debug_inline constexpr TileIndex(const TileIndex &o) = default; - debug_inline constexpr TileIndex(TileIndex &&o) = default; - - debug_inline constexpr TileIndex(const uint32_t &value) : StrongIntegralTypedef(value) {} - - debug_inline constexpr TileIndex &operator =(const TileIndex &rhs) { this->value = rhs.value; return *this; } - debug_inline constexpr TileIndex &operator =(TileIndex &&rhs) { this->value = std::move(rhs.value); return *this; } - debug_inline constexpr TileIndex &operator =(const uint32_t &rhs) { this->value = rhs; return *this; } - - /** Implicit conversion to the base type for e.g. array indexing. */ - debug_inline constexpr operator uint32_t() const { return this->value; } - - /* Import operators from the base class into our overload set. */ - using StrongIntegralTypedef::operator ==; - using StrongIntegralTypedef::operator !=; - using StrongIntegralTypedef::operator +; - using StrongIntegralTypedef::operator -; - - /* Add comparison and add/sub for signed ints as e.g. 0 is signed and will - * match ambiguously when only unsigned overloads are present. */ - constexpr bool operator ==(int rhs) const { return this->value == (uint32_t)rhs; } - constexpr bool operator !=(int rhs) const { return this->value != (uint32_t)rhs; } - constexpr TileIndex operator +(int rhs) const { return { (uint32_t)(this->value + rhs) }; } - constexpr TileIndex operator -(int rhs) const { return { (uint32_t)(this->value - rhs) }; } -}; +/* Make sure the size is as expected. */ +static_assert(sizeof(TileIndex) == 4); /** * The very nice invalid tile marker diff --git a/src/timer/timer_game_calendar.cpp b/src/timer/timer_game_calendar.cpp index 8174f9a1b4..8cf18c91b2 100644 --- a/src/timer/timer_game_calendar.cpp +++ b/src/timer/timer_game_calendar.cpp @@ -75,8 +75,8 @@ static const uint16_t _accum_days_for_month[] = { */ /* There are 97 leap years in 400 years */ - TimerGameCalendar::Year yr = 400 * (date / (DAYS_IN_YEAR * 400 + 97)); - int rem = date % (DAYS_IN_YEAR * 400 + 97); + TimerGameCalendar::Year yr = 400 * (static_cast(date) / (DAYS_IN_YEAR * 400 + 97)); + int rem = static_cast(date) % (DAYS_IN_YEAR * 400 + 97); uint16_t x; if (rem >= DAYS_IN_YEAR * 100 + 25) { @@ -141,7 +141,7 @@ static const uint16_t _accum_days_for_month[] = { */ /* static */ bool TimerGameCalendar::IsLeapYear(TimerGameCalendar::Year yr) { - return yr % 4 == 0 && (yr % 100 != 0 || yr % 400 == 0); + return static_cast(yr) % 4 == 0 && (static_cast(yr) % 100 != 0 || static_cast(yr) % 400 == 0); } /** @@ -215,7 +215,7 @@ void TimerManager::Elapsed(TimerGameCalendar::TElapsed delta) timer->Elapsed(TimerGameCalendar::DAY); } - if ((TimerGameCalendar::date % 7) == 3) { + if ((static_cast(TimerGameCalendar::date) % 7) == 3) { for (auto timer : timers) { timer->Elapsed(TimerGameCalendar::WEEK); } diff --git a/src/timer/timer_game_calendar.h b/src/timer/timer_game_calendar.h index ddb8a62342..833f5893c1 100644 --- a/src/timer/timer_game_calendar.h +++ b/src/timer/timer_game_calendar.h @@ -11,6 +11,7 @@ #define TIMER_GAME_CALENDAR_H #include "stdafx.h" +#include "../core/strong_typedef_type.hpp" /** * Timer that is increased every 27ms, and counts towards ticks / days / months / years. @@ -76,12 +77,18 @@ public: struct TStorage { }; - using Date = int32_t; ///< The type to store our dates in - using DateFract = uint16_t; ///< The fraction of a date we're in, i.e. the number of ticks since the last date changeover + /** The type to store our dates in. */ + using Date = StrongType::Typedef; - using Year = int32_t; ///< Type for the year, note: 0 based, i.e. starts at the year 0. - using Month = uint8_t; ///< Type for the month, note: 0 based, i.e. 0 = January, 11 = December. - using Day = uint8_t; ///< Type for the day of the month, note: 1 based, first day of a month is 1. + /** The fraction of a date we're in, i.e. the number of ticks since the last date changeover. */ + using DateFract = uint16_t; + + /** Type for the year, note: 0 based, i.e. starts at the year 0. */ + using Year = StrongType::Typedef; + /** Type for the month, note: 0 based, i.e. 0 = January, 11 = December. */ + using Month = uint8_t; + /** Type for the day of the month, note: 1 based, first day of a month is 1. */ + using Day = uint8_t; /** * Data structure to convert between Date and triplet (year, month, and day). diff --git a/src/timetable_cmd.cpp b/src/timetable_cmd.cpp index 40c3f428fd..459f257dba 100644 --- a/src/timetable_cmd.cpp +++ b/src/timetable_cmd.cpp @@ -426,7 +426,7 @@ void UpdateVehicleTimetable(Vehicle *v, bool travelling) just_started = !HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED); if (v->timetable_start != 0) { - v->lateness_counter = (TimerGameCalendar::date - v->timetable_start) * DAY_TICKS + TimerGameCalendar::date_fract; + v->lateness_counter = static_cast(TimerGameCalendar::date - v->timetable_start) * DAY_TICKS + TimerGameCalendar::date_fract; v->timetable_start = 0; } diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp index 766da5b151..16bc9839b4 100644 --- a/src/toolbar_gui.cpp +++ b/src/toolbar_gui.cpp @@ -2510,7 +2510,7 @@ struct ScenarioEditorToolbarWindow : Window { value = atoi(str); } else { /* An empty string means revert to the default */ - value = DEF_START_YEAR; + value = static_cast(DEF_START_YEAR); } SetStartingYear(value); diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 50b38fea37..96fccf564e 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -595,7 +595,7 @@ static void TileLoop_Town(TileIndex tile) /* Binomial distribution per tick, by a series of coin flips */ /* Reduce generation rate to a 1/4, using tile bits to spread out distribution. * As tick counter is incremented by 256 between each call, we ignore the lower 8 bits. */ - if (GB(TimerGameTick::counter, 8, 2) == GB(tile, 0, 2)) { + if (GB(TimerGameTick::counter, 8, 2) == GB(static_cast(tile), 0, 2)) { /* Make a bitmask with up to 32 bits set, one for each potential pax */ int genmax = (hs->population + 7) / 8; uint32_t genmask = (genmax >= 32) ? 0xFFFFFFFF : ((1 << genmax) - 1); @@ -871,7 +871,7 @@ RoadType GetTownRoadType(const Town *t) if (!HasBit(rti->flags, ROTF_TOWN_BUILD)) continue; /* Not yet introduced at this date. */ - if (IsInsideMM(rti->introduction_date, 0, MAX_DATE) && rti->introduction_date > TimerGameCalendar::date) continue; + if (IsInsideMM(rti->introduction_date, 0, static_cast(MAX_DATE)) && rti->introduction_date > TimerGameCalendar::date) continue; if (best != nullptr) { if ((rti->max_speed == 0 ? assume_max_speed : rti->max_speed) < (best->max_speed == 0 ? assume_max_speed : best->max_speed)) continue; diff --git a/src/vehicle.cpp b/src/vehicle.cpp index a21e4ff052..ac42a1a38a 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -1400,7 +1400,7 @@ void AgeVehicle(Vehicle *v) str = STR_NEWS_VEHICLE_IS_GETTING_OLD; } else if (age == DateAtStartOfYear(0)) { str = STR_NEWS_VEHICLE_IS_GETTING_VERY_OLD; - } else if (age > DateAtStartOfYear(0) && (age % DAYS_IN_LEAP_YEAR) == 0) { + } else if (age > DateAtStartOfYear(0) && (static_cast(age) % DAYS_IN_LEAP_YEAR) == 0) { str = STR_NEWS_VEHICLE_IS_GETTING_VERY_OLD_AND; } else { return;