train.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #ifndef TRAIN_H
00013 #define TRAIN_H
00014
00015 #include "newgrf_engine.h"
00016 #include "cargotype.h"
00017 #include "rail.h"
00018 #include "engine_base.h"
00019 #include "rail_map.h"
00020 #include "ground_vehicle.hpp"
00021
00022 struct Train;
00023
00024 enum VehicleRailFlags {
00025 VRF_REVERSING = 0,
00026
00027
00028 VRF_POWEREDWAGON = 3,
00029
00030
00031 VRF_REVERSE_DIRECTION = 4,
00032
00033
00034 VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL = 6,
00035
00036
00037 VRF_TOGGLE_REVERSE = 7,
00038
00039
00040 VRF_TRAIN_STUCK = 8,
00041
00042
00043 VRF_LEAVING_STATION = 9,
00044 };
00045
00047 enum TrainForceProceeding {
00048 TFP_NONE = 0,
00049 TFP_STUCK = 1,
00050 TFP_SIGNAL = 2,
00051 };
00052 typedef SimpleTinyEnumT<TrainForceProceeding, byte> TrainForceProceedingByte;
00053
00054 byte FreightWagonMult(CargoID cargo);
00055
00056 void CheckTrainsLengths();
00057
00058 void FreeTrainTrackReservation(const Train *v, TileIndex origin = INVALID_TILE, Trackdir orig_td = INVALID_TRACKDIR);
00059 bool TryPathReserve(Train *v, bool mark_as_stuck = false, bool first_tile_okay = false);
00060
00061 int GetTrainStopLocation(StationID station_id, TileIndex tile, const Train *v, int *station_ahead, int *station_length);
00062
00064 struct TrainCache {
00065
00066 const struct SpriteGroup *cached_override;
00067
00068 uint16 last_speed;
00069
00070
00071 bool cached_tilt;
00072
00073 byte user_def_data;
00074
00075
00076 int cached_max_curve_speed;
00077 };
00078
00082 struct Train : public GroundVehicle<Train, VEH_TRAIN> {
00083 TrainCache tcache;
00084
00085
00086 Train *other_multiheaded_part;
00087
00088 uint16 crash_anim_pos;
00089
00090 uint16 flags;
00091 TrackBitsByte track;
00092 TrainForceProceedingByte force_proceed;
00093 RailTypeByte railtype;
00094 RailTypes compatible_railtypes;
00095
00097 uint16 wait_counter;
00098
00100 Train() : GroundVehicle<Train, VEH_TRAIN>() {}
00102 virtual ~Train() { this->PreDestructor(); }
00103
00104 friend struct GroundVehicle<Train, VEH_TRAIN>;
00105
00106 const char *GetTypeString() const { return "train"; }
00107 void MarkDirty();
00108 void UpdateDeltaXY(Direction direction);
00109 ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_TRAIN_INC : EXPENSES_TRAIN_RUN; }
00110 void PlayLeaveStationSound() const;
00111 bool IsPrimaryVehicle() const { return this->IsFrontEngine(); }
00112 SpriteID GetImage(Direction direction) const;
00113 int GetDisplaySpeed() const { return this->tcache.last_speed; }
00114 int GetDisplayMaxSpeed() const { return this->vcache.cached_max_speed; }
00115 Money GetRunningCost() const;
00116 int GetDisplayImageWidth(Point *offset = NULL) const;
00117 bool IsInDepot() const;
00118 bool IsStoppedInDepot() const;
00119 bool Tick();
00120 void OnNewDay();
00121 uint Crash(bool flooded = false);
00122 Trackdir GetVehicleTrackdir() const;
00123 TileIndex GetOrderStationLocation(StationID station);
00124 bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse);
00125
00126 void ReserveTrackUnderConsist() const;
00127
00128 int GetCurveSpeedLimit() const;
00129
00130 void ConsistChanged(bool same_length);
00131
00132 void RailtypeChanged();
00133
00134 int UpdateSpeed();
00135
00136 void UpdateAcceleration();
00137
00138 int GetCurrentMaxSpeed() const;
00139
00146 FORCEINLINE Train *GetNextArticulatedPart() const
00147 {
00148 assert(this->HasArticulatedPart());
00149 return this->Next();
00150 }
00151
00156 FORCEINLINE Train *GetFirstEnginePart()
00157 {
00158 Train *v = this;
00159 while (v->IsArticulatedPart()) v = v->Previous();
00160 return v;
00161 }
00162
00167 FORCEINLINE const Train *GetFirstEnginePart() const
00168 {
00169 const Train *v = this;
00170 while (v->IsArticulatedPart()) v = v->Previous();
00171 return v;
00172 }
00173
00178 FORCEINLINE Train *GetLastEnginePart()
00179 {
00180 Train *v = this;
00181 while (v->HasArticulatedPart()) v = v->GetNextArticulatedPart();
00182 return v;
00183 }
00184
00189 FORCEINLINE Train *GetNextVehicle() const
00190 {
00191 const Train *v = this;
00192 while (v->HasArticulatedPart()) v = v->GetNextArticulatedPart();
00193
00194
00195 return v->Next();
00196 }
00197
00202 FORCEINLINE Train *GetPrevVehicle() const
00203 {
00204 Train *v = this->Previous();
00205 while (v != NULL && v->IsArticulatedPart()) v = v->Previous();
00206
00207 return v;
00208 }
00209
00214 FORCEINLINE Train *GetNextUnit() const
00215 {
00216 Train *v = this->GetNextVehicle();
00217 if (v != NULL && v->IsRearDualheaded()) v = v->GetNextVehicle();
00218
00219 return v;
00220 }
00221
00226 FORCEINLINE Train *GetPrevUnit()
00227 {
00228 Train *v = this->GetPrevVehicle();
00229 if (v != NULL && v->IsRearDualheaded()) v = v->GetPrevVehicle();
00230
00231 return v;
00232 }
00233
00234
00235 protected:
00236
00241 FORCEINLINE uint16 GetPower() const
00242 {
00243
00244 if (!this->IsArticulatedPart() && HasPowerOnRail(this->railtype, GetRailType(this->tile))) {
00245 uint16 power = GetVehicleProperty(this, PROP_TRAIN_POWER, RailVehInfo(this->engine_type)->power);
00246
00247 if (this->IsMultiheaded()) power /= 2;
00248 return power;
00249 }
00250
00251 return 0;
00252 }
00253
00258 FORCEINLINE uint16 GetPoweredPartPower(const Train *head) const
00259 {
00260
00261 if (HasBit(this->flags, VRF_POWEREDWAGON) && HasPowerOnRail(head->railtype, GetRailType(this->tile))) {
00262 return RailVehInfo(this->gcache.first_engine)->pow_wag_power;
00263 }
00264
00265 return 0;
00266 }
00267
00272 FORCEINLINE uint16 GetWeight() const
00273 {
00274 uint16 weight = (CargoSpec::Get(this->cargo_type)->weight * this->cargo.Count() * FreightWagonMult(this->cargo_type)) / 16;
00275
00276
00277 if (!this->IsArticulatedPart()) {
00278 weight += GetVehicleProperty(this, PROP_TRAIN_WEIGHT, RailVehInfo(this->engine_type)->weight);
00279 }
00280
00281
00282 if (HasBit(this->flags, VRF_POWEREDWAGON)) {
00283 weight += RailVehInfo(this->gcache.first_engine)->pow_wag_weight;
00284 }
00285
00286 return weight;
00287 }
00288
00293 FORCEINLINE byte GetTractiveEffort() const
00294 {
00295 return GetVehicleProperty(this, PROP_TRAIN_TRACTIVE_EFFORT, RailVehInfo(this->engine_type)->tractive_effort);
00296 }
00297
00302 FORCEINLINE byte GetAirDragArea() const
00303 {
00304
00305 return (this->track == TRACK_BIT_WORMHOLE && this->vehstatus & VS_HIDDEN) ? 28 : 14;
00306 }
00307
00312 FORCEINLINE byte GetAirDrag() const
00313 {
00314 return RailVehInfo(this->engine_type)->air_drag;
00315 }
00316
00321 FORCEINLINE AccelStatus GetAccelerationStatus() const
00322 {
00323 return (this->vehstatus & VS_STOPPED) || HasBit(this->flags, VRF_REVERSING) || HasBit(this->flags, VRF_TRAIN_STUCK) ? AS_BRAKE : AS_ACCEL;
00324 }
00325
00330 FORCEINLINE uint16 GetCurrentSpeed() const
00331 {
00332 return this->cur_speed;
00333 }
00334
00339 FORCEINLINE uint32 GetRollingFriction() const
00340 {
00341
00342
00343
00344 return 15 * (512 + this->GetCurrentSpeed()) / 512;
00345 }
00346
00351 FORCEINLINE int GetAccelerationType() const
00352 {
00353 return GetRailTypeInfo(this->railtype)->acceleration_type;
00354 }
00355
00360 FORCEINLINE uint32 GetSlopeSteepness() const
00361 {
00362 return _settings_game.vehicle.train_slope_steepness;
00363 }
00364
00369 FORCEINLINE uint16 GetMaxTrackSpeed() const
00370 {
00371 return GetRailTypeInfo(GetRailType(this->tile))->max_speed;
00372 }
00373
00378 FORCEINLINE bool TileMayHaveSlopedTrack() const
00379 {
00380
00381 return this->track == TRACK_BIT_X || this->track == TRACK_BIT_Y;
00382 }
00383 };
00384
00385 #define FOR_ALL_TRAINS(var) FOR_ALL_VEHICLES_OF_TYPE(Train, var)
00386
00387 #endif