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 VRF_BREAKDOWN_BRAKING = 10,
00036 VRF_BREAKDOWN_POWER = 11,
00037 VRF_BREAKDOWN_SPEED = 12,
00038 VRF_BREAKDOWN_STOPPED = 13,
00039
00040 VRF_IS_BROKEN = (1 << VRF_BREAKDOWN_POWER) | (1 << VRF_BREAKDOWN_SPEED) | (1 << VRF_BREAKDOWN_STOPPED),
00041 VRF_NEED_REPAIR = 14,
00042 VRF_TO_HEAVY = 15,
00043 };
00044
00046 enum TrainForceProceeding {
00047 TFP_NONE = 0,
00048 TFP_STUCK = 1,
00049 TFP_SIGNAL = 2,
00050 };
00051 typedef SimpleTinyEnumT<TrainForceProceeding, byte> TrainForceProceedingByte;
00052
00053 byte FreightWagonMult(CargoID cargo);
00054
00055 void CheckTrainsLengths();
00056
00057 void FreeTrainTrackReservation(const Train *v, TileIndex origin = INVALID_TILE, Trackdir orig_td = INVALID_TRACKDIR);
00058 bool TryPathReserve(Train *v, bool mark_as_stuck = false, bool first_tile_okay = false);
00059
00060 void DeleteVisibleTrain(Train *v);
00061
00062 int GetTrainStopLocation(StationID station_id, TileIndex tile, const Train *v, int *station_ahead, int *station_length);
00063
00064 void CheckBreakdownFlags(Train *v);
00065
00067 struct TrainCache {
00068
00069 const struct SpriteGroup *cached_override;
00070
00071
00072 bool cached_tilt;
00073 uint8 cached_num_engines;
00074
00075 byte user_def_data;
00076
00077
00078 int cached_max_curve_speed;
00079 };
00080
00084 struct Train : public GroundVehicle<Train, VEH_TRAIN> {
00085 TrainCache tcache;
00086
00087
00088 Train *other_multiheaded_part;
00089
00090 uint16 crash_anim_pos;
00091
00092 uint16 flags;
00093 TrackBitsByte track;
00094 TrainForceProceedingByte force_proceed;
00095 RailTypeByte railtype;
00096 RailTypes compatible_railtypes;
00097
00099 uint16 signal_speedlimit;
00100
00102 uint16 wait_counter;
00103
00105 Train() : GroundVehicleBase(), signal_speedlimit(UINT16_MAX) {}
00107 virtual ~Train() { this->PreDestructor(); }
00108
00109 friend struct GroundVehicle<Train, VEH_TRAIN>;
00110
00111 void MarkDirty();
00112 void UpdateDeltaXY(Direction direction);
00113 ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_TRAIN_INC : EXPENSES_TRAIN_RUN; }
00114 void PlayLeaveStationSound() const;
00115 bool IsPrimaryVehicle() const { return this->IsFrontEngine(); }
00116 SpriteID GetImage(Direction direction) const;
00117 int GetDisplaySpeed() const { return this->gcache.last_speed; }
00118 int GetDisplayMaxSpeed() const { return this->vcache.cached_max_speed; }
00119 Money GetRunningCost() const;
00120 int GetDisplayImageWidth(Point *offset = NULL) const;
00121 bool IsInDepot() const;
00122 bool IsStoppedInDepot() const;
00123 bool Tick();
00124 void OnNewDay();
00125 uint Crash(bool flooded = false);
00126 Trackdir GetVehicleTrackdir() const;
00127 TileIndex GetOrderStationLocation(StationID station);
00128 bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse);
00129
00130 void ReserveTrackUnderConsist() const;
00131
00132 int GetCurveSpeedLimit() const;
00133
00134 void ConsistChanged(bool same_length);
00135
00136 void RailtypeChanged();
00137
00138 int UpdateSpeed();
00139
00140 void UpdateAcceleration();
00141
00142 int GetCurrentMaxSpeed() const;
00143
00148 FORCEINLINE Train *GetNextUnit() const
00149 {
00150 Train *v = this->GetNextVehicle();
00151 if (v != NULL && v->IsRearDualheaded()) v = v->GetNextVehicle();
00152
00153 return v;
00154 }
00155
00160 FORCEINLINE Train *GetPrevUnit()
00161 {
00162 Train *v = this->GetPrevVehicle();
00163 if (v != NULL && v->IsRearDualheaded()) v = v->GetPrevVehicle();
00164
00165 return v;
00166 }
00167
00168
00169 protected:
00176 FORCEINLINE uint16 GetBreakdownSpeed() const
00177 {
00178 assert(this->IsFrontEngine());
00179 uint16 speed = UINT16_MAX;
00180
00181 for (const Train *w = this; w != NULL; w = w->Next()) {
00182 if (w->breakdown_ctr == 1 && w->breakdown_type == BREAKDOWN_LOW_SPEED) {
00183 speed = min(speed, w->breakdown_severity);
00184 }
00185 }
00186 return speed;
00187 }
00188
00193 FORCEINLINE uint16 GetPower() const
00194 {
00195
00196 if (!this->IsArticulatedPart() && HasPowerOnRail(this->railtype, GetRailType(this->tile))) {
00197 uint16 power = GetVehicleProperty(this, PROP_TRAIN_POWER, RailVehInfo(this->engine_type)->power);
00198
00199 if (this->IsMultiheaded()) power /= 2;
00200 return power;
00201 }
00202
00203 return 0;
00204 }
00205
00210 FORCEINLINE uint16 GetPoweredPartPower(const Train *head) const
00211 {
00212
00213 if (HasBit(this->flags, VRF_POWEREDWAGON) && HasPowerOnRail(head->railtype, GetRailType(this->tile))) {
00214 return RailVehInfo(this->gcache.first_engine)->pow_wag_power;
00215 }
00216
00217 return 0;
00218 }
00219
00224 FORCEINLINE uint16 GetWeight() const
00225 {
00226 uint16 weight = (CargoSpec::Get(this->cargo_type)->weight * this->cargo.Count() * FreightWagonMult(this->cargo_type)) / 16;
00227
00228
00229 if (!this->IsArticulatedPart()) {
00230 weight += GetVehicleProperty(this, PROP_TRAIN_WEIGHT, RailVehInfo(this->engine_type)->weight);
00231 }
00232
00233
00234 if (HasBit(this->flags, VRF_POWEREDWAGON)) {
00235 weight += RailVehInfo(this->gcache.first_engine)->pow_wag_weight;
00236 }
00237
00238 return weight;
00239 }
00240
00245 FORCEINLINE byte GetTractiveEffort() const
00246 {
00247 return GetVehicleProperty(this, PROP_TRAIN_TRACTIVE_EFFORT, RailVehInfo(this->engine_type)->tractive_effort);
00248 }
00249
00254 FORCEINLINE byte GetAirDragArea() const
00255 {
00256
00257 return (this->track == TRACK_BIT_WORMHOLE && this->vehstatus & VS_HIDDEN) ? 28 : 14;
00258 }
00259
00264 FORCEINLINE byte GetAirDrag() const
00265 {
00266 return RailVehInfo(this->engine_type)->air_drag;
00267 }
00268
00273 FORCEINLINE AccelStatus GetAccelerationStatus() const
00274 {
00275 return (this->vehstatus & VS_STOPPED) || HasBit(this->flags, VRF_REVERSING) || HasBit(this->flags, VRF_TRAIN_STUCK ) || HasBit(this->flags, VRF_BREAKDOWN_BRAKING) ? AS_BRAKE : AS_ACCEL;
00276 }
00277
00282 FORCEINLINE uint16 GetCurrentSpeed() const
00283 {
00284 return this->cur_speed;
00285 }
00286
00291 FORCEINLINE uint32 GetRollingFriction() const
00292 {
00293
00294
00295
00296 return 15 * (512 + this->GetCurrentSpeed()) / 512;
00297 }
00298
00303 FORCEINLINE int GetAccelerationType() const
00304 {
00305 return GetRailTypeInfo(this->railtype)->acceleration_type;
00306 }
00307
00312 FORCEINLINE uint32 GetSlopeSteepness() const
00313 {
00314 return _settings_game.vehicle.train_slope_steepness;
00315 }
00316
00321 FORCEINLINE uint16 GetMaxTrackSpeed() const
00322 {
00323 return GetRailTypeInfo(GetRailType(this->tile))->max_speed;
00324 }
00325
00330 FORCEINLINE bool TileMayHaveSlopedTrack() const
00331 {
00332
00333 return this->track == TRACK_BIT_X || this->track == TRACK_BIT_Y;
00334 }
00335 };
00336
00337 #define FOR_ALL_TRAINS(var) FOR_ALL_VEHICLES_OF_TYPE(Train, var)
00338
00339 #endif