Also scroll tile separators in the train depot
[openttd/fttd.git] / src / ground_vehicle.hpp
bloba8094564f30afcc770c22da14a64489cb57d5493
1 /* $Id$ */
3 /*
4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
8 */
10 /** @file ground_vehicle.hpp Base class and functions for all vehicles that move through ground. */
12 #ifndef GROUND_VEHICLE_HPP
13 #define GROUND_VEHICLE_HPP
15 #include "vehicle_base.h"
16 #include "vehicle_gui.h"
17 #include "landscape.h"
18 #include "window_func.h"
19 #include "widgets/vehicle_widget.h"
21 /** What is the status of our acceleration? */
22 enum AccelStatus {
23 AS_ACCEL, ///< We want to go faster, if possible of course.
24 AS_BRAKE, ///< We want to stop.
27 /**
28 * Cached, frequently calculated values.
29 * All of these values except cached_slope_resistance are set only for the first part of a vehicle.
31 struct GroundVehicleCache {
32 /* Cached acceleration values, recalculated when the cargo on a vehicle changes (in addition to the conditions below) */
33 uint32 cached_weight; ///< Total weight of the consist (valid only for the first engine).
34 uint32 cached_slope_resistance; ///< Resistance caused by weight when this vehicle part is at a slope.
35 uint32 cached_max_te; ///< Maximum tractive effort of consist (valid only for the first engine).
36 uint16 cached_axle_resistance; ///< Resistance caused by the axles of the vehicle (valid only for the first engine).
38 /* Cached acceleration values, recalculated on load and each time a vehicle is added to/removed from the consist. */
39 uint16 cached_max_track_speed; ///< Maximum consist speed limited by track type (valid only for the first engine).
40 uint32 cached_power; ///< Total power of the consist (valid only for the first engine).
41 uint32 cached_air_drag; ///< Air drag coefficient of the vehicle (valid only for the first engine).
43 /* Cached NewGRF values, recalculated on load and each time a vehicle is added to/removed from the consist. */
44 uint16 cached_total_length; ///< Length of the whole vehicle (valid only for the first engine).
45 EngineID first_engine; ///< Cached EngineID of the front vehicle. INVALID_ENGINE for the front vehicle itself.
46 uint8 cached_veh_length; ///< Length of this vehicle in units of 1/VEHICLE_LENGTH of normal length. It is cached because this can be set by a callback.
48 /* Cached UI information. */
49 uint16 last_speed; ///< The last speed we did display, so we only have to redraw when this changes.
52 /** Ground vehicle flags. */
53 enum GroundVehicleFlags {
54 GVF_GOINGUP_BIT = 0, ///< Vehicle is currently going uphill. (Cached track information for acceleration)
55 GVF_GOINGDOWN_BIT = 1, ///< Vehicle is currently going downhill. (Cached track information for acceleration)
56 GVF_SUPPRESS_IMPLICIT_ORDERS = 2, ///< Disable insertion and removal of automatic orders until the vehicle completes the real order.
59 /** Base class for all vehicles that move through ground. */
60 struct GroundVehicleBase : public VehicleAdapter <GroundVehicleBase, Vehicle> {
61 GroundVehicleCache gcache; ///< Cache of often calculated values.
62 uint16 gv_flags; ///< @see GroundVehicleFlags.
64 /** Constructor. */
65 GroundVehicleBase (VehicleType type)
66 : VehicleAdapter <GroundVehicleBase, Vehicle> (type)
70 /**
71 * Converts a Vehicle to a GroundVehicleBase with type checking.
72 * @param v Vehicle pointer
73 * @return pointer to GroundVehicleBase
75 static GroundVehicleBase *From (Vehicle *v)
77 assert (v->IsGroundVehicle());
78 return static_cast <GroundVehicleBase *> (v);
81 /**
82 * Converts a const Vehicle to const GroundVehicleBase with type checking.
83 * @param v Vehicle pointer
84 * @return pointer to GroundVehicleBase
86 static const GroundVehicleBase *From (const Vehicle *v)
88 assert (v->IsGroundVehicle());
89 return static_cast <const GroundVehicleBase *> (v);
92 /**
93 * Common code executed for crashed ground vehicles
94 * @param flooded was this vehicle flooded?
95 * @return number of victims
97 uint Crash (bool flooded) OVERRIDE
99 /* Crashed vehicles aren't going up or down */
100 for (GroundVehicleBase *v = this; v != NULL; v = v->Next()) {
101 ClrBit(v->gv_flags, GVF_GOINGUP_BIT);
102 ClrBit(v->gv_flags, GVF_GOINGDOWN_BIT);
104 return this->Vehicle::Crash (flooded);
108 * Calculates the total slope resistance for this vehicle.
109 * @return Slope resistance.
111 int64 GetSlopeResistance (void) const
113 int64 incl = 0;
115 for (const GroundVehicleBase *u = this; u != NULL; u = u->Next()) {
116 if (HasBit(u->gv_flags, GVF_GOINGUP_BIT)) {
117 incl += u->gcache.cached_slope_resistance;
118 } else if (HasBit(u->gv_flags, GVF_GOINGDOWN_BIT)) {
119 incl -= u->gcache.cached_slope_resistance;
123 return incl;
127 * Reset the Z position of a vehicle when entering a new tile,
128 * and clear inclination flags.
130 void ResetZPosition (void)
132 this->z_pos = GetSlopePixelZ (this->x_pos, this->y_pos);
133 ClrBit(this->gv_flags, GVF_GOINGUP_BIT);
134 ClrBit(this->gv_flags, GVF_GOINGDOWN_BIT);
137 /** Update the inclination when entering a new tile. */
138 void UpdateInclination (void)
140 /* To check whether the current tile is sloped, and in which
141 * direction it is sloped, we get the 'z' at the center of
142 * the tile (middle_z) and the edge of the tile (old_z),
143 * which we then can compare. */
144 int middle_z = GetSlopePixelZ((this->x_pos & ~TILE_UNIT_MASK) | (TILE_SIZE / 2), (this->y_pos & ~TILE_UNIT_MASK) | (TILE_SIZE / 2));
146 if (middle_z != this->z_pos) {
147 SetBit(this->gv_flags, (middle_z > this->z_pos) ? GVF_GOINGUP_BIT : GVF_GOINGDOWN_BIT);
152 * Updates vehicle's Z position.
153 * Inclination can't change in the middle of a tile.
154 * The faster code is used for trains and road vehicles unless they are
155 * reversing on a sloped tile.
157 inline void UpdateZPosition()
159 #if 0
160 /* The following code does this: */
162 if (HasBit(this->gv_flags, GVF_GOINGUP_BIT)) {
163 switch (this->direction) {
164 case DIR_NE:
165 this->z_pos += (this->x_pos & 1); break;
166 case DIR_SW:
167 this->z_pos += (this->x_pos & 1) ^ 1; break;
168 case DIR_NW:
169 this->z_pos += (this->y_pos & 1); break;
170 case DIR_SE:
171 this->z_pos += (this->y_pos & 1) ^ 1; break;
172 default: break;
174 } else {
175 switch (this->direction) {
176 case DIR_NE:
177 this->z_pos -= (this->x_pos & 1); break;
178 case DIR_SW:
179 this->z_pos -= (this->x_pos & 1) ^ 1; break;
180 case DIR_NW:
181 this->z_pos -= (this->y_pos & 1); break;
182 case DIR_SE:
183 this->z_pos -= (this->y_pos & 1) ^ 1; break;
184 default: break;
188 /* But gcc 4.4.5 isn't able to nicely optimise it, and the resulting
189 * code is full of conditional jumps. */
190 #endif
192 /* Vehicle's Z position can change only if it has GVF_GOINGUP_BIT or GVF_GOINGDOWN_BIT set.
193 * Furthermore, if this function is called once every time the vehicle's position changes,
194 * we know the Z position changes by +/-1 at certain moments - when x_pos, y_pos is odd/even,
195 * depending on orientation of the slope and vehicle's direction */
197 /* DirToDiagDir() is a simple right shift */
198 DiagDirection dir = DirToDiagDir(this->direction);
199 /* Read variables, so the compiler knows the access doesn't trap */
200 int8 x_pos = this->x_pos;
201 int8 y_pos = this->y_pos;
202 /* DiagDirToAxis() is a simple mask */
203 int8 d = DiagDirToAxis(dir) == AXIS_X ? x_pos : y_pos;
204 /* We need only the least significant bit */
205 d &= 1;
206 /* Conditional "^ 1". Optimised to "(dir - 1) <= 1". */
207 d ^= (int8)(dir == DIAGDIR_SW || dir == DIAGDIR_SE);
208 /* Subtraction instead of addition because we are testing for GVF_GOINGUP_BIT.
209 * GVF_GOINGUP_BIT is used because it's bit 0, so simple AND can be used,
210 * without any shift */
211 this->z_pos += HasBit(this->gv_flags, GVF_GOINGUP_BIT) ? d : -d;
215 * Set front engine state.
217 inline void SetFrontEngine() { SetBit(this->subtype, GVSF_FRONT); }
220 * Remove the front engine state.
222 inline void ClearFrontEngine() { ClrBit(this->subtype, GVSF_FRONT); }
225 * Set a vehicle to be an articulated part.
227 inline void SetArticulatedPart() { SetBit(this->subtype, GVSF_ARTICULATED_PART); }
230 * Clear a vehicle from being an articulated part.
232 inline void ClearArticulatedPart() { ClrBit(this->subtype, GVSF_ARTICULATED_PART); }
235 * Set a vehicle to be a wagon.
237 inline void SetWagon() { SetBit(this->subtype, GVSF_WAGON); }
240 * Clear wagon property.
242 inline void ClearWagon() { ClrBit(this->subtype, GVSF_WAGON); }
245 * Set engine status.
247 inline void SetEngine() { SetBit(this->subtype, GVSF_ENGINE); }
250 * Clear engine status.
252 inline void ClearEngine() { ClrBit(this->subtype, GVSF_ENGINE); }
255 * Set a vehicle as a free wagon.
257 inline void SetFreeWagon() { SetBit(this->subtype, GVSF_FREE_WAGON); }
260 * Clear a vehicle from being a free wagon.
262 inline void ClearFreeWagon() { ClrBit(this->subtype, GVSF_FREE_WAGON); }
265 * Set a vehicle as a multiheaded engine.
267 inline void SetMultiheaded() { SetBit(this->subtype, GVSF_MULTIHEADED); }
270 * Clear multiheaded engine property.
272 inline void ClearMultiheaded() { ClrBit(this->subtype, GVSF_MULTIHEADED); }
275 * Check if the vehicle is a free wagon (got no engine in front of it).
276 * @return Returns true if the vehicle is a free wagon.
278 inline bool IsFreeWagon() const { return HasBit(this->subtype, GVSF_FREE_WAGON); }
281 * Check if a vehicle is an engine (can be first in a consist).
282 * @return Returns true if vehicle is an engine.
284 inline bool IsEngine() const { return HasBit(this->subtype, GVSF_ENGINE); }
287 * Check if a vehicle is a wagon.
288 * @return Returns true if vehicle is a wagon.
290 inline bool IsWagon() const { return HasBit(this->subtype, GVSF_WAGON); }
293 * Check if the vehicle is a multiheaded engine.
294 * @return Returns true if the vehicle is a multiheaded engine.
296 inline bool IsMultiheaded() const { return HasBit(this->subtype, GVSF_MULTIHEADED); }
299 * Tell if we are dealing with the rear end of a multiheaded engine.
300 * @return True if the engine is the rear part of a dualheaded engine.
302 inline bool IsRearDualheaded() const { return this->IsMultiheaded() && !this->IsEngine(); }
305 * Update the GUI variant of the current speed of the vehicle.
306 * Also mark the widget dirty when that is needed, i.e. when
307 * the speed of this vehicle has changed.
309 inline void SetLastSpeed()
311 if (this->cur_speed != this->gcache.last_speed) {
312 SetWindowWidgetDirty(WC_VEHICLE_VIEW, this->index, WID_VV_START_STOP);
313 this->gcache.last_speed = this->cur_speed;
317 protected:
319 * Update the speed of the vehicle.
321 * It updates the cur_speed and subspeed variables depending on the state
322 * of the vehicle; in this case the current acceleration, minimum and
323 * maximum speeds of the vehicle. It returns the distance that that the
324 * vehicle can drive this tick. #Vehicle::GetAdvanceDistance() determines
325 * the distance to drive before moving a step on the map.
326 * @param accel The acceleration we would like to give this vehicle.
327 * @param min_speed The minimum speed here, in vehicle specific units.
328 * @param max_speed The maximum speed here, in vehicle specific units.
329 * @return Distance to drive.
331 inline uint DoUpdateSpeed(uint accel, int min_speed, int max_speed)
333 uint spd = this->subspeed + accel;
334 this->subspeed = (byte)spd;
336 /* When we are going faster than the maximum speed, reduce the speed
337 * somewhat gradually. But never lower than the maximum speed. */
338 int tempmax = max_speed;
339 if (this->cur_speed > max_speed) {
340 tempmax = max(this->cur_speed - (this->cur_speed / 10) - 1, max_speed);
343 /* Enforce a maximum and minimum speed. Normally we would use something like
344 * Clamp for this, but in this case min_speed might be below the maximum speed
345 * threshold for some reason. That makes acceleration fail and assertions
346 * happen in Clamp. So make it explicit that min_speed overrules the maximum
347 * speed by explicit ordering of min and max. */
348 this->cur_speed = spd = max(min(this->cur_speed + ((int)spd >> 8), tempmax), min_speed);
350 int scaled_spd = this->GetAdvanceSpeed(spd);
352 scaled_spd += this->progress;
353 this->progress = 0; // set later in *Handler or *Controller
354 return scaled_spd;
359 * Base class for all vehicles that move through ground.
361 * Child classes must define all of the following functions.
362 * These functions are not defined as pure virtual functions at this class to improve performance.
364 * virtual uint16 GetPower() const = 0;
365 * virtual uint16 GetPoweredPartPower(const T *head) const = 0;
366 * virtual uint16 GetWeight() const = 0;
367 * virtual byte GetTractiveEffort() const = 0;
368 * virtual byte GetAirDrag() const = 0;
369 * virtual byte GetAirDragArea() const = 0;
370 * virtual AccelStatus GetAccelerationStatus() const = 0;
371 * virtual uint16 GetCurrentSpeed() const = 0;
372 * virtual uint32 GetRollingFriction() const = 0;
373 * virtual int GetAccelerationType() const = 0;
374 * virtual int32 GetSlopeSteepness() const = 0;
375 * virtual int GetDisplayMaxSpeed() const = 0;
376 * virtual uint16 GetMaxTrackSpeed() const = 0;
378 template <class T, VehicleType Type>
379 struct GroundVehicle : public SpecializedVehicle <T, Type, GroundVehicleBase> {
381 * The constructor at SpecializedVehicle must be called.
383 GroundVehicle() : SpecializedVehicle <T, Type, GroundVehicleBase> () {}
385 void PowerChanged();
386 void CargoChanged();
387 int GetAcceleration() const;
388 bool IsChainInDepot() const;
391 #endif /* GROUND_VEHICLE_HPP */