train.h

Go to the documentation of this file.
00001 /* $Id: train.h 21521 2010-12-14 21:33:53Z terkhen $ */
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 
00024 enum VehicleRailFlags {
00025   VRF_REVERSING         = 0,
00026 
00027   /* used to store if a wagon is powered or not */
00028   VRF_POWEREDWAGON      = 3,
00029 
00030   /* used to reverse the visible direction of the vehicle */
00031   VRF_REVERSE_DIRECTION = 4,
00032 
00033   /* used to mark that electric train engine is allowed to run on normal rail */
00034   VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL = 6,
00035 
00036   /* used for vehicle var 0xFE bit 8 (toggled each time the train is reversed, accurate for first vehicle only) */
00037   VRF_TOGGLE_REVERSE = 7,
00038 
00039   /* used to mark a train that can't get a path reservation */
00040   VRF_TRAIN_STUCK    = 8,
00041 
00042   /* used to mark a train that is just leaving a station */
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   /* Cached wagon override spritegroup */
00066   const struct SpriteGroup *cached_override;
00067 
00068   uint16 last_speed; // NOSAVE: only used in UI
00069 
00070   /* cached values, recalculated on load and each time a vehicle is added to/removed from the consist. */
00071   bool cached_tilt;           
00072 
00073   byte user_def_data;         
00074 
00075   /* cached max. speed / acceleration data */
00076   int cached_max_curve_speed; 
00077 };
00078 
00082 struct Train : public GroundVehicle<Train, VEH_TRAIN> {
00083   TrainCache tcache;
00084 
00085   /* Link between the two ends of a multiheaded engine */
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>; // GroundVehicle needs to use the acceleration functions defined at 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 
00145   enum TrainSubtype {
00146     TS_FRONT             = 0, 
00147     TS_ARTICULATED_PART  = 1, 
00148     TS_WAGON             = 2, 
00149     TS_ENGINE            = 3, 
00150     TS_FREE_WAGON        = 4, 
00151     TS_MULTIHEADED       = 5, 
00152   };
00153 
00157   FORCEINLINE void SetFrontEngine() { SetBit(this->subtype, TS_FRONT); }
00158 
00162   FORCEINLINE void ClearFrontEngine() { ClrBit(this->subtype, TS_FRONT); }
00163 
00167   FORCEINLINE void SetArticulatedPart() { SetBit(this->subtype, TS_ARTICULATED_PART); }
00168 
00172   FORCEINLINE void ClearArticulatedPart() { ClrBit(this->subtype, TS_ARTICULATED_PART); }
00173 
00177   FORCEINLINE void SetWagon() { SetBit(this->subtype, TS_WAGON); }
00178 
00182   FORCEINLINE void ClearWagon() { ClrBit(this->subtype, TS_WAGON); }
00183 
00187   FORCEINLINE void SetEngine() { SetBit(this->subtype, TS_ENGINE); }
00188 
00192   FORCEINLINE void ClearEngine() { ClrBit(this->subtype, TS_ENGINE); }
00193 
00197   FORCEINLINE void SetFreeWagon() { SetBit(this->subtype, TS_FREE_WAGON); }
00198 
00202   FORCEINLINE void ClearFreeWagon() { ClrBit(this->subtype, TS_FREE_WAGON); }
00203 
00207   FORCEINLINE void SetMultiheaded() { SetBit(this->subtype, TS_MULTIHEADED); }
00208 
00212   FORCEINLINE void ClearMultiheaded() { ClrBit(this->subtype, TS_MULTIHEADED); }
00213 
00214 
00219   FORCEINLINE bool IsFrontEngine() const { return HasBit(this->subtype, TS_FRONT); }
00220 
00225   FORCEINLINE bool IsFreeWagon() const { return HasBit(this->subtype, TS_FREE_WAGON); }
00226 
00231   FORCEINLINE bool IsEngine() const { return HasBit(this->subtype, TS_ENGINE); }
00232 
00237   FORCEINLINE bool IsWagon() const { return HasBit(this->subtype, TS_WAGON); }
00238 
00243   FORCEINLINE bool IsMultiheaded() const { return HasBit(this->subtype, TS_MULTIHEADED); }
00244 
00249   FORCEINLINE bool IsRearDualheaded() const { return this->IsMultiheaded() && !this->IsEngine(); }
00250 
00255   FORCEINLINE bool IsArticulatedPart() const { return HasBit(this->subtype, TS_ARTICULATED_PART); }
00256 
00261   FORCEINLINE bool HasArticulatedPart() const { return this->Next() != NULL && this->Next()->IsArticulatedPart(); }
00262 
00263 
00270   FORCEINLINE Train *GetNextArticPart() const
00271   {
00272     assert(this->HasArticulatedPart());
00273     return this->Next();
00274   }
00275 
00280   FORCEINLINE Train *GetFirstEnginePart()
00281   {
00282     Train *v = this;
00283     while (v->IsArticulatedPart()) v = v->Previous();
00284     return v;
00285   }
00286 
00291   FORCEINLINE const Train *GetFirstEnginePart() const
00292   {
00293     const Train *v = this;
00294     while (v->IsArticulatedPart()) v = v->Previous();
00295     return v;
00296   }
00297 
00302   FORCEINLINE Train *GetLastEnginePart()
00303   {
00304     Train *v = this;
00305     while (v->HasArticulatedPart()) v = v->GetNextArticPart();
00306     return v;
00307   }
00308 
00313   FORCEINLINE Train *GetNextVehicle() const
00314   {
00315     const Train *v = this;
00316     while (v->HasArticulatedPart()) v = v->GetNextArticPart();
00317 
00318     /* v now contains the last artic part in the engine */
00319     return v->Next();
00320   }
00321 
00326   FORCEINLINE Train *GetPrevVehicle() const
00327   {
00328     Train *v = this->Previous();
00329     while (v != NULL && v->IsArticulatedPart()) v = v->Previous();
00330 
00331     return v;
00332   }
00333 
00338   FORCEINLINE Train *GetNextUnit() const
00339   {
00340     Train *v = this->GetNextVehicle();
00341     if (v != NULL && v->IsRearDualheaded()) v = v->GetNextVehicle();
00342 
00343     return v;
00344   }
00345 
00350   FORCEINLINE Train *GetPrevUnit()
00351   {
00352     Train *v = this->GetPrevVehicle();
00353     if (v != NULL && v->IsRearDualheaded()) v = v->GetPrevVehicle();
00354 
00355     return v;
00356   }
00357 
00358 
00359 protected: // These functions should not be called outside acceleration code.
00360 
00365   FORCEINLINE uint16 GetPower() const
00366   {
00367     /* Power is not added for articulated parts */
00368     if (!this->IsArticulatedPart() && HasPowerOnRail(this->railtype, GetRailType(this->tile))) {
00369       uint16 power = GetVehicleProperty(this, PROP_TRAIN_POWER, RailVehInfo(this->engine_type)->power);
00370       /* Halve power for multiheaded parts */
00371       if (this->IsMultiheaded()) power /= 2;
00372       return power;
00373     }
00374 
00375     return 0;
00376   }
00377 
00382   FORCEINLINE uint16 GetPoweredPartPower(const Train *head) const
00383   {
00384     /* For powered wagons the engine defines the type of engine (i.e. railtype) */
00385     if (HasBit(this->flags, VRF_POWEREDWAGON) && HasPowerOnRail(head->railtype, GetRailType(this->tile))) {
00386       return RailVehInfo(this->gcache.first_engine)->pow_wag_power;
00387     }
00388 
00389     return 0;
00390   }
00391 
00396   FORCEINLINE uint16 GetWeight() const
00397   {
00398     uint16 weight = (CargoSpec::Get(this->cargo_type)->weight * this->cargo.Count() * FreightWagonMult(this->cargo_type)) / 16;
00399 
00400     /* Vehicle weight is not added for articulated parts. */
00401     if (!this->IsArticulatedPart()) {
00402       weight += GetVehicleProperty(this, PROP_TRAIN_WEIGHT, RailVehInfo(this->engine_type)->weight);
00403     }
00404 
00405     /* Powered wagons have extra weight added. */
00406     if (HasBit(this->flags, VRF_POWEREDWAGON)) {
00407       weight += RailVehInfo(this->gcache.first_engine)->pow_wag_weight;
00408     }
00409 
00410     return weight;
00411   }
00412 
00417   FORCEINLINE byte GetTractiveEffort() const
00418   {
00419     return GetVehicleProperty(this, PROP_TRAIN_TRACTIVE_EFFORT, RailVehInfo(this->engine_type)->tractive_effort);
00420   }
00421 
00426   FORCEINLINE byte GetAirDragArea() const
00427   {
00428     /* Air drag is higher in tunnels due to the limited cross-section. */
00429     return (this->track == TRACK_BIT_WORMHOLE && this->vehstatus & VS_HIDDEN) ? 28 : 14;
00430   }
00431 
00436   FORCEINLINE byte GetAirDrag() const
00437   {
00438     return RailVehInfo(this->engine_type)->air_drag;
00439   }
00440 
00445   FORCEINLINE AccelStatus GetAccelerationStatus() const
00446   {
00447     return (this->vehstatus & VS_STOPPED) || HasBit(this->flags, VRF_REVERSING) || HasBit(this->flags, VRF_TRAIN_STUCK) ? AS_BRAKE : AS_ACCEL;
00448   }
00449 
00454   FORCEINLINE uint16 GetCurrentSpeed() const
00455   {
00456     return this->cur_speed;
00457   }
00458 
00463   FORCEINLINE uint32 GetRollingFriction() const
00464   {
00465     /* Rolling friction for steel on steel is between 0.1% and 0.2%,
00466      * but we use a higher value here to get better game-play results.
00467      * The friction coefficient increases with speed in a way that
00468      * it doubles at 512 km/h, triples at 1024 km/h and so on. */
00469     return 30 * (512 + this->GetCurrentSpeed()) / 512;
00470   }
00471 
00476   FORCEINLINE int GetAccelerationType() const
00477   {
00478     return GetRailTypeInfo(this->railtype)->acceleration_type;
00479   }
00480 
00485   FORCEINLINE uint32 GetSlopeSteepness() const
00486   {
00487     return _settings_game.vehicle.train_slope_steepness;
00488   }
00489 
00494   FORCEINLINE uint16 GetMaxTrackSpeed() const
00495   {
00496     return GetRailTypeInfo(GetRailType(this->tile))->max_speed;
00497   }
00498 
00503   FORCEINLINE bool TileMayHaveSlopedTrack() const
00504   {
00505     /* Any track that isn't TRACK_BIT_X or TRACK_BIT_Y cannot be sloped. */
00506     return this->track == TRACK_BIT_X || this->track == TRACK_BIT_Y;
00507   }
00508 };
00509 
00510 #define FOR_ALL_TRAINS(var) FOR_ALL_VEHICLES_OF_TYPE(Train, var)
00511 
00512 #endif /* TRAIN_H */

Generated on Fri Dec 31 17:15:41 2010 for OpenTTD by  doxygen 1.6.1