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
00025 enum VehicleRailFlags {
00026 VRF_REVERSING = 0,
00027 VRF_POWEREDWAGON = 3,
00028 VRF_REVERSE_DIRECTION = 4,
00029
00030 VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL = 6,
00031 VRF_TOGGLE_REVERSE = 7,
00032 VRF_TRAIN_STUCK = 8,
00033 VRF_LEAVING_STATION = 9,
00034 };
00035
00037 enum TrainForceProceeding {
00038 TFP_NONE = 0,
00039 TFP_STUCK = 1,
00040 TFP_SIGNAL = 2,
00041 };
00042 typedef SimpleTinyEnumT<TrainForceProceeding, byte> TrainForceProceedingByte;
00043
00044 byte FreightWagonMult(CargoID cargo);
00045
00046 void CheckTrainsLengths();
00047
00048 void FreeTrainTrackReservation(const Train *v, TileIndex origin = INVALID_TILE, Trackdir orig_td = INVALID_TRACKDIR);
00049 bool TryPathReserve(Train *v, bool mark_as_stuck = false, bool first_tile_okay = false);
00050
00051 int GetTrainStopLocation(StationID station_id, TileIndex tile, const Train *v, int *station_ahead, int *station_length);
00052
00053 void GetTrainSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type);
00054
00056 struct TrainCache {
00057
00058 const struct SpriteGroup *cached_override;
00059
00060
00061 bool cached_tilt;
00062
00063 byte user_def_data;
00064
00065
00066 int cached_max_curve_speed;
00067 };
00068
00072 struct Train FINAL : public GroundVehicle<Train, VEH_TRAIN> {
00073 TrainCache tcache;
00074
00075
00076 Train *other_multiheaded_part;
00077
00078 uint16 crash_anim_pos;
00079
00080 uint16 flags;
00081 TrackBitsByte track;
00082 TrainForceProceedingByte force_proceed;
00083 RailTypeByte railtype;
00084 RailTypes compatible_railtypes;
00085
00087 uint16 wait_counter;
00088
00090 Train() : GroundVehicleBase() {}
00092 virtual ~Train() { this->PreDestructor(); }
00093
00094 friend struct GroundVehicle<Train, VEH_TRAIN>;
00095
00096 void MarkDirty();
00097 void UpdateDeltaXY(Direction direction);
00098 ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_TRAIN_INC : EXPENSES_TRAIN_RUN; }
00099 void PlayLeaveStationSound() const;
00100 bool IsPrimaryVehicle() const { return this->IsFrontEngine(); }
00101 SpriteID GetImage(Direction direction, EngineImageType image_type) const;
00102 int GetDisplaySpeed() const { return this->gcache.last_speed; }
00103 int GetDisplayMaxSpeed() const { return this->vcache.cached_max_speed; }
00104 Money GetRunningCost() const;
00105 int GetDisplayImageWidth(Point *offset = NULL) const;
00106 bool IsInDepot() const { return this->track == TRACK_BIT_DEPOT; }
00107 bool Tick();
00108 void OnNewDay();
00109 uint Crash(bool flooded = false);
00110 Trackdir GetVehicleTrackdir() const;
00111 TileIndex GetOrderStationLocation(StationID station);
00112 bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse);
00113
00114 void ReserveTrackUnderConsist() const;
00115
00116 int GetCurveSpeedLimit() const;
00117
00118 void ConsistChanged(bool same_length);
00119
00120 int UpdateSpeed();
00121
00122 void UpdateAcceleration();
00123
00124 int GetCurrentMaxSpeed() const;
00125
00130 inline Train *GetNextUnit() const
00131 {
00132 Train *v = this->GetNextVehicle();
00133 if (v != NULL && v->IsRearDualheaded()) v = v->GetNextVehicle();
00134
00135 return v;
00136 }
00137
00142 inline Train *GetPrevUnit()
00143 {
00144 Train *v = this->GetPrevVehicle();
00145 if (v != NULL && v->IsRearDualheaded()) v = v->GetPrevVehicle();
00146
00147 return v;
00148 }
00149
00154 int CalcNextVehicleOffset() const
00155 {
00156
00157
00158
00159
00160 return this->gcache.cached_veh_length / 2 + (this->Next() != NULL ? this->Next()->gcache.cached_veh_length + 1 : 0) / 2;
00161 }
00162
00163 protected:
00164
00169 inline uint16 GetPower() const
00170 {
00171
00172 if (!this->IsArticulatedPart() && HasPowerOnRail(this->railtype, GetRailType(this->tile))) {
00173 uint16 power = GetVehicleProperty(this, PROP_TRAIN_POWER, RailVehInfo(this->engine_type)->power);
00174
00175 if (this->IsMultiheaded()) power /= 2;
00176 return power;
00177 }
00178
00179 return 0;
00180 }
00181
00186 inline uint16 GetPoweredPartPower(const Train *head) const
00187 {
00188
00189 if (HasBit(this->flags, VRF_POWEREDWAGON) && HasPowerOnRail(head->railtype, GetRailType(this->tile))) {
00190 return RailVehInfo(this->gcache.first_engine)->pow_wag_power;
00191 }
00192
00193 return 0;
00194 }
00195
00200 inline uint16 GetWeight() const
00201 {
00202 uint16 weight = (CargoSpec::Get(this->cargo_type)->weight * this->cargo.StoredCount() * FreightWagonMult(this->cargo_type)) / 16;
00203
00204
00205 if (!this->IsArticulatedPart()) {
00206 weight += GetVehicleProperty(this, PROP_TRAIN_WEIGHT, RailVehInfo(this->engine_type)->weight);
00207 }
00208
00209
00210 if (HasBit(this->flags, VRF_POWEREDWAGON)) {
00211 weight += RailVehInfo(this->gcache.first_engine)->pow_wag_weight;
00212 }
00213
00214 return weight;
00215 }
00216
00221 inline byte GetTractiveEffort() const
00222 {
00223 return GetVehicleProperty(this, PROP_TRAIN_TRACTIVE_EFFORT, RailVehInfo(this->engine_type)->tractive_effort);
00224 }
00225
00230 inline byte GetAirDragArea() const
00231 {
00232
00233 return (this->track == TRACK_BIT_WORMHOLE && this->vehstatus & VS_HIDDEN) ? 28 : 14;
00234 }
00235
00240 inline byte GetAirDrag() const
00241 {
00242 return RailVehInfo(this->engine_type)->air_drag;
00243 }
00244
00249 inline AccelStatus GetAccelerationStatus() const
00250 {
00251 return (this->vehstatus & VS_STOPPED) || HasBit(this->flags, VRF_REVERSING) || HasBit(this->flags, VRF_TRAIN_STUCK) ? AS_BRAKE : AS_ACCEL;
00252 }
00253
00258 inline uint16 GetCurrentSpeed() const
00259 {
00260 return this->cur_speed;
00261 }
00262
00267 inline uint32 GetRollingFriction() const
00268 {
00269
00270
00271
00272 return 15 * (512 + this->GetCurrentSpeed()) / 512;
00273 }
00274
00279 inline int GetAccelerationType() const
00280 {
00281 return GetRailTypeInfo(this->railtype)->acceleration_type;
00282 }
00283
00288 inline uint32 GetSlopeSteepness() const
00289 {
00290 return _settings_game.vehicle.train_slope_steepness;
00291 }
00292
00297 inline uint16 GetMaxTrackSpeed() const
00298 {
00299 return GetRailTypeInfo(GetRailType(this->tile))->max_speed;
00300 }
00301
00306 inline bool TileMayHaveSlopedTrack() const
00307 {
00308
00309 return this->track == TRACK_BIT_X || this->track == TRACK_BIT_Y;
00310 }
00311
00317 inline bool HasToUseGetSlopePixelZ()
00318 {
00319 return false;
00320 }
00321 };
00322
00323 #define FOR_ALL_TRAINS(var) FOR_ALL_VEHICLES_OF_TYPE(Train, var)
00324
00325 #endif