train.h

Go to the documentation of this file.
00001 /* $Id: train.h 18854 2010-01-17 23:03:43Z rubidium $ */
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 "vehicle_base.h"
00016 #include "newgrf_engine.h"
00017 #include "cargotype.h"
00018 #include "rail.h"
00019 #include "engine_base.h"
00020 #include "rail_map.h"
00021 
00022 struct Train;
00023 
00024 enum VehicleRailFlags {
00025   VRF_REVERSING         = 0,
00026 
00027   /* used to calculate if train is going up or down */
00028   VRF_GOINGUP           = 1,
00029   VRF_GOINGDOWN         = 2,
00030 
00031   /* used to store if a wagon is powered or not */
00032   VRF_POWEREDWAGON      = 3,
00033 
00034   /* used to reverse the visible direction of the vehicle */
00035   VRF_REVERSE_DIRECTION = 4,
00036 
00037   /* used to mark train as lost because PF can't find the route */
00038   VRF_NO_PATH_TO_DESTINATION = 5,
00039 
00040   /* used to mark that electric train engine is allowed to run on normal rail */
00041   VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL = 6,
00042 
00043   /* used for vehicle var 0xFE bit 8 (toggled each time the train is reversed, accurate for first vehicle only) */
00044   VRF_TOGGLE_REVERSE = 7,
00045 
00046   /* used to mark a train that can't get a path reservation */
00047   VRF_TRAIN_STUCK    = 8,
00048 };
00049 
00050 byte FreightWagonMult(CargoID cargo);
00051 
00052 void CheckTrainsLengths();
00053 
00054 void FreeTrainTrackReservation(const Train *v, TileIndex origin = INVALID_TILE, Trackdir orig_td = INVALID_TRACKDIR);
00055 bool TryPathReserve(Train *v, bool mark_as_stuck = false, bool first_tile_okay = false);
00056 
00057 int GetTrainStopLocation(StationID station_id, TileIndex tile, const Train *v, int *station_ahead, int *station_length);
00058 
00060 struct TrainCache {
00061   /* Cached wagon override spritegroup */
00062   const struct SpriteGroup *cached_override;
00063 
00064   uint16 last_speed; // NOSAVE: only used in UI
00065 
00066   /* cached values, recalculated on load and each time a vehicle is added to/removed from the consist. */
00067   uint32 cached_power;            
00068   uint16 cached_axle_resistance;  
00069   uint32 cached_air_drag;         
00070   uint16 cached_total_length;     
00071   uint8 cached_veh_length;        
00072   bool cached_tilt;               
00073 
00074   /* cached values, recalculated when the cargo on a train changes (in addition to the conditions above) */
00075   uint32 cached_weight;           
00076   uint32 cached_slope_resistance; 
00077   uint32 cached_max_te;           
00078 
00079   /* cached max. speed / acceleration data */
00080   uint16 cached_max_speed;    
00081   int cached_max_curve_speed; 
00082 
00090   byte cached_vis_effect;
00091   byte user_def_data;
00092 
00093   EngineID first_engine;  
00094 };
00095 
00097 enum AccelStatus {
00098   AS_ACCEL, 
00099   AS_BRAKE  
00100 };
00101 
00105 struct Train : public SpecializedVehicle<Train, VEH_TRAIN> {
00106   TrainCache tcache;
00107 
00108   /* Link between the two ends of a multiheaded engine */
00109   Train *other_multiheaded_part;
00110 
00111   uint16 crash_anim_pos;
00112 
00113   uint16 flags;
00114   TrackBitsByte track;
00115   byte force_proceed;
00116   RailTypeByte railtype;
00117   RailTypes compatible_railtypes;
00118 
00120   uint16 wait_counter;
00121 
00123   Train() : SpecializedVehicle<Train, VEH_TRAIN>() {}
00125   virtual ~Train() { this->PreDestructor(); }
00126 
00127   const char *GetTypeString() const { return "train"; }
00128   void MarkDirty();
00129   void UpdateDeltaXY(Direction direction);
00130   ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_TRAIN_INC : EXPENSES_TRAIN_RUN; }
00131   void PlayLeaveStationSound() const;
00132   bool IsPrimaryVehicle() const { return this->IsFrontEngine(); }
00133   SpriteID GetImage(Direction direction) const;
00134   int GetDisplaySpeed() const { return this->tcache.last_speed; }
00135   int GetDisplayMaxSpeed() const { return this->tcache.cached_max_speed; }
00136   Money GetRunningCost() const;
00137   int GetDisplayImageWidth(Point *offset = NULL) const;
00138   bool IsInDepot() const;
00139   bool IsStoppedInDepot() const;
00140   bool Tick();
00141   void OnNewDay();
00142   uint Crash(bool flooded = false);
00143   Trackdir GetVehicleTrackdir() const;
00144   TileIndex GetOrderStationLocation(StationID station);
00145   bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse);
00146 
00147   void ReserveTrackUnderConsist() const;
00148 
00149   int GetCurveSpeedLimit() const;
00150 
00151   void ConsistChanged(bool same_length);
00152   void CargoChanged();
00153   void PowerChanged();
00154 
00155   int UpdateSpeed();
00156 
00157   void UpdateAcceleration();
00158 
00159   int GetCurrentMaxSpeed() const;
00160   int GetAcceleration() const;
00161 
00167   enum TrainSubtype {
00168     TS_FRONT             = 0, 
00169     TS_ARTICULATED_PART  = 1, 
00170     TS_WAGON             = 2, 
00171     TS_ENGINE            = 3, 
00172     TS_FREE_WAGON        = 4, 
00173     TS_MULTIHEADED       = 5, 
00174   };
00175 
00179   FORCEINLINE void SetFrontEngine() { SetBit(this->subtype, TS_FRONT); }
00180 
00184   FORCEINLINE void ClearFrontEngine() { ClrBit(this->subtype, TS_FRONT); }
00185 
00189   FORCEINLINE void SetArticulatedPart() { SetBit(this->subtype, TS_ARTICULATED_PART); }
00190 
00194   FORCEINLINE void ClearArticulatedPart() { ClrBit(this->subtype, TS_ARTICULATED_PART); }
00195 
00199   FORCEINLINE void SetWagon() { SetBit(this->subtype, TS_WAGON); }
00200 
00204   FORCEINLINE void ClearWagon() { ClrBit(this->subtype, TS_WAGON); }
00205 
00209   FORCEINLINE void SetEngine() { SetBit(this->subtype, TS_ENGINE); }
00210 
00214   FORCEINLINE void ClearEngine() { ClrBit(this->subtype, TS_ENGINE); }
00215 
00219   FORCEINLINE void SetFreeWagon() { SetBit(this->subtype, TS_FREE_WAGON); }
00220 
00224   FORCEINLINE void ClearFreeWagon() { ClrBit(this->subtype, TS_FREE_WAGON); }
00225 
00229   FORCEINLINE void SetMultiheaded() { SetBit(this->subtype, TS_MULTIHEADED); }
00230 
00234   FORCEINLINE void ClearMultiheaded() { ClrBit(this->subtype, TS_MULTIHEADED); }
00235 
00236 
00241   FORCEINLINE bool IsFrontEngine() const { return HasBit(this->subtype, TS_FRONT); }
00242 
00247   FORCEINLINE bool IsFreeWagon() const { return HasBit(this->subtype, TS_FREE_WAGON); }
00248 
00253   FORCEINLINE bool IsEngine() const { return HasBit(this->subtype, TS_ENGINE); }
00254 
00259   FORCEINLINE bool IsWagon() const { return HasBit(this->subtype, TS_WAGON); }
00260 
00265   FORCEINLINE bool IsMultiheaded() const { return HasBit(this->subtype, TS_MULTIHEADED); }
00266 
00271   FORCEINLINE bool IsRearDualheaded() const { return this->IsMultiheaded() && !this->IsEngine(); }
00272 
00277   FORCEINLINE bool IsArticulatedPart() const { return HasBit(this->subtype, TS_ARTICULATED_PART); }
00278 
00283   FORCEINLINE bool HasArticulatedPart() const { return this->Next() != NULL && this->Next()->IsArticulatedPart(); }
00284 
00285 
00292   FORCEINLINE Train *GetNextArticPart() const
00293   {
00294     assert(this->HasArticulatedPart());
00295     return this->Next();
00296   }
00297 
00302   FORCEINLINE Train *GetFirstEnginePart()
00303   {
00304     Train *v = this;
00305     while (v->IsArticulatedPart()) v = v->Previous();
00306     return v;
00307   }
00308 
00313   FORCEINLINE const Train *GetFirstEnginePart() const
00314   {
00315     const Train *v = this;
00316     while (v->IsArticulatedPart()) v = v->Previous();
00317     return v;
00318   }
00319 
00324   FORCEINLINE Train *GetLastEnginePart()
00325   {
00326     Train *v = this;
00327     while (v->HasArticulatedPart()) v = v->GetNextArticPart();
00328     return v;
00329   }
00330 
00335   FORCEINLINE Train *GetNextVehicle() const
00336   {
00337     const Train *v = this;
00338     while (v->HasArticulatedPart()) v = v->GetNextArticPart();
00339 
00340     /* v now contains the last artic part in the engine */
00341     return v->Next();
00342   }
00343 
00348   FORCEINLINE Train *GetPrevVehicle() const
00349   {
00350     Train *v = this->Previous();
00351     while (v != NULL && v->IsArticulatedPart()) v = v->Previous();
00352 
00353     return v;
00354   }
00355 
00360   FORCEINLINE Train *GetNextUnit() const
00361   {
00362     Train *v = this->GetNextVehicle();
00363     if (v != NULL && v->IsRearDualheaded()) v = v->GetNextVehicle();
00364 
00365     return v;
00366   }
00367 
00372   FORCEINLINE Train *GetPrevUnit()
00373   {
00374     Train *v = this->GetPrevVehicle();
00375     if (v != NULL && v->IsRearDualheaded()) v = v->GetPrevVehicle();
00376 
00377     return v;
00378   }
00379 
00380 
00381 protected: /* These functions should not be called outside acceleration code. */
00382 
00387   FORCEINLINE uint16 GetPower() const
00388   {
00389     /* Power is not added for articulated parts */
00390     if (!this->IsArticulatedPart() && HasPowerOnRail(this->railtype, GetRailType(this->tile))) {
00391       uint16 power = GetVehicleProperty(this, PROP_TRAIN_POWER, RailVehInfo(this->engine_type)->power);
00392       /* Halve power for multiheaded parts */
00393       if (this->IsMultiheaded()) power /= 2;
00394       return power;
00395     }
00396 
00397     return 0;
00398   }
00399 
00404   FORCEINLINE uint16 GetPoweredPartPower(const Train *head) const
00405   {
00406     if (HasBit(this->flags, VRF_POWEREDWAGON) && HasPowerOnRail(head->railtype, GetRailType(head->tile))) {
00407       return RailVehInfo(this->tcache.first_engine)->pow_wag_power;
00408     }
00409 
00410     return 0;
00411   }
00412 
00417   FORCEINLINE uint16 GetWeight() const
00418   {
00419     uint16 weight = (CargoSpec::Get(this->cargo_type)->weight * this->cargo.Count() * FreightWagonMult(this->cargo_type)) / 16;
00420 
00421     /* Vehicle weight is not added for articulated parts. */
00422     if (!this->IsArticulatedPart()) {
00423       weight += GetVehicleProperty(this, PROP_TRAIN_WEIGHT, RailVehInfo(this->engine_type)->weight);
00424     }
00425 
00426     /* Powered wagons have extra weight added. */
00427     if (HasBit(this->flags, VRF_POWEREDWAGON)) {
00428       weight += RailVehInfo(this->tcache.first_engine)->pow_wag_weight;
00429     }
00430 
00431     return weight;
00432   }
00433 
00438   FORCEINLINE byte GetTractiveEffort() const
00439   {
00440     return GetVehicleProperty(this, PROP_TRAIN_TRACTIVE_EFFORT, RailVehInfo(this->engine_type)->tractive_effort);
00441   }
00442 
00447   FORCEINLINE AccelStatus GetAccelerationStatus() const
00448   {
00449     return (this->vehstatus & VS_STOPPED) || HasBit(this->flags, VRF_REVERSING) || HasBit(this->flags, VRF_TRAIN_STUCK) ? AS_BRAKE : AS_ACCEL;
00450   }
00451 
00456   FORCEINLINE uint16 GetCurrentSpeed() const
00457   {
00458     return this->cur_speed * 10 / 16;
00459   }
00460 
00465   FORCEINLINE uint32 GetRollingFriction() const
00466   {
00467     return 35;
00468   }
00469 
00474   FORCEINLINE int32 GetSlopeResistance() const
00475   {
00476     int32 incl = 0;
00477 
00478     for (const Train *u = this; u != NULL; u = u->Next()) {
00479       if (HasBit(u->flags, VRF_GOINGUP)) {
00480         incl += u->tcache.cached_slope_resistance;
00481       } else if (HasBit(u->flags, VRF_GOINGDOWN)) {
00482         incl -= u->tcache.cached_slope_resistance;
00483       }
00484     }
00485 
00486     return incl;
00487   }
00488 
00493   FORCEINLINE int GetAccelerationType() const
00494   {
00495     return GetRailTypeInfo(this->railtype)->acceleration_type;
00496   }
00497 };
00498 
00499 #define FOR_ALL_TRAINS(var) FOR_ALL_VEHICLES_OF_TYPE(Train, var)
00500 
00501 #endif /* TRAIN_H */

Generated on Wed Jan 20 23:38:41 2010 for OpenTTD by  doxygen 1.5.6