train.h

Go to the documentation of this file.
00001 /* $Id: train.h 20521 2010-08-16 23:15:33Z 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 
00063 struct AccelerationCache {
00064   /* cached values, recalculated when the cargo on a train changes (in addition to the conditions above) */
00065   uint32 cached_weight;           
00066   uint32 cached_slope_resistance; 
00067   uint32 cached_max_te;           
00068 
00069   /* cached values, recalculated on load and each time a vehicle is added to/removed from the consist. */
00070   uint32 cached_power;            
00071   uint32 cached_air_drag;         
00072   uint16 cached_axle_resistance;  
00073 };
00074 
00076 struct TrainCache : public AccelerationCache {
00077   /* Cached wagon override spritegroup */
00078   const struct SpriteGroup *cached_override;
00079 
00080   uint16 last_speed; // NOSAVE: only used in UI
00081 
00082   /* cached values, recalculated on load and each time a vehicle is added to/removed from the consist. */
00083   uint16 cached_total_length; 
00084   uint8 cached_veh_length;    
00085   bool cached_tilt;           
00086 
00087   /* cached max. speed / acceleration data */
00088   uint16 cached_max_speed;    
00089   uint16 cached_max_rail_speed; 
00090   int cached_max_curve_speed; 
00091 
00099   byte cached_vis_effect;
00100   byte user_def_data;
00101 
00102   EngineID first_engine;  
00103 };
00104 
00106 enum AccelStatus {
00107   AS_ACCEL, 
00108   AS_BRAKE  
00109 };
00110 
00114 struct Train : public SpecializedVehicle<Train, VEH_TRAIN> {
00115   TrainCache tcache;
00116 
00117   /* Link between the two ends of a multiheaded engine */
00118   Train *other_multiheaded_part;
00119 
00120   uint16 crash_anim_pos;
00121 
00122   uint16 flags;
00123   TrackBitsByte track;
00124   byte force_proceed;
00125   RailTypeByte railtype;
00126   RailTypes compatible_railtypes;
00127 
00129   uint16 wait_counter;
00130 
00132   Train() : SpecializedVehicle<Train, VEH_TRAIN>() {}
00134   virtual ~Train() { this->PreDestructor(); }
00135 
00136   const char *GetTypeString() const { return "train"; }
00137   void MarkDirty();
00138   void UpdateDeltaXY(Direction direction);
00139   ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_TRAIN_INC : EXPENSES_TRAIN_RUN; }
00140   void PlayLeaveStationSound() const;
00141   bool IsPrimaryVehicle() const { return this->IsFrontEngine(); }
00142   SpriteID GetImage(Direction direction) const;
00143   int GetDisplaySpeed() const { return this->tcache.last_speed; }
00144   int GetDisplayMaxSpeed() const { return this->tcache.cached_max_speed; }
00145   Money GetRunningCost() const;
00146   int GetDisplayImageWidth(Point *offset = NULL) const;
00147   bool IsInDepot() const;
00148   bool IsStoppedInDepot() const;
00149   bool Tick();
00150   void OnNewDay();
00151   uint Crash(bool flooded = false);
00152   Trackdir GetVehicleTrackdir() const;
00153   TileIndex GetOrderStationLocation(StationID station);
00154   bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse);
00155 
00156   void ReserveTrackUnderConsist() const;
00157 
00158   int GetCurveSpeedLimit() const;
00159 
00160   void ConsistChanged(bool same_length);
00161   void CargoChanged();
00162   void PowerChanged();
00163 
00164   void RailtypeChanged();
00165 
00166   int UpdateSpeed();
00167 
00168   void UpdateAcceleration();
00169 
00170   int GetCurrentMaxSpeed() const;
00171   int GetAcceleration() const;
00172 
00178   enum TrainSubtype {
00179     TS_FRONT             = 0, 
00180     TS_ARTICULATED_PART  = 1, 
00181     TS_WAGON             = 2, 
00182     TS_ENGINE            = 3, 
00183     TS_FREE_WAGON        = 4, 
00184     TS_MULTIHEADED       = 5, 
00185   };
00186 
00190   FORCEINLINE void SetFrontEngine() { SetBit(this->subtype, TS_FRONT); }
00191 
00195   FORCEINLINE void ClearFrontEngine() { ClrBit(this->subtype, TS_FRONT); }
00196 
00200   FORCEINLINE void SetArticulatedPart() { SetBit(this->subtype, TS_ARTICULATED_PART); }
00201 
00205   FORCEINLINE void ClearArticulatedPart() { ClrBit(this->subtype, TS_ARTICULATED_PART); }
00206 
00210   FORCEINLINE void SetWagon() { SetBit(this->subtype, TS_WAGON); }
00211 
00215   FORCEINLINE void ClearWagon() { ClrBit(this->subtype, TS_WAGON); }
00216 
00220   FORCEINLINE void SetEngine() { SetBit(this->subtype, TS_ENGINE); }
00221 
00225   FORCEINLINE void ClearEngine() { ClrBit(this->subtype, TS_ENGINE); }
00226 
00230   FORCEINLINE void SetFreeWagon() { SetBit(this->subtype, TS_FREE_WAGON); }
00231 
00235   FORCEINLINE void ClearFreeWagon() { ClrBit(this->subtype, TS_FREE_WAGON); }
00236 
00240   FORCEINLINE void SetMultiheaded() { SetBit(this->subtype, TS_MULTIHEADED); }
00241 
00245   FORCEINLINE void ClearMultiheaded() { ClrBit(this->subtype, TS_MULTIHEADED); }
00246 
00247 
00252   FORCEINLINE bool IsFrontEngine() const { return HasBit(this->subtype, TS_FRONT); }
00253 
00258   FORCEINLINE bool IsFreeWagon() const { return HasBit(this->subtype, TS_FREE_WAGON); }
00259 
00264   FORCEINLINE bool IsEngine() const { return HasBit(this->subtype, TS_ENGINE); }
00265 
00270   FORCEINLINE bool IsWagon() const { return HasBit(this->subtype, TS_WAGON); }
00271 
00276   FORCEINLINE bool IsMultiheaded() const { return HasBit(this->subtype, TS_MULTIHEADED); }
00277 
00282   FORCEINLINE bool IsRearDualheaded() const { return this->IsMultiheaded() && !this->IsEngine(); }
00283 
00288   FORCEINLINE bool IsArticulatedPart() const { return HasBit(this->subtype, TS_ARTICULATED_PART); }
00289 
00294   FORCEINLINE bool HasArticulatedPart() const { return this->Next() != NULL && this->Next()->IsArticulatedPart(); }
00295 
00296 
00303   FORCEINLINE Train *GetNextArticPart() const
00304   {
00305     assert(this->HasArticulatedPart());
00306     return this->Next();
00307   }
00308 
00313   FORCEINLINE Train *GetFirstEnginePart()
00314   {
00315     Train *v = this;
00316     while (v->IsArticulatedPart()) v = v->Previous();
00317     return v;
00318   }
00319 
00324   FORCEINLINE const Train *GetFirstEnginePart() const
00325   {
00326     const Train *v = this;
00327     while (v->IsArticulatedPart()) v = v->Previous();
00328     return v;
00329   }
00330 
00335   FORCEINLINE Train *GetLastEnginePart()
00336   {
00337     Train *v = this;
00338     while (v->HasArticulatedPart()) v = v->GetNextArticPart();
00339     return v;
00340   }
00341 
00346   FORCEINLINE Train *GetNextVehicle() const
00347   {
00348     const Train *v = this;
00349     while (v->HasArticulatedPart()) v = v->GetNextArticPart();
00350 
00351     /* v now contains the last artic part in the engine */
00352     return v->Next();
00353   }
00354 
00359   FORCEINLINE Train *GetPrevVehicle() const
00360   {
00361     Train *v = this->Previous();
00362     while (v != NULL && v->IsArticulatedPart()) v = v->Previous();
00363 
00364     return v;
00365   }
00366 
00371   FORCEINLINE Train *GetNextUnit() const
00372   {
00373     Train *v = this->GetNextVehicle();
00374     if (v != NULL && v->IsRearDualheaded()) v = v->GetNextVehicle();
00375 
00376     return v;
00377   }
00378 
00383   FORCEINLINE Train *GetPrevUnit()
00384   {
00385     Train *v = this->GetPrevVehicle();
00386     if (v != NULL && v->IsRearDualheaded()) v = v->GetPrevVehicle();
00387 
00388     return v;
00389   }
00390 
00391 
00392 protected: // These functions should not be called outside acceleration code.
00393 
00394   void UpdateVisualEffect(bool allow_power_change);
00395 
00400   FORCEINLINE uint16 GetPower() const
00401   {
00402     /* Power is not added for articulated parts */
00403     if (!this->IsArticulatedPart() && HasPowerOnRail(this->railtype, GetRailType(this->tile))) {
00404       uint16 power = GetVehicleProperty(this, PROP_TRAIN_POWER, RailVehInfo(this->engine_type)->power);
00405       /* Halve power for multiheaded parts */
00406       if (this->IsMultiheaded()) power /= 2;
00407       return power;
00408     }
00409 
00410     return 0;
00411   }
00412 
00417   FORCEINLINE uint16 GetPoweredPartPower(const Train *head) const
00418   {
00419     /* For powered wagons the engine defines the type of engine (i.e. railtype) */
00420     if (HasBit(this->flags, VRF_POWEREDWAGON) && HasPowerOnRail(head->railtype, GetRailType(this->tile))) {
00421       return RailVehInfo(this->tcache.first_engine)->pow_wag_power;
00422     }
00423 
00424     return 0;
00425   }
00426 
00431   FORCEINLINE uint16 GetWeight() const
00432   {
00433     uint16 weight = (CargoSpec::Get(this->cargo_type)->weight * this->cargo.Count() * FreightWagonMult(this->cargo_type)) / 16;
00434 
00435     /* Vehicle weight is not added for articulated parts. */
00436     if (!this->IsArticulatedPart()) {
00437       weight += GetVehicleProperty(this, PROP_TRAIN_WEIGHT, RailVehInfo(this->engine_type)->weight);
00438     }
00439 
00440     /* Powered wagons have extra weight added. */
00441     if (HasBit(this->flags, VRF_POWEREDWAGON)) {
00442       weight += RailVehInfo(this->tcache.first_engine)->pow_wag_weight;
00443     }
00444 
00445     return weight;
00446   }
00447 
00452   FORCEINLINE byte GetTractiveEffort() const
00453   {
00454     return GetVehicleProperty(this, PROP_TRAIN_TRACTIVE_EFFORT, RailVehInfo(this->engine_type)->tractive_effort);
00455   }
00456 
00461   FORCEINLINE AccelStatus GetAccelerationStatus() const
00462   {
00463     return (this->vehstatus & VS_STOPPED) || HasBit(this->flags, VRF_REVERSING) || HasBit(this->flags, VRF_TRAIN_STUCK) ? AS_BRAKE : AS_ACCEL;
00464   }
00465 
00470   FORCEINLINE uint16 GetCurrentSpeed() const
00471   {
00472     return this->cur_speed * 10 / 16;
00473   }
00474 
00479   FORCEINLINE uint32 GetRollingFriction() const
00480   {
00481     return 35;
00482   }
00483 
00488   FORCEINLINE int32 GetSlopeResistance() const
00489   {
00490     int32 incl = 0;
00491 
00492     for (const Train *u = this; u != NULL; u = u->Next()) {
00493       if (HasBit(u->flags, VRF_GOINGUP)) {
00494         incl += u->tcache.cached_slope_resistance;
00495       } else if (HasBit(u->flags, VRF_GOINGDOWN)) {
00496         incl -= u->tcache.cached_slope_resistance;
00497       }
00498     }
00499 
00500     return incl;
00501   }
00502 
00507   FORCEINLINE int GetAccelerationType() const
00508   {
00509     return GetRailTypeInfo(this->railtype)->acceleration_type;
00510   }
00511 
00516   FORCEINLINE uint32 GetSlopeSteepness() const
00517   {
00518     return 20 * _settings_game.vehicle.train_slope_steepness; // 1% slope * slope steepness
00519   }
00520 };
00521 
00522 #define FOR_ALL_TRAINS(var) FOR_ALL_VEHICLES_OF_TYPE(Train, var)
00523 
00524 #endif /* TRAIN_H */

Generated on Mon Aug 30 19:37:02 2010 for OpenTTD by  doxygen 1.6.1