Files
@ r28822:57cd1bc354de
Branch filter:
Location: cpp/openttd-patchpack/source/src/roadveh.h
r28822:57cd1bc354de
11.8 KiB
text/x-c
Codechange: Add `GetVisibleRangeIterators()` to `Scrollbar`.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 | /*
* 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 <http://www.gnu.org/licenses/>.
*/
/** @file src/roadveh.h Road vehicle states */
#ifndef ROADVEH_H
#define ROADVEH_H
#include "ground_vehicle.hpp"
#include "engine_base.h"
#include "cargotype.h"
#include "track_func.h"
#include "road.h"
#include "road_map.h"
#include "newgrf_engine.h"
struct RoadVehicle;
/** Road vehicle states */
enum RoadVehicleStates {
/*
* Lower 4 bits are used for vehicle track direction. (Trackdirs)
* When in a road stop (bit 5 or bit 6 set) these bits give the
* track direction of the entry to the road stop.
* As the entry direction will always be a diagonal
* direction (X_NE, Y_SE, X_SW or Y_NW) only bits 0 and 3
* are needed to hold this direction. Bit 1 is then used to show
* that the vehicle is using the second road stop bay.
* Bit 2 is then used for drive-through stops to show the vehicle
* is stopping at this road stop.
*/
/* Numeric values */
RVSB_IN_DEPOT = 0xFE, ///< The vehicle is in a depot
RVSB_WORMHOLE = 0xFF, ///< The vehicle is in a tunnel and/or bridge
/* Bit numbers */
RVS_USING_SECOND_BAY = 1, ///< Only used while in a road stop
RVS_ENTERED_STOP = 2, ///< Only set when a vehicle has entered the stop
RVS_DRIVE_SIDE = 4, ///< Only used when retrieving move data
RVS_IN_ROAD_STOP = 5, ///< The vehicle is in a road stop
RVS_IN_DT_ROAD_STOP = 6, ///< The vehicle is in a drive-through road stop
/* Bit sets of the above specified bits */
RVSB_IN_ROAD_STOP = 1 << RVS_IN_ROAD_STOP, ///< The vehicle is in a road stop
RVSB_IN_ROAD_STOP_END = RVSB_IN_ROAD_STOP + TRACKDIR_END,
RVSB_IN_DT_ROAD_STOP = 1 << RVS_IN_DT_ROAD_STOP, ///< The vehicle is in a drive-through road stop
RVSB_IN_DT_ROAD_STOP_END = RVSB_IN_DT_ROAD_STOP + TRACKDIR_END,
RVSB_DRIVE_SIDE = 1 << RVS_DRIVE_SIDE, ///< The vehicle is at the opposite side of the road
RVSB_TRACKDIR_MASK = 0x0F, ///< The mask used to extract track dirs
RVSB_ROAD_STOP_TRACKDIR_MASK = 0x09, ///< Only bits 0 and 3 are used to encode the trackdir for road stops
};
/** State information about the Road Vehicle controller */
static const uint RDE_NEXT_TILE = 0x80; ///< We should enter the next tile
static const uint RDE_TURNED = 0x40; ///< We just finished turning
/* Start frames for when a vehicle enters a tile/changes its state.
* The start frame is different for vehicles that turned around or
* are leaving the depot as the do not start at the edge of the tile.
* For trams there are a few different start frames as there are two
* places where trams can turn. */
static const uint RVC_DEFAULT_START_FRAME = 0;
static const uint RVC_TURN_AROUND_START_FRAME = 1;
static const uint RVC_DEPOT_START_FRAME = 6;
static const uint RVC_START_FRAME_AFTER_LONG_TRAM = 21;
static const uint RVC_TURN_AROUND_START_FRAME_SHORT_TRAM = 16;
/* Stop frame for a vehicle in a drive-through stop */
static const uint RVC_DRIVE_THROUGH_STOP_FRAME = 11;
static const uint RVC_DEPOT_STOP_FRAME = 11;
/** The number of ticks a vehicle has for overtaking. */
static const byte RV_OVERTAKE_TIMEOUT = 35;
void RoadVehUpdateCache(RoadVehicle *v, bool same_length = false);
void GetRoadVehSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type);
struct RoadVehPathCache {
std::deque<Trackdir> td;
std::deque<TileIndex> tile;
inline bool empty() const { return this->td.empty(); }
inline size_t size() const
{
assert(this->td.size() == this->tile.size());
return this->td.size();
}
inline void clear()
{
this->td.clear();
this->tile.clear();
}
};
/**
* Buses, trucks and trams belong to this class.
*/
struct RoadVehicle final : public GroundVehicle<RoadVehicle, VEH_ROAD> {
RoadVehPathCache path; ///< Cached path.
byte state; ///< @see RoadVehicleStates
byte frame;
uint16_t blocked_ctr;
byte overtaking; ///< Set to #RVSB_DRIVE_SIDE when overtaking, otherwise 0.
byte overtaking_ctr; ///< The length of the current overtake attempt.
uint16_t crashed_ctr; ///< Animation counter when the vehicle has crashed. @see RoadVehIsCrashed
byte reverse_ctr;
RoadType roadtype; //!< Roadtype of this vehicle.
RoadTypes compatible_roadtypes; //!< Roadtypes this consist is powered on.
VehicleID disaster_vehicle = INVALID_VEHICLE; ///< NOSAVE: Disaster vehicle targetting this vehicle.
/** We don't want GCC to zero our struct! It already is zeroed and has an index! */
RoadVehicle() : GroundVehicleBase() {}
/** We want to 'destruct' the right class. */
virtual ~RoadVehicle() { this->PreDestructor(); }
friend struct GroundVehicle<RoadVehicle, VEH_ROAD>; // GroundVehicle needs to use the acceleration functions defined at RoadVehicle.
void MarkDirty() override;
void UpdateDeltaXY() override;
ExpensesType GetExpenseType(bool income) const override { return income ? EXPENSES_ROADVEH_REVENUE : EXPENSES_ROADVEH_RUN; }
bool IsPrimaryVehicle() const override { return this->IsFrontEngine(); }
void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const override;
int GetDisplaySpeed() const override { return this->gcache.last_speed / 2; }
int GetDisplayMaxSpeed() const override { return this->vcache.cached_max_speed / 2; }
Money GetRunningCost() const override;
int GetDisplayImageWidth(Point *offset = nullptr) const;
bool IsInDepot() const override { return this->state == RVSB_IN_DEPOT; }
bool Tick() override;
void OnNewCalendarDay() override;
void OnNewEconomyDay() override;
uint Crash(bool flooded = false) override;
Trackdir GetVehicleTrackdir() const override;
TileIndex GetOrderStationLocation(StationID station) override;
ClosestDepot FindClosestDepot() override;
bool IsBus() const;
int GetCurrentMaxSpeed() const override;
int UpdateSpeed();
void SetDestTile(TileIndex tile) override;
protected: // These functions should not be called outside acceleration code.
/**
* Allows to know the power value that this vehicle will use.
* @return Power value from the engine in HP, or zero if the vehicle is not powered.
*/
inline uint16_t GetPower() const
{
/* Power is not added for articulated parts */
if (!this->IsArticulatedPart()) {
/* Road vehicle power is in units of 10 HP. */
return 10 * GetVehicleProperty(this, PROP_ROADVEH_POWER, RoadVehInfo(this->engine_type)->power);
}
return 0;
}
/**
* Returns a value if this articulated part is powered.
* @return Zero, because road vehicles don't have powered parts.
*/
inline uint16_t GetPoweredPartPower(const RoadVehicle *) const
{
return 0;
}
/**
* Allows to know the weight value that this vehicle will use.
* @return Weight value from the engine in tonnes.
*/
inline uint16_t GetWeight() const
{
uint16_t weight = CargoSpec::Get(this->cargo_type)->WeightOfNUnits(this->cargo.StoredCount());
/* Vehicle weight is not added for articulated parts. */
if (!this->IsArticulatedPart()) {
/* Road vehicle weight is in units of 1/4 t. */
weight += GetVehicleProperty(this, PROP_ROADVEH_WEIGHT, RoadVehInfo(this->engine_type)->weight) / 4;
}
return weight;
}
/**
* Calculates the weight value that this vehicle will have when fully loaded with its current cargo.
* @return Weight value in tonnes.
*/
uint16_t GetMaxWeight() const override;
/**
* Allows to know the tractive effort value that this vehicle will use.
* @return Tractive effort value from the engine.
*/
inline byte GetTractiveEffort() const
{
/* The tractive effort coefficient is in units of 1/256. */
return GetVehicleProperty(this, PROP_ROADVEH_TRACTIVE_EFFORT, RoadVehInfo(this->engine_type)->tractive_effort);
}
/**
* Gets the area used for calculating air drag.
* @return Area of the engine in m^2.
*/
inline byte GetAirDragArea() const
{
return 6;
}
/**
* Gets the air drag coefficient of this vehicle.
* @return Air drag value from the engine.
*/
inline byte GetAirDrag() const
{
return RoadVehInfo(this->engine_type)->air_drag;
}
/**
* Checks the current acceleration status of this vehicle.
* @return Acceleration status.
*/
inline AccelStatus GetAccelerationStatus() const
{
return (this->vehstatus & VS_STOPPED) ? AS_BRAKE : AS_ACCEL;
}
/**
* Calculates the current speed of this vehicle.
* @return Current speed in km/h-ish.
*/
inline uint16_t GetCurrentSpeed() const
{
return this->cur_speed / 2;
}
/**
* Returns the rolling friction coefficient of this vehicle.
* @return Rolling friction coefficient in [1e-4].
*/
inline uint32_t GetRollingFriction() const
{
/* Trams have a slightly greater friction coefficient than trains.
* The rest of road vehicles have bigger values. */
uint32_t coeff = RoadTypeIsTram(this->roadtype) ? 40 : 75;
/* The friction coefficient increases with speed in a way that
* it doubles at 128 km/h, triples at 256 km/h and so on. */
return coeff * (128 + this->GetCurrentSpeed()) / 128;
}
/**
* Allows to know the acceleration type of a vehicle.
* @return Zero, road vehicles always use a normal acceleration method.
*/
inline int GetAccelerationType() const
{
return 0;
}
/**
* Returns the slope steepness used by this vehicle.
* @return Slope steepness used by the vehicle.
*/
inline uint32_t GetSlopeSteepness() const
{
return _settings_game.vehicle.roadveh_slope_steepness;
}
/**
* Gets the maximum speed allowed by the track for this vehicle.
* @return Since roads don't limit road vehicle speed, it returns always zero.
*/
inline uint16_t GetMaxTrackSpeed() const
{
return GetRoadTypeInfo(GetRoadType(this->tile, GetRoadTramType(this->roadtype)))->max_speed;
}
/**
* Checks if the vehicle is at a tile that can be sloped.
* @return True if the tile can be sloped.
*/
inline bool TileMayHaveSlopedTrack() const
{
TrackStatus ts = GetTileTrackStatus(this->tile, TRANSPORT_ROAD, GetRoadTramType(this->roadtype));
TrackBits trackbits = TrackStatusToTrackBits(ts);
return trackbits == TRACK_BIT_X || trackbits == TRACK_BIT_Y;
}
/**
* Road vehicles have to use GetSlopePixelZ() to compute their height
* if they are reversing because in that case, their direction
* is not parallel with the road. It is safe to return \c true
* even if it is not reversing.
* @return are we (possibly) reversing?
*/
inline bool HasToUseGetSlopePixelZ()
{
const RoadVehicle *rv = this->First();
/* Check if this vehicle is in the same direction as the road under.
* We already know it has either GVF_GOINGUP_BIT or GVF_GOINGDOWN_BIT set. */
if (rv->state <= RVSB_TRACKDIR_MASK && IsReversingRoadTrackdir((Trackdir)rv->state)) {
/* If the first vehicle is reversing, this vehicle may be reversing too
* (especially if this is the first, and maybe the only, vehicle).*/
return true;
}
while (rv != this) {
/* If any previous vehicle has different direction,
* we may be in the middle of reversing. */
if (this->direction != rv->direction) return true;
rv = rv->Next();
}
return false;
}
};
#endif /* ROADVEH_H */
|