ground_vehicle.hpp

Go to the documentation of this file.
00001 /* $Id: ground_vehicle.hpp 21862 2011-01-19 20:04:09Z 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 GROUND_VEHICLE_HPP
00013 #define GROUND_VEHICLE_HPP
00014 
00015 #include "vehicle_base.h"
00016 #include "landscape.h"
00017 
00019 enum AccelStatus {
00020   AS_ACCEL, 
00021   AS_BRAKE  
00022 };
00023 
00028 struct GroundVehicleCache {
00029   /* Cached acceleration values, recalculated when the cargo on a vehicle changes (in addition to the conditions below) */
00030   uint32 cached_weight;           
00031   uint32 cached_slope_resistance; 
00032   uint32 cached_max_te;           
00033   uint16 cached_axle_resistance;  
00034 
00035   /* Cached acceleration values, recalculated on load and each time a vehicle is added to/removed from the consist. */
00036   uint16 cached_max_track_speed;  
00037   uint32 cached_power;            
00038   uint32 cached_air_drag;         
00039 
00040   /* Cached NewGRF values, recalculated on load and each time a vehicle is added to/removed from the consist. */
00041   uint16 cached_total_length;     
00042   EngineID first_engine;          
00043   uint8 cached_veh_length;        
00044 };
00045 
00047 enum GroundVehicleFlags {
00048   GVF_GOINGUP_BIT       = 0,
00049   GVF_GOINGDOWN_BIT     = 1,
00050 };
00051 
00073 template <class T, VehicleType Type>
00074 struct GroundVehicle : public SpecializedVehicle<T, Type> {
00075   GroundVehicleCache gcache; 
00076   uint16 gv_flags;           
00077 
00081   GroundVehicle() : SpecializedVehicle<T, Type>() {}
00082 
00083   void PowerChanged();
00084   void CargoChanged();
00085   int GetAcceleration() const;
00086 
00091   FORCEINLINE int32 GetSlopeResistance() const
00092   {
00093     int32 incl = 0;
00094 
00095     for (const T *u = T::From(this); u != NULL; u = u->Next()) {
00096       if (HasBit(u->gv_flags, GVF_GOINGUP_BIT)) {
00097         incl += u->gcache.cached_slope_resistance;
00098       } else if (HasBit(u->gv_flags, GVF_GOINGDOWN_BIT)) {
00099         incl -= u->gcache.cached_slope_resistance;
00100       }
00101     }
00102 
00103     return incl;
00104   }
00105 
00112   FORCEINLINE byte UpdateInclination(bool new_tile, bool turned)
00113   {
00114     byte old_z = this->z_pos;
00115 
00116     if (new_tile) {
00117       this->z_pos = GetSlopeZ(this->x_pos, this->y_pos);
00118       ClrBit(this->gv_flags, GVF_GOINGUP_BIT);
00119       ClrBit(this->gv_flags, GVF_GOINGDOWN_BIT);
00120 
00121       if (T::From(this)->TileMayHaveSlopedTrack()) {
00122         /* To check whether the current tile is sloped, and in which
00123          * direction it is sloped, we get the 'z' at the center of
00124          * the tile (middle_z) and the edge of the tile (old_z),
00125          * which we then can compare. */
00126         static const int HALF_TILE_SIZE = TILE_SIZE / 2;
00127         static const int INV_TILE_SIZE_MASK = ~(TILE_SIZE - 1);
00128 
00129         byte middle_z = GetSlopeZ((this->x_pos & INV_TILE_SIZE_MASK) | HALF_TILE_SIZE, (this->y_pos & INV_TILE_SIZE_MASK) | HALF_TILE_SIZE);
00130 
00131         if (middle_z != this->z_pos) {
00132           SetBit(this->gv_flags, (middle_z > old_z) ? GVF_GOINGUP_BIT : GVF_GOINGDOWN_BIT);
00133         }
00134       }
00135     } else {
00136       /* Flat tile, tile with two opposing corners raised and tile with 3 corners
00137        * raised can never have sloped track ... */
00138       static const uint32 never_sloped = 1 << SLOPE_FLAT | 1 << SLOPE_EW | 1 << SLOPE_NS | 1 << SLOPE_NWS | 1 << SLOPE_WSE | 1 << SLOPE_SEN | 1 << SLOPE_ENW;
00139       /* ... unless it's a bridge head. */
00140       if (IsTileType(this->tile, MP_TUNNELBRIDGE) || // the following check would be true for tunnels anyway
00141           (T::From(this)->TileMayHaveSlopedTrack() && !HasBit(never_sloped, GetTileSlope(this->tile, NULL)))) {
00142         this->z_pos = GetSlopeZ(this->x_pos, this->y_pos);
00143       } else {
00144         /* Verify that assumption. */
00145         assert(this->z_pos == GetSlopeZ(this->x_pos, this->y_pos));
00146       }
00147     }
00148 
00149     this->UpdateViewport(true, turned);
00150     return old_z;
00151   }
00152 
00157   enum GroundVehicleSubtypeFlags {
00158     GVSF_FRONT            = 0, 
00159     GVSF_ARTICULATED_PART = 1, 
00160     GVSF_WAGON            = 2, 
00161     GVSF_ENGINE           = 3, 
00162     GVSF_FREE_WAGON       = 4, 
00163     GVSF_MULTIHEADED      = 5, 
00164   };
00165 
00169   FORCEINLINE void SetFrontEngine() { SetBit(this->subtype, GVSF_FRONT); }
00170 
00174   FORCEINLINE void ClearFrontEngine() { ClrBit(this->subtype, GVSF_FRONT); }
00175 
00179   FORCEINLINE void SetArticulatedPart() { SetBit(this->subtype, GVSF_ARTICULATED_PART); }
00180 
00184   FORCEINLINE void ClearArticulatedPart() { ClrBit(this->subtype, GVSF_ARTICULATED_PART); }
00185 
00189   FORCEINLINE void SetWagon() { SetBit(this->subtype, GVSF_WAGON); }
00190 
00194   FORCEINLINE void ClearWagon() { ClrBit(this->subtype, GVSF_WAGON); }
00195 
00199   FORCEINLINE void SetEngine() { SetBit(this->subtype, GVSF_ENGINE); }
00200 
00204   FORCEINLINE void ClearEngine() { ClrBit(this->subtype, GVSF_ENGINE); }
00205 
00209   FORCEINLINE void SetFreeWagon() { SetBit(this->subtype, GVSF_FREE_WAGON); }
00210 
00214   FORCEINLINE void ClearFreeWagon() { ClrBit(this->subtype, GVSF_FREE_WAGON); }
00215 
00219   FORCEINLINE void SetMultiheaded() { SetBit(this->subtype, GVSF_MULTIHEADED); }
00220 
00224   FORCEINLINE void ClearMultiheaded() { ClrBit(this->subtype, GVSF_MULTIHEADED); }
00225 
00230   FORCEINLINE bool IsFrontEngine() const { return HasBit(this->subtype, GVSF_FRONT); }
00231 
00236   FORCEINLINE bool IsFreeWagon() const { return HasBit(this->subtype, GVSF_FREE_WAGON); }
00237 
00242   FORCEINLINE bool IsEngine() const { return HasBit(this->subtype, GVSF_ENGINE); }
00243 
00248   FORCEINLINE bool IsWagon() const { return HasBit(this->subtype, GVSF_WAGON); }
00249 
00254   FORCEINLINE bool IsMultiheaded() const { return HasBit(this->subtype, GVSF_MULTIHEADED); }
00255 
00260   FORCEINLINE bool IsRearDualheaded() const { return this->IsMultiheaded() && !this->IsEngine(); }
00261 
00266   FORCEINLINE bool IsArticulatedPart() const { return HasBit(this->subtype, GVSF_ARTICULATED_PART); }
00267 
00272   FORCEINLINE bool HasArticulatedPart() const { return this->Next() != NULL && this->Next()->IsArticulatedPart(); }
00273 };
00274 
00275 #endif /* GROUND_VEHICLE_HPP */

Generated on Thu Jan 20 22:57:34 2011 for OpenTTD by  doxygen 1.6.1