|
1 /* $Id$ */ |
|
2 |
|
3 #ifndef VEHICLE_H |
|
4 #define VEHICLE_H |
|
5 |
|
6 #include "oldpool.h" |
|
7 #include "order.h" |
|
8 #include "rail.h" |
|
9 |
|
10 enum { |
|
11 VEH_Invalid = 0x00, |
|
12 VEH_Train = 0x10, |
|
13 VEH_Road = 0x11, |
|
14 VEH_Ship = 0x12, |
|
15 VEH_Aircraft = 0x13, |
|
16 VEH_Special = 0x14, |
|
17 VEH_Disaster = 0x15, |
|
18 } ; |
|
19 |
|
20 enum VehStatus { |
|
21 VS_HIDDEN = 0x01, |
|
22 VS_STOPPED = 0x02, |
|
23 VS_UNCLICKABLE = 0x04, |
|
24 VS_DEFPAL = 0x08, |
|
25 VS_TRAIN_SLOWING = 0x10, |
|
26 VS_SHADOW = 0x20, |
|
27 VS_AIRCRAFT_BROKEN = 0x40, |
|
28 VS_CRASHED = 0x80, |
|
29 }; |
|
30 |
|
31 enum LoadStatus { |
|
32 LS_LOADING_FINISHED, |
|
33 LS_CARGO_UNLOADING, |
|
34 LS_CARGO_PAID_FOR, |
|
35 }; |
|
36 |
|
37 /* Effect vehicle types */ |
|
38 typedef enum EffectVehicle { |
|
39 EV_CHIMNEY_SMOKE = 0, |
|
40 EV_STEAM_SMOKE = 1, |
|
41 EV_DIESEL_SMOKE = 2, |
|
42 EV_ELECTRIC_SPARK = 3, |
|
43 EV_SMOKE = 4, |
|
44 EV_EXPLOSION_LARGE = 5, |
|
45 EV_BREAKDOWN_SMOKE = 6, |
|
46 EV_EXPLOSION_SMALL = 7, |
|
47 EV_BULLDOZER = 8, |
|
48 EV_BUBBLE = 9 |
|
49 } EffectVehicle; |
|
50 |
|
51 typedef struct VehicleRail { |
|
52 uint16 last_speed; // NOSAVE: only used in UI |
|
53 uint16 crash_anim_pos; |
|
54 uint16 days_since_order_progr; |
|
55 |
|
56 // cached values, recalculated on load and each time a vehicle is added to/removed from the consist. |
|
57 uint16 cached_max_speed; // max speed of the consist. (minimum of the max speed of all vehicles in the consist) |
|
58 uint32 cached_power; // total power of the consist. |
|
59 uint8 cached_veh_length; // length of this vehicle in units of 1/8 of normal length, cached because this can be set by a callback |
|
60 uint16 cached_total_length; ///< Length of the whole train, valid only for first engine. |
|
61 |
|
62 // cached values, recalculated when the cargo on a train changes (in addition to the conditions above) |
|
63 uint32 cached_weight; // total weight of the consist. |
|
64 uint32 cached_veh_weight; // weight of the vehicle. |
|
65 uint32 cached_max_te; // max tractive effort of consist |
|
66 /** |
|
67 * Position/type of visual effect. |
|
68 * bit 0 - 3 = position of effect relative to vehicle. (0 = front, 8 = centre, 15 = rear) |
|
69 * bit 4 - 5 = type of effect. (0 = default for engine class, 1 = steam, 2 = diesel, 3 = electric) |
|
70 * bit 6 = disable visual effect. |
|
71 * bit 7 = disable powered wagons. |
|
72 */ |
|
73 byte cached_vis_effect; |
|
74 |
|
75 // NOSAVE: for wagon override - id of the first engine in train |
|
76 // 0xffff == not in train |
|
77 EngineID first_engine; |
|
78 |
|
79 byte track; |
|
80 byte force_proceed; |
|
81 byte railtype; |
|
82 RailTypeMask compatible_railtypes; |
|
83 |
|
84 byte flags; |
|
85 |
|
86 // Link between the two ends of a multiheaded engine |
|
87 Vehicle *other_multiheaded_part; |
|
88 } VehicleRail; |
|
89 |
|
90 enum { |
|
91 VRF_REVERSING = 0, |
|
92 |
|
93 // used to calculate if train is going up or down |
|
94 VRF_GOINGUP = 1, |
|
95 VRF_GOINGDOWN = 2, |
|
96 |
|
97 // used to store if a wagon is powered or not |
|
98 VRF_POWEREDWAGON = 3, |
|
99 |
|
100 // used to reverse the visible direction of the vehicle |
|
101 VRF_REVERSE_DIRECTION = 4, |
|
102 |
|
103 // used to mark train as lost because PF can't find the route |
|
104 VRF_NO_PATH_TO_DESTINATION = 5, |
|
105 |
|
106 // used to mark that electric train engine is allowed to run on normal rail |
|
107 VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL = 6, |
|
108 }; |
|
109 |
|
110 typedef struct VehicleAir { |
|
111 uint16 crashed_counter; |
|
112 byte pos; |
|
113 byte previous_pos; |
|
114 StationID targetairport; |
|
115 byte state; |
|
116 } VehicleAir; |
|
117 |
|
118 typedef struct VehicleRoad { |
|
119 byte state; |
|
120 byte frame; |
|
121 uint16 blocked_ctr; |
|
122 byte overtaking; |
|
123 byte overtaking_ctr; |
|
124 uint16 crashed_ctr; |
|
125 byte reverse_ctr; |
|
126 struct RoadStop *slot; |
|
127 byte slot_age; |
|
128 } VehicleRoad; |
|
129 |
|
130 typedef struct VehicleSpecial { |
|
131 uint16 unk0; |
|
132 byte unk2; |
|
133 } VehicleSpecial; |
|
134 |
|
135 typedef struct VehicleDisaster { |
|
136 uint16 image_override; |
|
137 uint16 unk2; |
|
138 } VehicleDisaster; |
|
139 |
|
140 typedef struct VehicleShip { |
|
141 byte state; |
|
142 } VehicleShip; |
|
143 |
|
144 |
|
145 struct Vehicle { |
|
146 byte type; // type, ie roadven,train,ship,aircraft,special |
|
147 byte subtype; // subtype (Filled with values from EffectVehicles or TrainSubTypes) |
|
148 |
|
149 VehicleID index; // NOSAVE: Index in vehicle array |
|
150 |
|
151 Vehicle *next; // next |
|
152 Vehicle *first; // NOSAVE: pointer to the first vehicle in the chain |
|
153 Vehicle *depot_list; //NOSAVE: linked list to tell what vehicles entered a depot during the last tick. Used by autoreplace |
|
154 |
|
155 StringID string_id; // Displayed string |
|
156 |
|
157 UnitID unitnumber; // unit number, for display purposes only |
|
158 PlayerID owner; // which player owns the vehicle? |
|
159 |
|
160 TileIndex tile; // Current tile index |
|
161 TileIndex dest_tile; // Heading for this tile |
|
162 |
|
163 int32 x_pos; // coordinates |
|
164 int32 y_pos; |
|
165 byte z_pos; |
|
166 byte direction; // facing |
|
167 |
|
168 byte spritenum; // currently displayed sprite index |
|
169 // 0xfd == custom sprite, 0xfe == custom second head sprite |
|
170 // 0xff == reserved for another custom sprite |
|
171 uint16 cur_image; // sprite number for this vehicle |
|
172 byte sprite_width; // width of vehicle sprite |
|
173 byte sprite_height; // height of vehicle sprite |
|
174 byte z_height; // z-height of vehicle sprite |
|
175 int8 x_offs; // x offset for vehicle sprite |
|
176 int8 y_offs; // y offset for vehicle sprite |
|
177 EngineID engine_type; |
|
178 |
|
179 // for randomized variational spritegroups |
|
180 // bitmask used to resolve them; parts of it get reseeded when triggers |
|
181 // of corresponding spritegroups get matched |
|
182 byte random_bits; |
|
183 byte waiting_triggers; // triggers to be yet matched |
|
184 |
|
185 uint16 max_speed; // maximum speed |
|
186 uint16 cur_speed; // current speed |
|
187 byte subspeed; // fractional speed |
|
188 byte acceleration; // used by train & aircraft |
|
189 byte progress; |
|
190 uint32 motion_counter; |
|
191 |
|
192 byte vehstatus; // Status |
|
193 StationID last_station_visited; |
|
194 |
|
195 CargoID cargo_type; // type of cargo this vehicle is carrying |
|
196 byte cargo_days; // how many days have the pieces been in transit |
|
197 StationID cargo_source; // source of cargo |
|
198 uint16 cargo_cap; // total capacity |
|
199 uint16 cargo_count; // how many pieces are used |
|
200 byte cargo_subtype; ///< Used for livery refits (NewGRF variations) |
|
201 |
|
202 byte day_counter; // increased by one for each day |
|
203 byte tick_counter; // increased by one for each tick |
|
204 |
|
205 /* Begin Order-stuff */ |
|
206 Order current_order; ///< The current order (+ status, like: loading) |
|
207 VehicleOrderID cur_order_index; ///< The index to the current order |
|
208 |
|
209 Order *orders; ///< Pointer to the first order for this vehicle |
|
210 VehicleOrderID num_orders; ///< How many orders there are in the list |
|
211 |
|
212 Vehicle *next_shared; ///< If not NULL, this points to the next vehicle that shared the order |
|
213 Vehicle *prev_shared; ///< If not NULL, this points to the prev vehicle that shared the order |
|
214 /* End Order-stuff */ |
|
215 |
|
216 // Boundaries for the current position in the world and a next hash link. |
|
217 // NOSAVE: All of those can be updated with VehiclePositionChanged() |
|
218 int32 left_coord; |
|
219 int32 top_coord; |
|
220 int32 right_coord; |
|
221 int32 bottom_coord; |
|
222 VehicleID next_hash; |
|
223 |
|
224 // Related to age and service time |
|
225 Date age; // Age in days |
|
226 Date max_age; // Maximum age |
|
227 Date date_of_last_service; |
|
228 Date service_interval; |
|
229 uint16 reliability; |
|
230 uint16 reliability_spd_dec; |
|
231 byte breakdown_ctr; |
|
232 byte breakdown_delay; |
|
233 byte breakdowns_since_last_service; |
|
234 byte breakdown_chance; |
|
235 Year build_year; |
|
236 |
|
237 bool leave_depot_instantly; // NOSAVE: stores if the vehicle needs to leave the depot it just entered. Used by autoreplace |
|
238 |
|
239 uint16 load_unload_time_rem; |
|
240 byte load_status; |
|
241 |
|
242 int32 profit_this_year; |
|
243 int32 profit_last_year; |
|
244 uint32 value; |
|
245 |
|
246 union { |
|
247 VehicleRail rail; |
|
248 VehicleAir air; |
|
249 VehicleRoad road; |
|
250 VehicleSpecial special; |
|
251 VehicleDisaster disaster; |
|
252 VehicleShip ship; |
|
253 } u; |
|
254 }; |
|
255 |
|
256 #define is_custom_sprite(x) (x >= 0xFD) |
|
257 #define IS_CUSTOM_FIRSTHEAD_SPRITE(x) (x == 0xFD) |
|
258 #define IS_CUSTOM_SECONDHEAD_SPRITE(x) (x == 0xFE) |
|
259 |
|
260 typedef void *VehicleFromPosProc(Vehicle *v, void *data); |
|
261 |
|
262 void VehicleServiceInDepot(Vehicle *v); |
|
263 Vehicle *AllocateVehicle(void); |
|
264 bool AllocateVehicles(Vehicle **vl, int num); |
|
265 Vehicle *ForceAllocateVehicle(void); |
|
266 Vehicle *ForceAllocateSpecialVehicle(void); |
|
267 void VehiclePositionChanged(Vehicle *v); |
|
268 void AfterLoadVehicles(void); |
|
269 Vehicle *GetLastVehicleInChain(Vehicle *v); |
|
270 Vehicle *GetPrevVehicleInChain(const Vehicle *v); |
|
271 Vehicle *GetFirstVehicleInChain(const Vehicle *v); |
|
272 uint CountVehiclesInChain(const Vehicle* v); |
|
273 bool IsEngineCountable(const Vehicle *v); |
|
274 void DeleteVehicleChain(Vehicle *v); |
|
275 void *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc); |
|
276 void CallVehicleTicks(void); |
|
277 Vehicle *FindVehicleOnTileZ(TileIndex tile, byte z); |
|
278 |
|
279 void InitializeTrains(void); |
|
280 byte VehicleRandomBits(void); |
|
281 void ResetVehiclePosHash(void); |
|
282 |
|
283 bool CanFillVehicle(Vehicle *v); |
|
284 bool CanRefitTo(EngineID engine_type, CargoID cid_to); |
|
285 CargoID FindFirstRefittableCargo(EngineID engine_type); |
|
286 int32 GetRefitCost(EngineID engine_type); |
|
287 |
|
288 void ViewportAddVehicles(DrawPixelInfo *dpi); |
|
289 |
|
290 /* train_cmd.h */ |
|
291 int GetTrainImage(const Vehicle* v, Direction direction); |
|
292 int GetAircraftImage(const Vehicle* v, Direction direction); |
|
293 int GetRoadVehImage(const Vehicle* v, Direction direction); |
|
294 int GetShipImage(const Vehicle* v, Direction direction); |
|
295 |
|
296 Vehicle *CreateEffectVehicle(int x, int y, int z, EffectVehicle type); |
|
297 Vehicle *CreateEffectVehicleAbove(int x, int y, int z, EffectVehicle type); |
|
298 Vehicle *CreateEffectVehicleRel(const Vehicle *v, int x, int y, int z, EffectVehicle type); |
|
299 |
|
300 uint32 VehicleEnterTile(Vehicle *v, TileIndex tile, int x, int y); |
|
301 |
|
302 StringID VehicleInTheWayErrMsg(const Vehicle* v); |
|
303 Vehicle *FindVehicleBetween(TileIndex from, TileIndex to, byte z); |
|
304 |
|
305 bool UpdateSignalsOnSegment(TileIndex tile, DiagDirection direction); |
|
306 void SetSignalsOnBothDir(TileIndex tile, byte track); |
|
307 |
|
308 Vehicle *CheckClickOnVehicle(const ViewPort *vp, int x, int y); |
|
309 |
|
310 void DecreaseVehicleValue(Vehicle *v); |
|
311 void CheckVehicleBreakdown(Vehicle *v); |
|
312 void AgeVehicle(Vehicle *v); |
|
313 void VehicleEnteredDepotThisTick(Vehicle *v); |
|
314 |
|
315 void BeginVehicleMove(Vehicle *v); |
|
316 void EndVehicleMove(Vehicle *v); |
|
317 |
|
318 void ShowAircraftViewWindow(const Vehicle* v); |
|
319 |
|
320 UnitID GetFreeUnitNumber(byte type); |
|
321 |
|
322 int LoadUnloadVehicle(Vehicle *v, bool just_arrived); |
|
323 |
|
324 void TrainConsistChanged(Vehicle *v); |
|
325 void TrainPowerChanged(Vehicle *v); |
|
326 int32 GetTrainRunningCost(const Vehicle *v); |
|
327 |
|
328 int CheckTrainStoppedInDepot(const Vehicle *v); |
|
329 |
|
330 bool VehicleNeedsService(const Vehicle *v); |
|
331 |
|
332 uint GenerateVehicleSortList(const Vehicle*** sort_list, uint16 *length_of_array, byte type, PlayerID owner, StationID station, OrderID order, uint16 depot_airport_index, uint16 window_type); |
|
333 void BuildDepotVehicleList(byte type, TileIndex tile, Vehicle ***engine_list, uint16 *engine_list_length, uint16 *engine_count, Vehicle ***wagon_list, uint16 *wagon_list_length, uint16 *wagon_count); |
|
334 int32 SendAllVehiclesToDepot(byte type, uint32 flags, bool service, PlayerID owner, uint16 vlw_flag, uint32 id); |
|
335 bool IsVehicleInDepot(const Vehicle *v); |
|
336 void VehicleEnterDepot(Vehicle *v); |
|
337 |
|
338 /* Flags to add to p2 for goto depot commands */ |
|
339 /* Note: bits 8-10 are used for VLW flags */ |
|
340 enum { |
|
341 DEPOT_SERVICE = (1 << 0), // The vehicle will leave the depot right after arrival (serivce only) |
|
342 DEPOT_MASS_SEND = (1 << 1), // Tells that it's a mass send to depot command (type in VLW flag) |
|
343 DEPOT_DONT_CANCEL = (1 << 2), // Don't cancel current goto depot command if any |
|
344 DEPOT_LOCATE_HANGAR = (1 << 3), // Find another airport if the target one lacks a hangar |
|
345 }; |
|
346 |
|
347 typedef struct GetNewVehiclePosResult { |
|
348 int x,y; |
|
349 TileIndex old_tile; |
|
350 TileIndex new_tile; |
|
351 } GetNewVehiclePosResult; |
|
352 |
|
353 /** |
|
354 * Returns the Trackdir on which the vehicle is currently located. |
|
355 * Works for trains and ships. |
|
356 * Currently works only sortof for road vehicles, since they have a fuzzy |
|
357 * concept of being "on" a trackdir. Dunno really what it returns for a road |
|
358 * vehicle that is halfway a tile, never really understood that part. For road |
|
359 * vehicles that are at the beginning or end of the tile, should just return |
|
360 * the diagonal trackdir on which they are driving. I _think_. |
|
361 * For other vehicles types, or vehicles with no clear trackdir (such as those |
|
362 * in depots), returns 0xFF. |
|
363 */ |
|
364 Trackdir GetVehicleTrackdir(const Vehicle* v); |
|
365 |
|
366 /* returns true if staying in the same tile */ |
|
367 bool GetNewVehiclePos(const Vehicle *v, GetNewVehiclePosResult *gp); |
|
368 Direction GetDirectionTowards(const Vehicle* v, int x, int y); |
|
369 |
|
370 #define BEGIN_ENUM_WAGONS(v) do { |
|
371 #define END_ENUM_WAGONS(v) } while ( (v=v->next) != NULL); |
|
372 |
|
373 DECLARE_OLD_POOL(Vehicle, Vehicle, 9, 125) |
|
374 |
|
375 static inline VehicleID GetMaxVehicleIndex(void) |
|
376 { |
|
377 /* TODO - This isn't the real content of the function, but |
|
378 * with the new pool-system this will be replaced with one that |
|
379 * _really_ returns the highest index. Now it just returns |
|
380 * the next safe value we are sure about everything is below. |
|
381 */ |
|
382 return GetVehiclePoolSize() - 1; |
|
383 } |
|
384 |
|
385 static inline uint GetNumVehicles(void) |
|
386 { |
|
387 return GetVehiclePoolSize(); |
|
388 } |
|
389 |
|
390 /** |
|
391 * Check if a Vehicle really exists. |
|
392 */ |
|
393 static inline bool IsValidVehicle(const Vehicle *v) |
|
394 { |
|
395 return v->type != 0; |
|
396 } |
|
397 |
|
398 void DestroyVehicle(Vehicle *v); |
|
399 |
|
400 static inline void DeleteVehicle(Vehicle *v) |
|
401 { |
|
402 DestroyVehicle(v); |
|
403 v->type = 0; |
|
404 } |
|
405 |
|
406 #define FOR_ALL_VEHICLES_FROM(v, start) for (v = GetVehicle(start); v != NULL; v = (v->index + 1U < GetVehiclePoolSize()) ? GetVehicle(v->index + 1) : NULL) if (IsValidVehicle(v)) |
|
407 #define FOR_ALL_VEHICLES(v) FOR_ALL_VEHICLES_FROM(v, 0) |
|
408 |
|
409 /** |
|
410 * Check if an index is a vehicle-index (so between 0 and max-vehicles) |
|
411 * |
|
412 * @return Returns true if the vehicle-id is in range |
|
413 */ |
|
414 static inline bool IsValidVehicleID(uint index) |
|
415 { |
|
416 return index < GetVehiclePoolSize() && IsValidVehicle(GetVehicle(index)); |
|
417 } |
|
418 |
|
419 /* Returns order 'index' of a vehicle or NULL when it doesn't exists */ |
|
420 static inline Order *GetVehicleOrder(const Vehicle *v, int index) |
|
421 { |
|
422 Order *order = v->orders; |
|
423 |
|
424 if (index < 0) return NULL; |
|
425 |
|
426 while (order != NULL && index-- > 0) |
|
427 order = order->next; |
|
428 |
|
429 return order; |
|
430 } |
|
431 |
|
432 /* Returns the last order of a vehicle, or NULL if it doesn't exists */ |
|
433 static inline Order *GetLastVehicleOrder(const Vehicle *v) |
|
434 { |
|
435 Order *order = v->orders; |
|
436 |
|
437 if (order == NULL) return NULL; |
|
438 |
|
439 while (order->next != NULL) |
|
440 order = order->next; |
|
441 |
|
442 return order; |
|
443 } |
|
444 |
|
445 /* Get the first vehicle of a shared-list, so we only have to walk forwards */ |
|
446 static inline Vehicle *GetFirstVehicleFromSharedList(const Vehicle *v) |
|
447 { |
|
448 Vehicle *u = (Vehicle *)v; |
|
449 while (u->prev_shared != NULL) u = u->prev_shared; |
|
450 |
|
451 return u; |
|
452 } |
|
453 |
|
454 // NOSAVE: Return values from various commands. |
|
455 VARDEF VehicleID _new_vehicle_id; |
|
456 VARDEF uint16 _returned_refit_capacity; |
|
457 |
|
458 enum { |
|
459 INVALID_VEHICLE = 0xFFFF, |
|
460 }; |
|
461 |
|
462 /** |
|
463 * Get the colour map for an engine. This used for unbuilt engines in the user interface. |
|
464 * @param engine_type ID of engine |
|
465 * @param player ID of player |
|
466 * @return A ready-to-use palette modifier |
|
467 */ |
|
468 PalSpriteID GetEnginePalette(EngineID engine_type, PlayerID player); |
|
469 |
|
470 /** |
|
471 * Get the colour map for a vehicle. |
|
472 * @param v Vehicle to get colour map for |
|
473 * @return A ready-to-use palette modifier |
|
474 */ |
|
475 PalSpriteID GetVehiclePalette(const Vehicle *v); |
|
476 |
|
477 /* A lot of code calls for the invalidation of the status bar, which is widget 5. |
|
478 * Best is to have a virtual value for it when it needs to change again */ |
|
479 #define STATUS_BAR 5 |
|
480 |
|
481 extern const uint32 _send_to_depot_proc_table[]; |
|
482 #define CMD_SEND_TO_DEPOT(x) _send_to_depot_proc_table[ x - VEH_Train] |
|
483 |
|
484 #endif /* VEHICLE_H */ |