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 
8 /** @file src/roadveh.h Road vehicle states */
9 
10 #ifndef ROADVEH_H
11 #define ROADVEH_H
12 
13 #include "ground_vehicle.hpp"
14 #include "engine_base.h"
15 #include "cargotype.h"
16 #include "track_func.h"
17 #include "road.h"
18 #include "road_map.h"
19 #include "newgrf_engine.h"
20 #include <deque>
21 
22 struct RoadVehicle;
23 
24 /** Road vehicle states */
25 enum RoadVehicleStates {
26 	/*
27 	 * Lower 4 bits are used for vehicle track direction. (Trackdirs)
28 	 * When in a road stop (bit 5 or bit 6 set) these bits give the
29 	 * track direction of the entry to the road stop.
30 	 * As the entry direction will always be a diagonal
31 	 * direction (X_NE, Y_SE, X_SW or Y_NW) only bits 0 and 3
32 	 * are needed to hold this direction. Bit 1 is then used to show
33 	 * that the vehicle is using the second road stop bay.
34 	 * Bit 2 is then used for drive-through stops to show the vehicle
35 	 * is stopping at this road stop.
36 	 */
37 
38 	/* Numeric values */
39 	RVSB_IN_DEPOT                = 0xFE,                      ///< The vehicle is in a depot
40 	RVSB_WORMHOLE                = 0xFF,                      ///< The vehicle is in a tunnel and/or bridge
41 
42 	/* Bit numbers */
43 	RVS_USING_SECOND_BAY         =    1,                      ///< Only used while in a road stop
44 	RVS_ENTERED_STOP             =    2,                      ///< Only set when a vehicle has entered the stop
45 	RVS_DRIVE_SIDE               =    4,                      ///< Only used when retrieving move data
46 	RVS_IN_ROAD_STOP             =    5,                      ///< The vehicle is in a road stop
47 	RVS_IN_DT_ROAD_STOP          =    6,                      ///< The vehicle is in a drive-through road stop
48 
49 	/* Bit sets of the above specified bits */
50 	RVSB_IN_ROAD_STOP            = 1 << RVS_IN_ROAD_STOP,     ///< The vehicle is in a road stop
51 	RVSB_IN_ROAD_STOP_END        = RVSB_IN_ROAD_STOP + TRACKDIR_END,
52 	RVSB_IN_DT_ROAD_STOP         = 1 << RVS_IN_DT_ROAD_STOP,  ///< The vehicle is in a drive-through road stop
53 	RVSB_IN_DT_ROAD_STOP_END     = RVSB_IN_DT_ROAD_STOP + TRACKDIR_END,
54 
55 	RVSB_DRIVE_SIDE              = 1 << RVS_DRIVE_SIDE,       ///< The vehicle is at the opposite side of the road
56 
57 	RVSB_TRACKDIR_MASK           = 0x0F,                      ///< The mask used to extract track dirs
58 	RVSB_ROAD_STOP_TRACKDIR_MASK = 0x09,                      ///< Only bits 0 and 3 are used to encode the trackdir for road stops
59 };
60 
61 /** State information about the Road Vehicle controller */
62 static const uint RDE_NEXT_TILE = 0x80; ///< We should enter the next tile
63 static const uint RDE_TURNED    = 0x40; ///< We just finished turning
64 
65 /* Start frames for when a vehicle enters a tile/changes its state.
66  * The start frame is different for vehicles that turned around or
67  * are leaving the depot as the do not start at the edge of the tile.
68  * For trams there are a few different start frames as there are two
69  * places where trams can turn. */
70 static const uint RVC_DEFAULT_START_FRAME                =  0;
71 static const uint RVC_TURN_AROUND_START_FRAME            =  1;
72 static const uint RVC_DEPOT_START_FRAME                  =  6;
73 static const uint RVC_START_FRAME_AFTER_LONG_TRAM        = 21;
74 static const uint RVC_TURN_AROUND_START_FRAME_SHORT_TRAM = 16;
75 /* Stop frame for a vehicle in a drive-through stop */
76 static const uint RVC_DRIVE_THROUGH_STOP_FRAME           = 11;
77 static const uint RVC_DEPOT_STOP_FRAME                   = 11;
78 
79 /** The number of ticks a vehicle has for overtaking. */
80 static const byte RV_OVERTAKE_TIMEOUT = 35;
81 
82 void RoadVehUpdateCache(RoadVehicle *v, bool same_length = false);
83 void GetRoadVehSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type);
84 
85 struct RoadVehPathCache {
86 	std::deque<Trackdir> td;
87 	std::deque<TileIndex> tile;
88 
emptyRoadVehPathCache89 	inline bool empty() const { return this->td.empty(); }
90 
sizeRoadVehPathCache91 	inline size_t size() const
92 	{
93 		assert(this->td.size() == this->tile.size());
94 		return this->td.size();
95 	}
96 
clearRoadVehPathCache97 	inline void clear()
98 	{
99 		this->td.clear();
100 		this->tile.clear();
101 	}
102 };
103 
104 /**
105  * Buses, trucks and trams belong to this class.
106  */
107 struct RoadVehicle FINAL : public GroundVehicle<RoadVehicle, VEH_ROAD> {
108 	RoadVehPathCache path;  ///< Cached path.
109 	byte state;             ///< @see RoadVehicleStates
110 	byte frame;
111 	uint16 blocked_ctr;
112 	byte overtaking;        ///< Set to #RVSB_DRIVE_SIDE when overtaking, otherwise 0.
113 	byte overtaking_ctr;    ///< The length of the current overtake attempt.
114 	uint16 crashed_ctr;     ///< Animation counter when the vehicle has crashed. @see RoadVehIsCrashed
115 	byte reverse_ctr;
116 
117 	RoadType roadtype;              //!< Roadtype of this vehicle.
118 	RoadTypes compatible_roadtypes; //!< Roadtypes this consist is powered on.
119 
120 	/** We don't want GCC to zero our struct! It already is zeroed and has an index! */
RoadVehicleFINAL121 	RoadVehicle() : GroundVehicleBase() {}
122 	/** We want to 'destruct' the right class. */
~RoadVehicleFINAL123 	virtual ~RoadVehicle() { this->PreDestructor(); }
124 
125 	friend struct GroundVehicle<RoadVehicle, VEH_ROAD>; // GroundVehicle needs to use the acceleration functions defined at RoadVehicle.
126 
127 	void MarkDirty();
128 	void UpdateDeltaXY();
129 	ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_ROADVEH_INC : EXPENSES_ROADVEH_RUN; }
130 	bool IsPrimaryVehicle() const { return this->IsFrontEngine(); }
131 	void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const;
132 	int GetDisplaySpeed() const { return this->gcache.last_speed / 2; }
133 	int GetDisplayMaxSpeed() const { return this->vcache.cached_max_speed / 2; }
134 	Money GetRunningCost() const;
135 	int GetDisplayImageWidth(Point *offset = nullptr) const;
136 	bool IsInDepot() const { return this->state == RVSB_IN_DEPOT; }
137 	bool Tick();
138 	void OnNewDay();
139 	uint Crash(bool flooded = false);
140 	Trackdir GetVehicleTrackdir() const;
141 	TileIndex GetOrderStationLocation(StationID station);
142 	bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse);
143 
144 	bool IsBus() const;
145 
146 	int GetCurrentMaxSpeed() const;
147 	int UpdateSpeed();
148 	void SetDestTile(TileIndex tile);
149 
150 protected: // These functions should not be called outside acceleration code.
151 
152 	/**
153 	 * Allows to know the power value that this vehicle will use.
154 	 * @return Power value from the engine in HP, or zero if the vehicle is not powered.
155 	 */
156 	inline uint16 GetPower() const
157 	{
158 		/* Power is not added for articulated parts */
159 		if (!this->IsArticulatedPart()) {
160 			/* Road vehicle power is in units of 10 HP. */
161 			return 10 * GetVehicleProperty(this, PROP_ROADVEH_POWER, RoadVehInfo(this->engine_type)->power);
162 		}
163 		return 0;
164 	}
165 
166 	/**
167 	 * Returns a value if this articulated part is powered.
168 	 * @return Zero, because road vehicles don't have powered parts.
169 	 */
170 	inline uint16 GetPoweredPartPower(const RoadVehicle *head) const
171 	{
172 		return 0;
173 	}
174 
175 	/**
176 	 * Allows to know the weight value that this vehicle will use.
177 	 * @return Weight value from the engine in tonnes.
178 	 */
179 	inline uint16 GetWeight() const
180 	{
181 		uint16 weight = (CargoSpec::Get(this->cargo_type)->weight * this->cargo.StoredCount()) / 16;
182 
183 		/* Vehicle weight is not added for articulated parts. */
184 		if (!this->IsArticulatedPart()) {
185 			/* Road vehicle weight is in units of 1/4 t. */
186 			weight += GetVehicleProperty(this, PROP_ROADVEH_WEIGHT, RoadVehInfo(this->engine_type)->weight) / 4;
187 		}
188 
189 		return weight;
190 	}
191 
192 	/**
193 	 * Allows to know the tractive effort value that this vehicle will use.
194 	 * @return Tractive effort value from the engine.
195 	 */
196 	inline byte GetTractiveEffort() const
197 	{
198 		/* The tractive effort coefficient is in units of 1/256.  */
199 		return GetVehicleProperty(this, PROP_ROADVEH_TRACTIVE_EFFORT, RoadVehInfo(this->engine_type)->tractive_effort);
200 	}
201 
202 	/**
203 	 * Gets the area used for calculating air drag.
204 	 * @return Area of the engine in m^2.
205 	 */
206 	inline byte GetAirDragArea() const
207 	{
208 		return 6;
209 	}
210 
211 	/**
212 	 * Gets the air drag coefficient of this vehicle.
213 	 * @return Air drag value from the engine.
214 	 */
215 	inline byte GetAirDrag() const
216 	{
217 		return RoadVehInfo(this->engine_type)->air_drag;
218 	}
219 
220 	/**
221 	 * Checks the current acceleration status of this vehicle.
222 	 * @return Acceleration status.
223 	 */
224 	inline AccelStatus GetAccelerationStatus() const
225 	{
226 		return (this->vehstatus & VS_STOPPED) ? AS_BRAKE : AS_ACCEL;
227 	}
228 
229 	/**
230 	 * Calculates the current speed of this vehicle.
231 	 * @return Current speed in km/h-ish.
232 	 */
233 	inline uint16 GetCurrentSpeed() const
234 	{
235 		return this->cur_speed / 2;
236 	}
237 
238 	/**
239 	 * Returns the rolling friction coefficient of this vehicle.
240 	 * @return Rolling friction coefficient in [1e-4].
241 	 */
242 	inline uint32 GetRollingFriction() const
243 	{
244 		/* Trams have a slightly greater friction coefficient than trains.
245 		 * The rest of road vehicles have bigger values. */
246 		uint32 coeff = RoadTypeIsTram(this->roadtype) ? 40 : 75;
247 		/* The friction coefficient increases with speed in a way that
248 		 * it doubles at 128 km/h, triples at 256 km/h and so on. */
249 		return coeff * (128 + this->GetCurrentSpeed()) / 128;
250 	}
251 
252 	/**
253 	 * Allows to know the acceleration type of a vehicle.
254 	 * @return Zero, road vehicles always use a normal acceleration method.
255 	 */
256 	inline int GetAccelerationType() const
257 	{
258 		return 0;
259 	}
260 
261 	/**
262 	 * Returns the slope steepness used by this vehicle.
263 	 * @return Slope steepness used by the vehicle.
264 	 */
265 	inline uint32 GetSlopeSteepness() const
266 	{
267 		return _settings_game.vehicle.roadveh_slope_steepness;
268 	}
269 
270 	/**
271 	 * Gets the maximum speed allowed by the track for this vehicle.
272 	 * @return Since roads don't limit road vehicle speed, it returns always zero.
273 	 */
274 	inline uint16 GetMaxTrackSpeed() const
275 	{
276 		return GetRoadTypeInfo(GetRoadType(this->tile, GetRoadTramType(this->roadtype)))->max_speed;
277 	}
278 
279 	/**
280 	 * Checks if the vehicle is at a tile that can be sloped.
281 	 * @return True if the tile can be sloped.
282 	 */
283 	inline bool TileMayHaveSlopedTrack() const
284 	{
285 		TrackStatus ts = GetTileTrackStatus(this->tile, TRANSPORT_ROAD, GetRoadTramType(this->roadtype));
286 		TrackBits trackbits = TrackStatusToTrackBits(ts);
287 
288 		return trackbits == TRACK_BIT_X || trackbits == TRACK_BIT_Y;
289 	}
290 
291 	/**
292 	 * Road vehicles have to use GetSlopePixelZ() to compute their height
293 	 * if they are reversing because in that case, their direction
294 	 * is not parallel with the road. It is safe to return \c true
295 	 * even if it is not reversing.
296 	 * @return are we (possibly) reversing?
297 	 */
298 	inline bool HasToUseGetSlopePixelZ()
299 	{
300 		const RoadVehicle *rv = this->First();
301 
302 		/* Check if this vehicle is in the same direction as the road under.
303 		 * We already know it has either GVF_GOINGUP_BIT or GVF_GOINGDOWN_BIT set. */
304 
305 		if (rv->state <= RVSB_TRACKDIR_MASK && IsReversingRoadTrackdir((Trackdir)rv->state)) {
306 			/* If the first vehicle is reversing, this vehicle may be reversing too
307 			 * (especially if this is the first, and maybe the only, vehicle).*/
308 			return true;
309 		}
310 
311 		while (rv != this) {
312 			/* If any previous vehicle has different direction,
313 			 * we may be in the middle of reversing. */
314 			if (this->direction != rv->direction) return true;
315 			rv = rv->Next();
316 		}
317 
318 		return false;
319 	}
320 };
321 
322 #endif /* ROADVEH_H */
323