/* * This file is part of OpenTTD. * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . */ /** @file road.h Road specific functions. */ #ifndef ROAD_H #define ROAD_H #include "road_type.h" #include "gfx_type.h" #include "core/bitmath_func.hpp" #include "strings_type.h" #include "date_type.h" #include "core/enum_type.hpp" #include "newgrf.h" #include "economy_func.h" #include #include enum RoadTramType : bool { RTT_ROAD, RTT_TRAM, }; enum RoadTramTypes : uint8_t { RTTB_ROAD = 1 << RTT_ROAD, RTTB_TRAM = 1 << RTT_TRAM, }; DECLARE_ENUM_AS_BIT_SET(RoadTramTypes) static const RoadTramType _roadtramtypes[] = { RTT_ROAD, RTT_TRAM }; /** Roadtype flag bit numbers. Starts with RO instead of R because R is used for rails */ enum RoadTypeFlag { ROTF_CATENARY = 0, ///< Bit number for adding catenary ROTF_NO_LEVEL_CROSSING, ///< Bit number for disabling level crossing ROTF_NO_HOUSES, ///< Bit number for setting this roadtype as not house friendly ROTF_HIDDEN, ///< Bit number for hidden from construction. ROTF_TOWN_BUILD, ///< Bit number for allowing towns to build this roadtype. }; /** Roadtype flags. Starts with RO instead of R because R is used for rails */ enum RoadTypeFlags : uint8_t { ROTFB_NONE = 0, ///< All flags cleared. ROTFB_CATENARY = 1 << ROTF_CATENARY, ///< Value for drawing a catenary. ROTFB_NO_LEVEL_CROSSING = 1 << ROTF_NO_LEVEL_CROSSING, ///< Value for disabling a level crossing. ROTFB_NO_HOUSES = 1 << ROTF_NO_HOUSES, ///< Value for for setting this roadtype as not house friendly. ROTFB_HIDDEN = 1 << ROTF_HIDDEN, ///< Value for hidden from construction. ROTFB_TOWN_BUILD = 1 << ROTF_TOWN_BUILD, ///< Value for allowing towns to build this roadtype. }; DECLARE_ENUM_AS_BIT_SET(RoadTypeFlags) /** Roadtype extra flags. */ enum RoadTypeExtraFlag { RXTF_NOT_AVAILABLE_AI_GS = 0, ///< Bit number for unavailable for AI/GS RXTF_NO_TOWN_MODIFICATION, ///< Bit number for no town modification RXTF_NO_TUNNELS, ///< Bit number for no tunnels RXTF_NO_TRAIN_COLLISION, ///< Bit number for no train collision }; /** Roadtype extra flags. */ enum RoadTypeExtraFlags : uint8_t { RXTFB_NONE = 0, ///< All flags cleared. RXTFB_NOT_AVAILABLE_AI_GS = 1 << RXTF_NOT_AVAILABLE_AI_GS, RXTFB_NO_TOWN_MODIFICATION = 1 << RXTF_NO_TOWN_MODIFICATION, RXTFB_NO_TUNNELS = 1 << RXTF_NO_TUNNELS, RXTFB_NO_TRAIN_COLLISION = 1 << RXTF_NO_TRAIN_COLLISION, }; DECLARE_ENUM_AS_BIT_SET(RoadTypeExtraFlags) enum RoadTypeCollisionMode : uint8_t { RTCM_NORMAL = 0, RTCM_NONE, RTCM_ELEVATED, RTCM_END, }; struct SpriteGroup; /** Sprite groups for a roadtype. */ enum RoadTypeSpriteGroup { ROTSG_CURSORS, ///< Optional: Cursor and toolbar icon images ROTSG_OVERLAY, ///< Optional: Images for overlaying track ROTSG_GROUND, ///< Required: Main group of ground images ROTSG_TUNNEL, ///< Optional: Ground images for tunnels ROTSG_CATENARY_FRONT, ///< Optional: Catenary front ROTSG_CATENARY_BACK, ///< Optional: Catenary back ROTSG_BRIDGE, ///< Required: Bridge surface images ROTSG_reserved2, ///< Placeholder, if we need specific level crossing sprites. ROTSG_DEPOT, ///< Optional: Depot images ROTSG_reserved3, ///< Placeholder, if we add road fences (for highways). ROTSG_ROADSTOP, ///< Required: Bay stop surface ROTSG_ONEWAY, ///< Optional: One-way indicator images ROTSG_END, }; /** List of road type labels. */ typedef std::vector RoadTypeLabelList; class RoadTypeInfo { public: /** * struct containing the sprites for the road GUI. @note only sprites referred to * directly in the code are listed */ struct { SpriteID build_x_road; ///< button for building single rail in X direction SpriteID build_y_road; ///< button for building single rail in Y direction SpriteID auto_road; ///< button for the autoroad construction SpriteID build_depot; ///< button for building depots SpriteID build_tunnel; ///< button for building a tunnel SpriteID convert_road; ///< button for converting road types } gui_sprites; struct { CursorID road_swne; ///< Cursor for building rail in X direction CursorID road_nwse; ///< Cursor for building rail in Y direction CursorID autoroad; ///< Cursor for autorail tool CursorID depot; ///< Cursor for building a depot CursorID tunnel; ///< Cursor for building a tunnel SpriteID convert_road; ///< Cursor for converting road types } cursor; ///< Cursors associated with the road type. struct { StringID name; ///< Name of this rail type. StringID toolbar_caption; ///< Caption in the construction toolbar GUI for this rail type. StringID menu_text; ///< Name of this rail type in the main toolbar dropdown. StringID build_caption; ///< Caption of the build vehicle GUI for this rail type. StringID replace_text; ///< Text used in the autoreplace GUI. StringID new_engine; ///< Name of an engine for this type of road in the engine preview GUI. StringID err_build_road; ///< Building a normal piece of road StringID err_remove_road; ///< Removing a normal piece of road StringID err_depot; ///< Building a depot StringID err_build_station[2]; ///< Building a bus or truck station StringID err_remove_station[2]; ///< Removing of a bus or truck station StringID err_convert_road; ///< Converting a road type StringID picker_title[2]; ///< Title for the station picker for bus or truck stations StringID picker_tooltip[2]; ///< Tooltip for the station picker for bus or truck stations } strings; ///< Strings associated with the rail type. /** bitmask to the OTHER roadtypes on which a vehicle of THIS roadtype generates power */ RoadTypes powered_roadtypes; /** * Bit mask of road type flags */ RoadTypeFlags flags; /** * Bit mask of road type extra flags */ RoadTypeExtraFlags extra_flags; /** * Collision mode */ RoadTypeCollisionMode collision_mode; /** * Cost multiplier for building this road type */ uint16_t cost_multiplier; /** * Cost multiplier for maintenance of this road type */ uint16_t maintenance_multiplier; /** * Maximum speed for vehicles travelling on this road type */ uint16_t max_speed; /** * Unique 32 bit road type identifier */ RoadTypeLabel label; /** * Road type labels this type provides in addition to the main label. */ RoadTypeLabelList alternate_labels; /** * Colour on mini-map */ uint8_t map_colour; /** * Introduction date. * When #INVALID_DATE or a vehicle using this roadtype gets introduced earlier, * the vehicle's introduction date will be used instead for this roadtype. * The introduction at this date is furthermore limited by the * #introduction_required_types. */ CalTime::Date introduction_date; /** * Bitmask of roadtypes that are required for this roadtype to be introduced * at a given #introduction_date. */ RoadTypes introduction_required_roadtypes; /** * Bitmask of which other roadtypes are introduced when this roadtype is introduced. */ RoadTypes introduces_roadtypes; /** * The sorting order of this roadtype for the toolbar dropdown. */ uint8_t sorting_order; /** * NewGRF providing the Action3 for the roadtype. nullptr if not available. */ const GRFFile *grffile[ROTSG_END]; /** * Sprite groups for resolving sprites */ const SpriteGroup *group[ROTSG_END]; inline bool UsesOverlay() const { return this->group[ROTSG_GROUND] != nullptr; } }; extern RoadTypes _roadtypes_type; inline bool RoadTypeIsRoad(RoadType roadtype) { return !HasBit(_roadtypes_type, roadtype); } inline bool RoadTypeIsTram(RoadType roadtype) { return HasBit(_roadtypes_type, roadtype); } inline RoadTramType GetRoadTramType(RoadType roadtype) { return RoadTypeIsTram(roadtype) ? RTT_TRAM : RTT_ROAD; } inline RoadTramType OtherRoadTramType(RoadTramType rtt) { return rtt == RTT_ROAD ? RTT_TRAM : RTT_ROAD; } /** * Returns a pointer to the Roadtype information for a given roadtype * @param roadtype the road type which the information is requested for * @return The pointer to the RoadTypeInfo */ inline const RoadTypeInfo *GetRoadTypeInfo(RoadType roadtype) { extern RoadTypeInfo _roadtypes[ROADTYPE_END]; assert(roadtype < ROADTYPE_END); return &_roadtypes[roadtype]; } /** * Checks if an engine of the given RoadType got power on a tile with a given * RoadType. This would normally just be an equality check, but for electrified * roads (which also support non-electric vehicles). * @return Whether the engine got power on this tile. * @param enginetype The RoadType of the engine we are considering. * @param tiletype The RoadType of the tile we are considering. */ inline bool HasPowerOnRoad(RoadType enginetype, RoadType tiletype) { return HasBit(GetRoadTypeInfo(enginetype)->powered_roadtypes, tiletype); } /** * Returns the cost of building the specified roadtype. * @param roadtype The roadtype being built. * @return The cost multiplier. */ inline Money RoadBuildCost(RoadType roadtype) { assert(roadtype < ROADTYPE_END); return (_price[PR_BUILD_ROAD] * GetRoadTypeInfo(roadtype)->cost_multiplier) >> 3; } /** * Returns the cost of clearing the specified roadtype. * @param roadtype The roadtype being removed. * @return The cost. */ inline Money RoadClearCost(RoadType roadtype) { assert(roadtype < ROADTYPE_END); /* Flat fee for removing road. */ if (RoadTypeIsRoad(roadtype)) return _price[PR_CLEAR_ROAD]; /* Clearing tram earns a little money, but also incurs the standard clear road cost, * so no profit can be made. */ return _price[PR_CLEAR_ROAD] - RoadBuildCost(roadtype) * 3 / 4; } /** * Calculates the cost of road conversion * @param from The roadtype we are converting from * @param to The roadtype we are converting to * @return Cost per RoadBit */ inline Money RoadConvertCost(RoadType from, RoadType to) { /* Don't apply convert costs when converting to the same roadtype (ex. building a roadstop over existing road) */ if (from == to) return (Money)0; /* Same cost as removing and then building. */ return RoadBuildCost(to) + RoadClearCost(from); } /** * Test if road disallows level crossings * @param roadtype The roadtype we are testing * @return True iff the roadtype disallows level crossings */ inline bool RoadNoLevelCrossing(RoadType roadtype) { assert(roadtype < ROADTYPE_END); return HasBit(GetRoadTypeInfo(roadtype)->flags, ROTF_NO_LEVEL_CROSSING); } /** * Test if road disallows tunnels * @param roadtype The roadtype we are testing * @return True iff the roadtype disallows tunnels */ inline bool RoadNoTunnels(RoadType roadtype) { assert(roadtype < ROADTYPE_END); return HasBit(GetRoadTypeInfo(roadtype)->extra_flags, RXTF_NO_TUNNELS); } RoadType GetRoadTypeByLabel(RoadTypeLabel label, bool allow_alternate_labels = true); void ResetRoadTypes(); void InitRoadTypes(); void InitRoadTypesCaches(); RoadType AllocateRoadType(RoadTypeLabel label, RoadTramType rtt); bool HasAnyRoadTypesAvail(CompanyID company, RoadTramType rtt); extern std::vector _sorted_roadtypes; extern RoadTypes _roadtypes_hidden_mask; extern std::array _collision_mode_roadtypes; extern RoadTypes _roadtypes_non_train_colliding; #endif /* ROAD_H */