OpenTTD Source  1.11.2
ground_vehicle.hpp
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * 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.
4  * 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.
5  * 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/>.
6  */
7 
10 #ifndef GROUND_VEHICLE_HPP
11 #define GROUND_VEHICLE_HPP
12 
13 #include "vehicle_base.h"
14 #include "vehicle_gui.h"
15 #include "landscape.h"
16 #include "window_func.h"
17 #include "widgets/vehicle_widget.h"
18 
23 };
24 
30  /* Cached acceleration values, recalculated when the cargo on a vehicle changes (in addition to the conditions below) */
31  uint32 cached_weight;
33  uint32 cached_max_te;
35 
36  /* Cached acceleration values, recalculated on load and each time a vehicle is added to/removed from the consist. */
38  uint32 cached_power;
39  uint32 cached_air_drag;
40 
41  /* Cached NewGRF values, recalculated on load and each time a vehicle is added to/removed from the consist. */
45 
46  /* Cached UI information. */
47  uint16 last_speed;
48 };
49 
55 };
56 
78 template <class T, VehicleType Type>
79 struct GroundVehicle : public SpecializedVehicle<T, Type> {
81  uint16 gv_flags;
82 
84 
89 
90  void PowerChanged();
91  void CargoChanged();
92  int GetAcceleration() const;
93  bool IsChainInDepot() const override;
94 
100  uint Crash(bool flooded) override
101  {
102  /* Crashed vehicles aren't going up or down */
103  for (T *v = T::From(this); v != nullptr; v = v->Next()) {
104  ClrBit(v->gv_flags, GVF_GOINGUP_BIT);
105  ClrBit(v->gv_flags, GVF_GOINGDOWN_BIT);
106  }
107  return this->Vehicle::Crash(flooded);
108  }
109 
114  inline int64 GetSlopeResistance() const
115  {
116  int64 incl = 0;
117 
118  for (const T *u = T::From(this); u != nullptr; u = u->Next()) {
119  if (HasBit(u->gv_flags, GVF_GOINGUP_BIT)) {
120  incl += u->gcache.cached_slope_resistance;
121  } else if (HasBit(u->gv_flags, GVF_GOINGDOWN_BIT)) {
122  incl -= u->gcache.cached_slope_resistance;
123  }
124  }
125 
126  return incl;
127  }
128 
136  {
137  this->z_pos = GetSlopePixelZ(this->x_pos, this->y_pos);
138  ClrBit(this->gv_flags, GVF_GOINGUP_BIT);
139  ClrBit(this->gv_flags, GVF_GOINGDOWN_BIT);
140 
141  if (T::From(this)->TileMayHaveSlopedTrack()) {
142  /* To check whether the current tile is sloped, and in which
143  * direction it is sloped, we get the 'z' at the center of
144  * the tile (middle_z) and the edge of the tile (old_z),
145  * which we then can compare. */
146  int middle_z = GetSlopePixelZ((this->x_pos & ~TILE_UNIT_MASK) | (TILE_SIZE / 2), (this->y_pos & ~TILE_UNIT_MASK) | (TILE_SIZE / 2));
147 
148  if (middle_z != this->z_pos) {
149  SetBit(this->gv_flags, (middle_z > this->z_pos) ? GVF_GOINGUP_BIT : GVF_GOINGDOWN_BIT);
150  }
151  }
152  }
153 
160  inline void UpdateZPosition()
161  {
162 #if 0
163  /* The following code does this: */
164 
165  if (HasBit(this->gv_flags, GVF_GOINGUP_BIT)) {
166  switch (this->direction) {
167  case DIR_NE:
168  this->z_pos += (this->x_pos & 1); break;
169  case DIR_SW:
170  this->z_pos += (this->x_pos & 1) ^ 1; break;
171  case DIR_NW:
172  this->z_pos += (this->y_pos & 1); break;
173  case DIR_SE:
174  this->z_pos += (this->y_pos & 1) ^ 1; break;
175  default: break;
176  }
177  } else if (HasBit(this->gv_flags, GVF_GOINGDOWN_BIT)) {
178  switch (this->direction) {
179  case DIR_NE:
180  this->z_pos -= (this->x_pos & 1); break;
181  case DIR_SW:
182  this->z_pos -= (this->x_pos & 1) ^ 1; break;
183  case DIR_NW:
184  this->z_pos -= (this->y_pos & 1); break;
185  case DIR_SE:
186  this->z_pos -= (this->y_pos & 1) ^ 1; break;
187  default: break;
188  }
189  }
190 
191  /* But gcc 4.4.5 isn't able to nicely optimise it, and the resulting
192  * code is full of conditional jumps. */
193 #endif
194 
195  /* Vehicle's Z position can change only if it has GVF_GOINGUP_BIT or GVF_GOINGDOWN_BIT set.
196  * Furthermore, if this function is called once every time the vehicle's position changes,
197  * we know the Z position changes by +/-1 at certain moments - when x_pos, y_pos is odd/even,
198  * depending on orientation of the slope and vehicle's direction */
199 
200  if (HasBit(this->gv_flags, GVF_GOINGUP_BIT) || HasBit(this->gv_flags, GVF_GOINGDOWN_BIT)) {
201  if (T::From(this)->HasToUseGetSlopePixelZ()) {
202  /* In some cases, we have to use GetSlopePixelZ() */
203  this->z_pos = GetSlopePixelZ(this->x_pos, this->y_pos);
204  return;
205  }
206  /* DirToDiagDir() is a simple right shift */
207  DiagDirection dir = DirToDiagDir(this->direction);
208  /* Read variables, so the compiler knows the access doesn't trap */
209  int8 x_pos = this->x_pos;
210  int8 y_pos = this->y_pos;
211  /* DiagDirToAxis() is a simple mask */
212  int8 d = DiagDirToAxis(dir) == AXIS_X ? x_pos : y_pos;
213  /* We need only the least significant bit */
214  d &= 1;
215  /* Conditional "^ 1". Optimised to "(dir - 1) <= 1". */
216  d ^= (int8)(dir == DIAGDIR_SW || dir == DIAGDIR_SE);
217  /* Subtraction instead of addition because we are testing for GVF_GOINGUP_BIT.
218  * GVF_GOINGUP_BIT is used because it's bit 0, so simple AND can be used,
219  * without any shift */
220  this->z_pos += HasBit(this->gv_flags, GVF_GOINGUP_BIT) ? d : -d;
221  }
222 
223  assert(this->z_pos == GetSlopePixelZ(this->x_pos, this->y_pos));
224  }
225 
232  inline int UpdateInclination(bool new_tile, bool update_delta)
233  {
234  int old_z = this->z_pos;
235 
236  if (new_tile) {
238  } else {
239  this->UpdateZPosition();
240  }
241 
242  this->UpdateViewport(true, update_delta);
243  return old_z;
244  }
245 
249  inline void SetFrontEngine() { SetBit(this->subtype, GVSF_FRONT); }
250 
254  inline void ClearFrontEngine() { ClrBit(this->subtype, GVSF_FRONT); }
255 
260 
265 
269  inline void SetWagon() { SetBit(this->subtype, GVSF_WAGON); }
270 
274  inline void ClearWagon() { ClrBit(this->subtype, GVSF_WAGON); }
275 
279  inline void SetEngine() { SetBit(this->subtype, GVSF_ENGINE); }
280 
284  inline void ClearEngine() { ClrBit(this->subtype, GVSF_ENGINE); }
285 
289  inline void SetFreeWagon() { SetBit(this->subtype, GVSF_FREE_WAGON); }
290 
294  inline void ClearFreeWagon() { ClrBit(this->subtype, GVSF_FREE_WAGON); }
295 
299  inline void SetMultiheaded() { SetBit(this->subtype, GVSF_MULTIHEADED); }
300 
304  inline void ClearMultiheaded() { ClrBit(this->subtype, GVSF_MULTIHEADED); }
305 
310  inline bool IsFreeWagon() const { return HasBit(this->subtype, GVSF_FREE_WAGON); }
311 
316  inline bool IsEngine() const { return HasBit(this->subtype, GVSF_ENGINE); }
317 
322  inline bool IsWagon() const { return HasBit(this->subtype, GVSF_WAGON); }
323 
328  inline bool IsMultiheaded() const { return HasBit(this->subtype, GVSF_MULTIHEADED); }
329 
334  inline bool IsRearDualheaded() const { return this->IsMultiheaded() && !this->IsEngine(); }
335 
341  inline void SetLastSpeed()
342  {
343  if (this->cur_speed != this->gcache.last_speed) {
345  this->gcache.last_speed = this->cur_speed;
346  }
347  }
348 
349 protected:
363  inline uint DoUpdateSpeed(uint accel, int min_speed, int max_speed)
364  {
365  uint spd = this->subspeed + accel;
366  this->subspeed = (byte)spd;
367 
368  /* When we are going faster than the maximum speed, reduce the speed
369  * somewhat gradually. But never lower than the maximum speed. */
370  int tempmax = max_speed;
371  if (this->cur_speed > max_speed) {
372  tempmax = std::max(this->cur_speed - (this->cur_speed / 10) - 1, max_speed);
373  }
374 
375  /* Enforce a maximum and minimum speed. Normally we would use something like
376  * Clamp for this, but in this case min_speed might be below the maximum speed
377  * threshold for some reason. That makes acceleration fail and assertions
378  * happen in Clamp. So make it explicit that min_speed overrules the maximum
379  * speed by explicit ordering of min and max. */
380  this->cur_speed = spd = std::max(std::min(this->cur_speed + ((int)spd >> 8), tempmax), min_speed);
381 
382  int scaled_spd = this->GetAdvanceSpeed(spd);
383 
384  scaled_spd += this->progress;
385  this->progress = 0; // set later in *Handler or *Controller
386  return scaled_spd;
387  }
388 };
389 
390 #endif /* GROUND_VEHICLE_HPP */
GVSF_ENGINE
@ GVSF_ENGINE
Engine that can be front engine, but might be placed behind another engine (not used for road vehicle...
Definition: vehicle_base.h:114
GroundVehicleCache::cached_air_drag
uint32 cached_air_drag
Air drag coefficient of the vehicle (valid only for the first engine).
Definition: ground_vehicle.hpp:39
DIAGDIR_SE
@ DIAGDIR_SE
Southeast.
Definition: direction_type.h:80
DIR_SW
@ DIR_SW
Southwest.
Definition: direction_type.h:31
GroundVehicle::GroundVehicle
GroundVehicle()
The constructor at SpecializedVehicle must be called.
Definition: ground_vehicle.hpp:88
vehicle_gui.h
Vehicle::y_pos
int32 y_pos
y coordinate.
Definition: vehicle_base.h:279
Vehicle::x_pos
int32 x_pos
x coordinate.
Definition: vehicle_base.h:278
GroundVehicle::GetAcceleration
int GetAcceleration() const
Calculates the acceleration of the vehicle under its current conditions.
Definition: ground_vehicle.cpp:105
DIR_SE
@ DIR_SE
Southeast.
Definition: direction_type.h:29
vehicle_widget.h
GVF_SUPPRESS_IMPLICIT_ORDERS
@ GVF_SUPPRESS_IMPLICIT_ORDERS
Disable insertion and removal of automatic orders until the vehicle completes the real order.
Definition: ground_vehicle.hpp:54
GroundVehicleCache::first_engine
EngineID first_engine
Cached EngineID of the front vehicle. INVALID_ENGINE for the front vehicle itself.
Definition: ground_vehicle.hpp:43
GroundVehicle::ClearFreeWagon
void ClearFreeWagon()
Clear a vehicle from being a free wagon.
Definition: ground_vehicle.hpp:294
Vehicle::z_pos
int32 z_pos
z coordinate.
Definition: vehicle_base.h:280
DIR_NW
@ DIR_NW
Northwest.
Definition: direction_type.h:33
DiagDirToAxis
static Axis DiagDirToAxis(DiagDirection d)
Convert a DiagDirection to the axis.
Definition: direction_func.h:214
GroundVehicle::ClearFrontEngine
void ClearFrontEngine()
Remove the front engine state.
Definition: ground_vehicle.hpp:254
Pool::PoolItem<&_vehicle_pool >::index
Tindex index
Index of this pool item.
Definition: pool_type.hpp:227
Vehicle::Crash
virtual uint Crash(bool flooded=false)
Crash the (whole) vehicle chain.
Definition: vehicle.cpp:260
HasBit
static bool HasBit(const T x, const uint8 y)
Checks if a bit in a value is set.
Definition: bitmath_func.hpp:103
ClrBit
static T ClrBit(T &x, const uint8 y)
Clears a bit in a variable.
Definition: bitmath_func.hpp:151
GroundVehicle::GroundVehicleBase
GroundVehicle< T, Type > GroundVehicleBase
Our type.
Definition: ground_vehicle.hpp:83
vehicle_base.h
TILE_SIZE
static const uint TILE_SIZE
Tile size in world coordinates.
Definition: tile_type.h:13
GroundVehicleCache::last_speed
uint16 last_speed
The last speed we did display, so we only have to redraw when this changes.
Definition: ground_vehicle.hpp:47
AS_ACCEL
@ AS_ACCEL
We want to go faster, if possible of course.
Definition: ground_vehicle.hpp:21
GroundVehicle::IsRearDualheaded
bool IsRearDualheaded() const
Tell if we are dealing with the rear end of a multiheaded engine.
Definition: ground_vehicle.hpp:334
Vehicle::cur_speed
uint16 cur_speed
current speed
Definition: vehicle_base.h:302
GroundVehicle::UpdateZPositionAndInclination
void UpdateZPositionAndInclination()
Updates vehicle's Z position and inclination.
Definition: ground_vehicle.hpp:135
GroundVehicle::SetWagon
void SetWagon()
Set a vehicle to be a wagon.
Definition: ground_vehicle.hpp:269
GroundVehicle::ClearEngine
void ClearEngine()
Clear engine status.
Definition: ground_vehicle.hpp:284
GVF_GOINGDOWN_BIT
@ GVF_GOINGDOWN_BIT
Vehicle is currently going downhill. (Cached track information for acceleration)
Definition: ground_vehicle.hpp:53
SetWindowWidgetDirty
void SetWindowWidgetDirty(WindowClass cls, WindowNumber number, byte widget_index)
Mark a particular widget in a particular window as dirty (in need of repainting)
Definition: window.cpp:3234
DIAGDIR_SW
@ DIAGDIR_SW
Southwest.
Definition: direction_type.h:81
EngineID
uint16 EngineID
Unique identification number of an engine.
Definition: engine_type.h:21
TILE_UNIT_MASK
static const uint TILE_UNIT_MASK
For masking in/out the inner-tile world coordinate units.
Definition: tile_type.h:14
GroundVehicleCache::cached_total_length
uint16 cached_total_length
Length of the whole vehicle (valid only for the first engine).
Definition: ground_vehicle.hpp:42
DirToDiagDir
static DiagDirection DirToDiagDir(Direction dir)
Convert a Direction to a DiagDirection.
Definition: direction_func.h:166
GroundVehicleCache
Cached, frequently calculated values.
Definition: ground_vehicle.hpp:29
GroundVehicleFlags
GroundVehicleFlags
Ground vehicle flags.
Definition: ground_vehicle.hpp:51
WC_VEHICLE_VIEW
@ WC_VEHICLE_VIEW
Vehicle view; Window numbers:
Definition: window_type.h:332
GroundVehicle::GetSlopeResistance
int64 GetSlopeResistance() const
Calculates the total slope resistance for this vehicle.
Definition: ground_vehicle.hpp:114
GroundVehicle::SetMultiheaded
void SetMultiheaded()
Set a vehicle as a multiheaded engine.
Definition: ground_vehicle.hpp:299
GroundVehicleCache::cached_axle_resistance
uint16 cached_axle_resistance
Resistance caused by the axles of the vehicle (valid only for the first engine).
Definition: ground_vehicle.hpp:34
GVF_GOINGUP_BIT
@ GVF_GOINGUP_BIT
Vehicle is currently going uphill. (Cached track information for acceleration)
Definition: ground_vehicle.hpp:52
GroundVehicleCache::cached_veh_length
uint8 cached_veh_length
Length of this vehicle in units of 1/VEHICLE_LENGTH of normal length. It is cached because this can b...
Definition: ground_vehicle.hpp:44
SpecializedVehicle
Class defining several overloaded accessors so we don't have to cast vehicle types that often.
Definition: vehicle_base.h:1042
GVSF_ARTICULATED_PART
@ GVSF_ARTICULATED_PART
Articulated part of an engine.
Definition: vehicle_base.h:112
GroundVehicleCache::cached_max_track_speed
uint16 cached_max_track_speed
Maximum consist speed (in internal units) limited by track type (valid only for the first engine).
Definition: ground_vehicle.hpp:37
GroundVehicle::IsChainInDepot
bool IsChainInDepot() const override
Check whether the whole vehicle chain is in the depot.
Definition: ground_vehicle.cpp:190
GroundVehicle::gcache
GroundVehicleCache gcache
Cache of often calculated values.
Definition: ground_vehicle.hpp:80
DIR_NE
@ DIR_NE
Northeast.
Definition: direction_type.h:27
GroundVehicle::SetFrontEngine
void SetFrontEngine()
Set front engine state.
Definition: ground_vehicle.hpp:249
GroundVehicleCache::cached_slope_resistance
uint32 cached_slope_resistance
Resistance caused by weight when this vehicle part is at a slope.
Definition: ground_vehicle.hpp:32
GroundVehicle::SetLastSpeed
void SetLastSpeed()
Update the GUI variant of the current speed of the vehicle.
Definition: ground_vehicle.hpp:341
GroundVehicleCache::cached_max_te
uint32 cached_max_te
Maximum tractive effort of consist (valid only for the first engine).
Definition: ground_vehicle.hpp:33
GVSF_WAGON
@ GVSF_WAGON
Wagon (not used for road vehicles).
Definition: vehicle_base.h:113
DiagDirection
DiagDirection
Enumeration for diagonal directions.
Definition: direction_type.h:77
WID_VV_START_STOP
@ WID_VV_START_STOP
Start or stop this vehicle, and show information about the current state.
Definition: vehicle_widget.h:17
landscape.h
Vehicle::direction
Direction direction
facing
Definition: vehicle_base.h:281
GroundVehicle::UpdateInclination
int UpdateInclination(bool new_tile, bool update_delta)
Checks if the vehicle is in a slope and sets the required flags in that case.
Definition: ground_vehicle.hpp:232
GVSF_FREE_WAGON
@ GVSF_FREE_WAGON
First in a wagon chain (in depot) (not used for road vehicles).
Definition: vehicle_base.h:115
GroundVehicleCache::cached_power
uint32 cached_power
Total power of the consist (valid only for the first engine).
Definition: ground_vehicle.hpp:38
Vehicle::subspeed
byte subspeed
fractional speed
Definition: vehicle_base.h:303
Vehicle::GetAdvanceSpeed
static uint GetAdvanceSpeed(uint speed)
Determines the effective vehicle movement speed.
Definition: vehicle_base.h:413
GroundVehicle::ClearMultiheaded
void ClearMultiheaded()
Clear multiheaded engine property.
Definition: ground_vehicle.hpp:304
GroundVehicle::SetArticulatedPart
void SetArticulatedPart()
Set a vehicle to be an articulated part.
Definition: ground_vehicle.hpp:259
GroundVehicle::SetEngine
void SetEngine()
Set engine status.
Definition: ground_vehicle.hpp:279
GroundVehicle::PowerChanged
void PowerChanged()
Recalculates the cached total power of a vehicle.
Definition: ground_vehicle.cpp:21
GroundVehicle::IsEngine
bool IsEngine() const
Check if a vehicle is an engine (can be first in a consist).
Definition: ground_vehicle.hpp:316
GroundVehicle::SetFreeWagon
void SetFreeWagon()
Set a vehicle as a free wagon.
Definition: ground_vehicle.hpp:289
GroundVehicle
Base class for all vehicles that move through ground.
Definition: ground_vehicle.hpp:79
GVSF_MULTIHEADED
@ GVSF_MULTIHEADED
Engine is multiheaded (not used for road vehicles).
Definition: vehicle_base.h:116
GroundVehicle::gv_flags
uint16 gv_flags
Definition: ground_vehicle.hpp:81
GroundVehicle::ClearWagon
void ClearWagon()
Clear wagon property.
Definition: ground_vehicle.hpp:274
Vehicle::subtype
byte subtype
subtype (Filled with values from AircraftSubType/DisasterSubType/EffectVehicleType/GroundVehicleSubty...
Definition: vehicle_base.h:336
GVSF_FRONT
@ GVSF_FRONT
Leading engine of a consist.
Definition: vehicle_base.h:111
window_func.h
SetBit
static T SetBit(T &x, const uint8 y)
Set a bit in a variable.
Definition: bitmath_func.hpp:121
Vehicle::progress
byte progress
The percentage (if divided by 256) this vehicle already crossed the tile unit.
Definition: vehicle_base.h:306
GroundVehicle::CargoChanged
void CargoChanged()
Recalculates the cached weight of a vehicle and its parts.
Definition: ground_vehicle.cpp:79
GroundVehicle::IsWagon
bool IsWagon() const
Check if a vehicle is a wagon.
Definition: ground_vehicle.hpp:322
GroundVehicle::IsFreeWagon
bool IsFreeWagon() const
Check if the vehicle is a free wagon (got no engine in front of it).
Definition: ground_vehicle.hpp:310
AS_BRAKE
@ AS_BRAKE
We want to stop.
Definition: ground_vehicle.hpp:22
GroundVehicle::UpdateZPosition
void UpdateZPosition()
Updates vehicle's Z position.
Definition: ground_vehicle.hpp:160
GroundVehicle::Crash
uint Crash(bool flooded) override
Common code executed for crashed ground vehicles.
Definition: ground_vehicle.hpp:100
GroundVehicle::DoUpdateSpeed
uint DoUpdateSpeed(uint accel, int min_speed, int max_speed)
Update the speed of the vehicle.
Definition: ground_vehicle.hpp:363
SpecializedVehicle::UpdateViewport
void UpdateViewport(bool force_update, bool update_delta)
Update vehicle sprite- and position caches.
Definition: vehicle_base.h:1184
GroundVehicleCache::cached_weight
uint32 cached_weight
Total weight of the consist (valid only for the first engine).
Definition: ground_vehicle.hpp:31
AccelStatus
AccelStatus
What is the status of our acceleration?
Definition: ground_vehicle.hpp:20
GroundVehicle::ClearArticulatedPart
void ClearArticulatedPart()
Clear a vehicle from being an articulated part.
Definition: ground_vehicle.hpp:264
GroundVehicle::IsMultiheaded
bool IsMultiheaded() const
Check if the vehicle is a multiheaded engine.
Definition: ground_vehicle.hpp:328
AXIS_X
@ AXIS_X
The X axis.
Definition: direction_type.h:124