/*
* 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 {
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 flags. Starts with RO instead of R because R is used for rails */
enum RoadTypeFlags {
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. Does not override ROTF_HIDDEN.
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. Does not override ROTFB_HIDDEN.
};
DECLARE_ENUM_AS_BIT_SET(RoadTypeFlags)
/** Roadtype extra flags. */
enum RoadTypeExtraFlags {
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
RXTFB_NONE = 0, ///< All flags cleared.
};
DECLARE_ENUM_AS_BIT_SET(RoadTypeExtraFlags)
enum RoadTypeCollisionMode : uint8 {
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: Drive-in 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 cost_multiplier;
/**
* Cost multiplier for maintenance of this road type
*/
uint16 maintenance_multiplier;
/**
* Maximum speed for vehicles travelling on this road type
*/
uint16 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
*/
byte 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.
*/
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.
*/
byte 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;
static inline bool RoadTypeIsRoad(RoadType roadtype)
{
return !HasBit(_roadtypes_type, roadtype);
}
static inline bool RoadTypeIsTram(RoadType roadtype)
{
return HasBit(_roadtypes_type, roadtype);
}
static inline RoadTramType GetRoadTramType(RoadType roadtype)
{
return RoadTypeIsTram(roadtype) ? RTT_TRAM : RTT_ROAD;
}
static 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
*/
static 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.
*/
static 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.
*/
static 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.
*/
static 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
*/
static 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
*/
static 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
*/
static 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 */