train.h

Go to the documentation of this file.
00001 /* $Id$ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * 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.
00006  * 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.
00007  * 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/>.
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   /* Cached wagon override spritegroup */
00058   const struct SpriteGroup *cached_override;
00059 
00060   /* cached values, recalculated on load and each time a vehicle is added to/removed from the consist. */
00061   bool cached_tilt;           
00062 
00063   byte user_def_data;         
00064 
00065   /* cached max. speed / acceleration data */
00066   int cached_max_curve_speed; 
00067 };
00068 
00072 struct Train FINAL : public GroundVehicle<Train, VEH_TRAIN> {
00073   TrainCache tcache;
00074 
00075   /* Link between the two ends of a multiheaded engine */
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>; // GroundVehicle needs to use the acceleration functions defined at 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     /* For vehicles with odd lengths the part before the center will be one unit
00157      * longer than the part after the center. This means we have to round up the
00158      * length of the next vehicle but may not round the length of the current
00159      * vehicle. */
00160     return this->gcache.cached_veh_length / 2 + (this->Next() != NULL ? this->Next()->gcache.cached_veh_length + 1 : 0) / 2;
00161   }
00162 
00163 protected: // These functions should not be called outside acceleration code.
00164 
00169   inline uint16 GetPower() const
00170   {
00171     /* Power is not added for articulated parts */
00172     if (!this->IsArticulatedPart() && HasPowerOnRail(this->railtype, GetRailType(this->tile))) {
00173       uint16 power = GetVehicleProperty(this, PROP_TRAIN_POWER, RailVehInfo(this->engine_type)->power);
00174       /* Halve power for multiheaded parts */
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     /* For powered wagons the engine defines the type of engine (i.e. railtype) */
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.Count() * FreightWagonMult(this->cargo_type)) / 16;
00203 
00204     /* Vehicle weight is not added for articulated parts. */
00205     if (!this->IsArticulatedPart()) {
00206       weight += GetVehicleProperty(this, PROP_TRAIN_WEIGHT, RailVehInfo(this->engine_type)->weight);
00207     }
00208 
00209     /* Powered wagons have extra weight added. */
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     /* Air drag is higher in tunnels due to the limited cross-section. */
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     /* Rolling friction for steel on steel is between 0.1% and 0.2%.
00270      * The friction coefficient increases with speed in a way that
00271      * it doubles at 512 km/h, triples at 1024 km/h and so on. */
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     /* Any track that isn't TRACK_BIT_X or TRACK_BIT_Y cannot be sloped. */
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 /* TRAIN_H */