ground_vehicle.hpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
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
00030 uint32 cached_weight;
00031 uint32 cached_slope_resistance;
00032 uint32 cached_max_te;
00033 uint16 cached_axle_resistance;
00034
00035
00036 uint16 cached_max_track_speed;
00037 uint32 cached_power;
00038 uint32 cached_air_drag;
00039
00040
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
00123
00124
00125
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
00137
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
00140 if (IsTileType(this->tile, MP_TUNNELBRIDGE) ||
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
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