Files
@ r12276:47d8173841ae
Branch filter:
Location: cpp/openttd-patchpack/source/src/train.h
r12276:47d8173841ae
11.8 KiB
text/x-c
(svn r16701) -Fix [FS#3001]: limit the screen's resolution to 65535x65535 so the dirty pixels stay within bounds of a 32 bits integer
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 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 | /* $Id$ */
/** @file train.h Base for the train class. */
#ifndef TRAIN_H
#define TRAIN_H
#include "stdafx.h"
#include "core/bitmath_func.hpp"
#include "vehicle_base.h"
struct Train;
enum VehicleRailFlags {
VRF_REVERSING = 0,
/* used to calculate if train is going up or down */
VRF_GOINGUP = 1,
VRF_GOINGDOWN = 2,
/* used to store if a wagon is powered or not */
VRF_POWEREDWAGON = 3,
/* used to reverse the visible direction of the vehicle */
VRF_REVERSE_DIRECTION = 4,
/* used to mark train as lost because PF can't find the route */
VRF_NO_PATH_TO_DESTINATION = 5,
/* used to mark that electric train engine is allowed to run on normal rail */
VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL = 6,
/* used for vehicle var 0xFE bit 8 (toggled each time the train is reversed, accurate for first vehicle only) */
VRF_TOGGLE_REVERSE = 7,
/* used to mark a train that can't get a path reservation */
VRF_TRAIN_STUCK = 8,
};
/** enum to handle train subtypes
* Do not access it directly unless you have to. Use the access functions below
* This is an enum to tell what bit to access as it is a bitmask
*/
enum TrainSubtype {
TS_FRONT = 0, ///< Leading engine of a train
TS_ARTICULATED_PART = 1, ///< Articulated part of an engine
TS_WAGON = 2, ///< Wagon
TS_ENGINE = 3, ///< Engine, that can be front engines, but might be placed behind another engine
TS_FREE_WAGON = 4, ///< First in a wagon chain (in depot)
TS_MULTIHEADED = 5, ///< Engine is a multiheaded
};
/** Check if a vehicle is front engine
* @param v vehicle to check
* @return Returns true if vehicle is a front engine
*/
static inline bool IsFrontEngine(const Vehicle *v)
{
assert(v->type == VEH_TRAIN);
return HasBit(v->subtype, TS_FRONT);
}
/** Set front engine state
* @param v vehicle to change
*/
static inline void SetFrontEngine(Vehicle *v)
{
assert(v->type == VEH_TRAIN);
SetBit(v->subtype, TS_FRONT);
}
/** Remove the front engine state
* @param v vehicle to change
*/
static inline void ClearFrontEngine(Vehicle *v)
{
assert(v->type == VEH_TRAIN);
ClrBit(v->subtype, TS_FRONT);
}
/** Check if a vehicle is an articulated part of an engine
* @param v vehicle to check
* @return Returns true if vehicle is an articulated part
*/
static inline bool IsArticulatedPart(const Vehicle *v)
{
assert(v->type == VEH_TRAIN);
return HasBit(v->subtype, TS_ARTICULATED_PART);
}
/** Set a vehicle to be an articulated part
* @param v vehicle to change
*/
static inline void SetArticulatedPart(Vehicle *v)
{
assert(v->type == VEH_TRAIN);
SetBit(v->subtype, TS_ARTICULATED_PART);
}
/** Clear a vehicle from being an articulated part
* @param v vehicle to change
*/
static inline void ClearArticulatedPart(Vehicle *v)
{
assert(v->type == VEH_TRAIN);
ClrBit(v->subtype, TS_ARTICULATED_PART);
}
/** Check if a vehicle is a wagon
* @param v vehicle to check
* @return Returns true if vehicle is a wagon
*/
static inline bool IsTrainWagon(const Vehicle *v)
{
assert(v->type == VEH_TRAIN);
return HasBit(v->subtype, TS_WAGON);
}
/** Set a vehicle to be a wagon
* @param v vehicle to change
*/
static inline void SetTrainWagon(Vehicle *v)
{
assert(v->type == VEH_TRAIN);
SetBit(v->subtype, TS_WAGON);
}
/** Clear wagon property
* @param v vehicle to change
*/
static inline void ClearTrainWagon(Vehicle *v)
{
assert(v->type == VEH_TRAIN);
ClrBit(v->subtype, TS_WAGON);
}
/** Check if a vehicle is an engine (can be first in a train)
* @param v vehicle to check
* @return Returns true if vehicle is an engine
*/
static inline bool IsTrainEngine(const Vehicle *v)
{
assert(v->type == VEH_TRAIN);
return HasBit(v->subtype, TS_ENGINE);
}
/** Set engine status
* @param v vehicle to change
*/
static inline void SetTrainEngine(Vehicle *v)
{
assert(v->type == VEH_TRAIN);
SetBit(v->subtype, TS_ENGINE);
}
/** Clear engine status
* @param v vehicle to change
*/
static inline void ClearTrainEngine(Vehicle *v)
{
assert(v->type == VEH_TRAIN);
ClrBit(v->subtype, TS_ENGINE);
}
/** Check if a vehicle is a free wagon (got no engine in front of it)
* @param v vehicle to check
* @return Returns true if vehicle is a free wagon
*/
static inline bool IsFreeWagon(const Vehicle *v)
{
assert(v->type == VEH_TRAIN);
return HasBit(v->subtype, TS_FREE_WAGON);
}
/** Set if a vehicle is a free wagon
* @param v vehicle to change
*/
static inline void SetFreeWagon(Vehicle *v)
{
assert(v->type == VEH_TRAIN);
SetBit(v->subtype, TS_FREE_WAGON);
}
/** Clear a vehicle from being a free wagon
* @param v vehicle to change
*/
static inline void ClearFreeWagon(Vehicle *v)
{
assert(v->type == VEH_TRAIN);
ClrBit(v->subtype, TS_FREE_WAGON);
}
/** Check if a vehicle is a multiheaded engine
* @param v vehicle to check
* @return Returns true if vehicle is a multiheaded engine
*/
static inline bool IsMultiheaded(const Vehicle *v)
{
assert(v->type == VEH_TRAIN);
return HasBit(v->subtype, TS_MULTIHEADED);
}
/** Set if a vehicle is a multiheaded engine
* @param v vehicle to change
*/
static inline void SetMultiheaded(Vehicle *v)
{
assert(v->type == VEH_TRAIN);
SetBit(v->subtype, TS_MULTIHEADED);
}
/** Clear multiheaded engine property
* @param v vehicle to change
*/
static inline void ClearMultiheaded(Vehicle *v)
{
assert(v->type == VEH_TRAIN);
ClrBit(v->subtype, TS_MULTIHEADED);
}
/** Check if an engine has an articulated part.
* @param v Vehicle.
* @return True if the engine has an articulated part.
*/
static inline bool EngineHasArticPart(const Vehicle *v)
{
assert(v->type == VEH_TRAIN);
return (v->Next() != NULL && IsArticulatedPart(v->Next()));
}
/** Tell if we are dealing with the rear end of a multiheaded engine.
* @param v Vehicle.
* @return True if the engine is the rear part of a dualheaded engine.
*/
static inline bool IsRearDualheaded(const Vehicle *v)
{
assert(v->type == VEH_TRAIN);
return (IsMultiheaded(v) && !IsTrainEngine(v));
}
void CcBuildLoco(bool success, TileIndex tile, uint32 p1, uint32 p2);
void CcBuildWagon(bool success, TileIndex tile, uint32 p1, uint32 p2);
byte FreightWagonMult(CargoID cargo);
int CheckTrainInDepot(const Train *v, bool needs_to_be_stopped);
int CheckTrainStoppedInDepot(const Train *v);
void UpdateTrainAcceleration(Train *v);
void CheckTrainsLengths();
void FreeTrainTrackReservation(const Train *v, TileIndex origin = INVALID_TILE, Trackdir orig_td = INVALID_TRACKDIR);
bool TryPathReserve(Train *v, bool mark_as_stuck = false, bool first_tile_okay = false);
int GetTrainStopLocation(StationID station_id, TileIndex tile, const Train *v, int *station_ahead, int *station_length);
void TrainConsistChanged(Train *v, bool same_length);
void TrainPowerChanged(Train *v);
int GetTrainCurveSpeedLimit(Train *v);
Money GetTrainRunningCost(const Train *v);
/** Variables that are cached to improve performance and such */
struct TrainCache {
/* Cached wagon override spritegroup */
const struct SpriteGroup *cached_override;
uint16 last_speed; // NOSAVE: only used in UI
/* cached values, recalculated on load and each time a vehicle is added to/removed from the consist. */
uint32 cached_power; ///< total power of the consist.
uint16 cached_total_length; ///< Length of the whole train, valid only for first engine.
uint8 cached_veh_length; ///< length of this vehicle in units of 1/8 of normal length, cached because this can be set by a callback
bool cached_tilt; ///< train can tilt; feature provides a bonus in curves
/* cached values, recalculated when the cargo on a train changes (in addition to the conditions above) */
uint32 cached_weight; ///< total weight of the consist.
uint32 cached_veh_weight; ///< weight of the vehicle.
uint32 cached_max_te; ///< max tractive effort of consist
/* cached max. speed / acceleration data */
uint16 cached_max_speed; ///< max speed of the consist. (minimum of the max speed of all vehicles in the consist)
int cached_max_curve_speed; ///< max consist speed limited by curves
/**
* Position/type of visual effect.
* bit 0 - 3 = position of effect relative to vehicle. (0 = front, 8 = centre, 15 = rear)
* bit 4 - 5 = type of effect. (0 = default for engine class, 1 = steam, 2 = diesel, 3 = electric)
* bit 6 = disable visual effect.
* bit 7 = disable powered wagons.
*/
byte cached_vis_effect;
byte user_def_data;
/* NOSAVE: for wagon override - id of the first engine in train
* 0xffff == not in train */
EngineID first_engine;
};
/**
* 'Train' is either a loco or a wagon.
*/
struct Train : public SpecializedVehicle<Train, VEH_TRAIN> {
TrainCache tcache;
/* Link between the two ends of a multiheaded engine */
Train *other_multiheaded_part;
uint16 crash_anim_pos;
uint16 flags;
TrackBitsByte track;
byte force_proceed;
RailTypeByte railtype;
RailTypes compatible_railtypes;
/** We don't want GCC to zero our struct! It already is zeroed and has an index! */
Train() : SpecializedVehicle<Train, VEH_TRAIN>() {}
/** We want to 'destruct' the right class. */
virtual ~Train() { this->PreDestructor(); }
const char *GetTypeString() const { return "train"; }
void MarkDirty();
void UpdateDeltaXY(Direction direction);
ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_TRAIN_INC : EXPENSES_TRAIN_RUN; }
void PlayLeaveStationSound() const;
bool IsPrimaryVehicle() const { return IsFrontEngine(this); }
SpriteID GetImage(Direction direction) const;
int GetDisplaySpeed() const { return this->tcache.last_speed; }
int GetDisplayMaxSpeed() const { return this->tcache.cached_max_speed; }
Money GetRunningCost() const;
bool IsInDepot() const { return CheckTrainInDepot(this, false) != -1; }
bool IsStoppedInDepot() const { return CheckTrainStoppedInDepot(this) >= 0; }
bool Tick();
void OnNewDay();
Trackdir GetVehicleTrackdir() const;
TileIndex GetOrderStationLocation(StationID station);
bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse);
};
#define FOR_ALL_TRAINS(var) FOR_ALL_VEHICLES_OF_TYPE(Train, var)
/**
* Get the next part of a multi-part engine.
* Will only work on a multi-part engine (EngineHasArticPart(v) == true),
* Result is undefined for normal engine.
*/
static inline Train *GetNextArticPart(const Train *v)
{
assert(EngineHasArticPart(v));
return v->Next();
}
/** Get the last part of a multi-part engine.
* @param v Vehicle.
* @return Last part of the engine.
*/
static inline Train *GetLastEnginePart(Train *v)
{
assert(v->type == VEH_TRAIN);
while (EngineHasArticPart(v)) v = GetNextArticPart(v);
return v;
}
/** Get the next real (non-articulated part) vehicle in the consist.
* @param v Vehicle.
* @return Next vehicle in the consist.
*/
static inline Train *GetNextVehicle(const Train *v)
{
assert(v->type == VEH_TRAIN);
while (EngineHasArticPart(v)) v = GetNextArticPart(v);
/* v now contains the last artic part in the engine */
return v->Next();
}
/** Get the previous real (non-articulated part) vehicle in the consist.
* @param w Vehicle.
* @return Previous vehicle in the consist.
*/
static inline Train *GetPrevVehicle(const Train *w)
{
assert(w->type == VEH_TRAIN);
Train *v = w->Previous();
while (v != NULL && IsArticulatedPart(v)) v = v->Previous();
return v;
}
/** Get the next real (non-articulated part and non rear part of dualheaded engine) vehicle in the consist.
* @param v Vehicle.
* @return Next vehicle in the consist.
*/
static inline Train *GetNextUnit(const Train *v)
{
assert(v->type == VEH_TRAIN);
Train *w = GetNextVehicle(v);
if (w != NULL && IsRearDualheaded(w)) w = GetNextVehicle(w);
return w;
}
/** Get the previous real (non-articulated part and non rear part of dualheaded engine) vehicle in the consist.
* @param v Vehicle.
* @return Previous vehicle in the consist.
*/
static inline Train *GetPrevUnit(const Train *v)
{
assert(v->type == VEH_TRAIN);
Train *w = GetPrevVehicle(v);
if (w != NULL && IsRearDualheaded(w)) w = GetPrevVehicle(w);
return w;
}
#endif /* TRAIN_H */
|