1 /*
2  * Copyright (c) 1997 - 2001 Hansj�rg Malthaner
3  *
4  * This file is part of the Simutrans project under the artistic license.
5  * (see license.txt)
6  */
7 
8 /*
9  * Vehicle base type.
10  */
11 
12 #ifndef SIMVEHICLE_H
13 #define SIMVEHICLE_H
14 
15 #include "../simtypes.h"
16 #include "../simobj.h"
17 #include "../halthandle_t.h"
18 #include "../convoihandle_t.h"
19 #include "../ifc/simtestdriver.h"
20 #include "../boden/grund.h"
21 #include "../descriptor/vehicle_desc.h"
22 #include "../vehicle/overtaker.h"
23 #include "../tpl/slist_tpl.h"
24 
25 class convoi_t;
26 class schedule_t;
27 class signal_t;
28 class ware_t;
29 class route_t;
30 
31 /*----------------------- Movables ------------------------------------*/
32 
33 /**
34  * Base class for all vehicles
35  *
36  * @author Hj. Malthaner
37  */
38 class vehicle_base_t : public obj_t
39 {
40 protected:
41 	// offsets for different directions
42 	static sint8 dxdy[16];
43 
44 	// to make the length on diagonals configurable
45 	// Number of vehicle steps along a diagonal...
46 	// remember to subtract one when stepping down to 0
47 	static uint8 diagonal_vehicle_steps_per_tile;
48 	static uint8 old_diagonal_vehicle_steps_per_tile;
49 	static uint16 diagonal_multiplier;
50 
51 	// [0]=xoff [1]=yoff
52 	static sint8 driveleft_base_offsets[8][2];
53 	static sint8 overtaking_base_offsets[8][2];
54 
55 	/**
56 	 * Actual travel direction in screen coordinates
57 	 * @author Hj. Malthaner
58 	 */
59 	ribi_t::ribi direction;
60 
61 	// true on slope (make calc_height much faster)
62 	uint8 use_calc_height:1;
63 
64 	/**
65 	 * Thing is moving on this lane.
66 	 * Possible values:
67 	 * (Back)
68 	 * 0 - sidewalk (going on the right side to w/sw/s)
69 	 * 1 - road     (going on the right side to w/sw/s)
70 	 * 2 - middle   (everything with waytype != road)
71 	 * 3 - road     (going on the right side to se/e/../nw)
72 	 * 4 - sidewalk (going on the right side to se/e/../nw)
73 	 * (Front)
74 	 */
75 	uint8 disp_lane:3;
76 
77 	sint8 dx, dy;
78 
79 	// number of steps in this tile (255 per tile)
80 	uint8 steps, steps_next;
81 
82 	/**
83 	 * Next position on our path
84 	 * @author Hj. Malthaner
85 	 */
86 	koord3d pos_next;
87 
88 	/**
89 	 * Offsets for uphill/downhill.
90 	 * Have to be multiplied with -TILE_HEIGHT_STEP/2.
91 	 * To obtain real z-offset, interpolate using steps, steps_next.
92 	 */
93 	uint8 zoff_start:4, zoff_end:4;
94 
95 	// cached image
96 	image_id image;
97 
98 	/**
99 	 * Vehicle movement: check whether this vehicle can enter the next tile (pos_next).
100 	 * @returns NULL if check fails, otherwise pointer to the next tile
101 	 */
102 	virtual grund_t* hop_check() = 0;
103 
104 	/**
105 	 * Vehicle movement: change tiles, calls leave_tile and enter_tile.
106 	 * @param gr pointer to ground of new position (never NULL)
107 	 */
108 	virtual void hop(grund_t* gr) = 0;
109 
110 	void calc_image() OVERRIDE = 0;
111 
112 	// check for road vehicle, if next tile is free
113 	vehicle_base_t *no_cars_blocking( const grund_t *gr, const convoi_t *cnv, const uint8 current_direction, const uint8 next_direction, const uint8 next_90direction );
114 
115 	// only needed for old way of moving vehicles to determine position at loading time
116 	bool is_about_to_hop( const sint8 neu_xoff, const sint8 neu_yoff ) const;
117 
118 public:
119 	// only called during load time: set some offsets
120 	static void set_diagonal_multiplier( uint32 multiplier, uint32 old_multiplier );
get_diagonal_multiplier()121 	static uint16 get_diagonal_multiplier() { return diagonal_multiplier; }
get_diagonal_vehicle_steps_per_tile()122 	static uint8 get_diagonal_vehicle_steps_per_tile() { return diagonal_vehicle_steps_per_tile; }
123 
124 	static void set_overtaking_offsets( bool driving_on_the_left );
125 
126 	// if true, this convoi needs to restart for correct alignment
127 	bool need_realignment() const;
128 
129 	uint32 do_drive(uint32 dist);	// basis movement code
130 
set_image(image_id b)131 	inline void set_image( image_id b ) { image = b; }
get_image()132 	image_id get_image() const OVERRIDE {return image;}
133 
134 	sint16 get_hoff(const sint16 raster_width=1) const;
get_steps()135 	uint8 get_steps() const {return steps;}
136 
get_disp_lane()137 	uint8 get_disp_lane() const { return disp_lane; }
138 
139 	// to make smaller steps than the tile granularity, we have to calculate our offsets ourselves!
140 	virtual void get_screen_offset( int &xoff, int &yoff, const sint16 raster_width ) const;
141 
142 	/**
143 	 * Vehicle movement: calculates z-offset of vehicles on slopes,
144 	 * handles vehicles that are invisible in tunnels.
145 	 * @param gr vehicle is on this ground
146 	 * @note has to be called after loading to initialize z-offsets
147 	 */
148 	void calc_height(grund_t *gr = NULL);
149 
150 	void rotate90() OVERRIDE;
151 
152 	template<class K1, class K2>
calc_direction(const K1 & from,const K2 & to)153 	static ribi_t::ribi calc_direction(const K1& from, const K2& to)
154 	{
155 		return ribi_type(from, to);
156 	}
157 
158 	ribi_t::ribi calc_set_direction(const koord3d& start, const koord3d& ende);
159 
get_direction()160 	ribi_t::ribi get_direction() const {return direction;}
161 
get_pos_next()162 	koord3d get_pos_next() const {return pos_next;}
163 
164 	waytype_t get_waytype() const OVERRIDE = 0;
165 
166 	// true, if this vehicle did not moved for some time
is_stuck()167 	virtual bool is_stuck() { return true; }
168 
169 	/**
170 	 * Vehicle movement: enter tile, add this to the ground.
171 	 * @pre position (obj_t::pos) needs to be updated prior to calling this functions
172 	 * @return pointer to ground (never NULL)
173 	 */
174 	virtual void enter_tile(grund_t*);
175 
176 	/**
177 	 * Vehicle movement: leave tile, release reserved crossing, remove vehicle from the ground.
178 	 */
179 	virtual void leave_tile();
180 
get_overtaker()181 	virtual overtaker_t *get_overtaker() { return NULL; }
182 
183 	vehicle_base_t();
184 
185 	vehicle_base_t(koord3d pos);
186 
is_flying()187 	virtual bool is_flying() const { return false; }
188 };
189 
190 
191 template<> inline vehicle_base_t* obj_cast<vehicle_base_t>(obj_t* const d)
192 {
193 	return d->is_moving() ? static_cast<vehicle_base_t*>(d) : 0;
194 }
195 
196 
197 /**
198  * Class for all vehicles with route
199  *
200  * @author Hj. Malthaner
201  */
202 
203 class vehicle_t : public vehicle_base_t, public test_driver_t
204 {
205 private:
206 	/**
207 	* Date of purchase in months
208 	* @author Hj. Malthaner
209 	*/
210 	sint32 purchase_time;
211 
212 	/* For the more physical acceleration model friction is introduced
213 	* frictionforce = gamma*speed*weight
214 	* since the total weight is needed a lot of times, we save it
215 	* @author prissi
216 	*/
217 	uint32 sum_weight;
218 
219 	grund_t* hop_check() OVERRIDE;
220 
221 	/**
222 	 * Calculate friction caused by slopes and curves.
223 	 */
224 	virtual void calc_friction(const grund_t *gr);
225 
226 protected:
227 	void hop(grund_t*) OVERRIDE;
228 
229 	// current limit (due to track etc.)
230 	sint32 speed_limit;
231 
232 	ribi_t::ribi previous_direction;
233 
234 	// for target reservation and search
235 	halthandle_t target_halt;
236 
237 	/* The friction is calculated new every step, so we save it too
238 	* @author prissi
239 	*/
240 	sint16 current_friction;
241 
242 	/**
243 	* Current index on the route
244 	* @author Hj. Malthaner
245 	*/
246 	uint16 route_index;
247 
248 	uint16 total_freight;	// since the sum is needed quite often, it is cached
249 	slist_tpl<ware_t> fracht;   // list of goods being transported
250 
251 	const vehicle_desc_t *desc;
252 
253 	convoi_t *cnv;		// != NULL if the vehicle is part of a Convoi
254 
255 	bool leading:1;	// true, if vehicle is first vehicle of a convoi
256 	bool last:1;	// true, if vehicle is last vehicle of a convoi
257 	bool smoke:1;
258 	bool check_for_finish:1;		// true, if on the last tile
259 	bool has_driven:1;
260 
check_next_tile(const grund_t *)261 	bool check_next_tile(const grund_t* ) const OVERRIDE {return false;}
262 
263 public:
264 	void calc_image() OVERRIDE;
265 
266 	// the coordinates, where the vehicle was loaded the last time
267 	koord3d last_stop_pos;
268 
get_convoi()269 	convoi_t *get_convoi() const { return cnv; }
270 
271 	void rotate90() OVERRIDE;
272 
273 
274 	/**
275 	 * Method checks whether next tile is free to move on.
276 	 * Looks up next tile, and calls @ref can_enter_tile(const grund_t*, sint32&, uint8).
277 	 */
278 	bool can_enter_tile(sint32 &restart_speed, uint8 second_check_count);
279 
280 	/**
281 	 * Method checks whether next tile is free to move on.
282 	 * @param gr_next next tile, must not be NULL
283 	 */
284 	virtual bool can_enter_tile(const grund_t *gr_next, sint32 &restart_speed, uint8 second_check_count) = 0;
285 
286 	void enter_tile(grund_t*) OVERRIDE;
287 
288 	void leave_tile() OVERRIDE;
289 
290 	waytype_t get_waytype() const OVERRIDE = 0;
291 
292 	/**
293 	* Determine the direction bits for this kind of vehicle.
294 	*
295 	* @author Hj. Malthaner, 04.01.01
296 	*/
get_ribi(const grund_t * gr)297 	ribi_t::ribi get_ribi(const grund_t* gr) const OVERRIDE { return gr->get_weg_ribi(get_waytype()); }
298 
get_purchase_time()299 	sint32 get_purchase_time() const {return purchase_time;}
300 
get_smoke(bool yesno)301 	void get_smoke(bool yesno ) { smoke = yesno;}
302 
303 	virtual bool calc_route(koord3d start, koord3d ziel, sint32 max_speed, route_t* route);
get_route_index()304 	uint16 get_route_index() const {return route_index;}
305 
306 	/**
307 	* Get the base image.
308 	* @author Hj. Malthaner
309 	*/
get_base_image()310 	image_id get_base_image() const { return desc->get_base_image(); }
311 
312 	/**
313 	 * @return image with base direction and freight image taken from loaded cargo
314 	 */
315 	image_id get_loaded_image() const;
316 
317 	/**
318 	* @return vehicle description object
319 	* @author Hj. Malthaner
320 	*/
get_desc()321 	const vehicle_desc_t *get_desc() const {return desc; }
322 
323 	/**
324 	* @return die running_cost in Cr/100Km
325 	* @author Hj. Malthaner
326 	*/
get_operating_cost()327 	int get_operating_cost() const { return desc->get_running_cost(); }
328 
329 	/**
330 	* Play sound, when the vehicle is visible on screen
331 	* @author Hj. Malthaner
332 	*/
333 	void play_sound() const;
334 
335 	/**
336 	 * Prepare vehicle for new ride.
337 	 * Sets route_index, pos_next, steps_next.
338 	 * If @p recalc is true this sets position and recalculates/resets movement parameters.
339 	 * @author Hj. Malthaner
340 	 */
341 	void initialise_journey( uint16 start_route_index, bool recalc );
342 
343 	vehicle_t();
344 	vehicle_t(koord3d pos, const vehicle_desc_t* desc, player_t* player);
345 
346 	~vehicle_t();
347 
348 	void make_smoke() const;
349 
350 	void show_info() OVERRIDE;
351 
352 	void info(cbuffer_t & buf) const OVERRIDE;
353 
354 	/* return friction constant: changes in hill and curves; may even negative downhill *
355 	* @author prissi
356 	*/
get_frictionfactor()357 	inline sint16 get_frictionfactor() const { return current_friction; }
358 
359 	/* Return total weight including freight (in kg!)
360 	* @author prissi
361 	*/
get_total_weight()362 	inline uint32 get_total_weight() const { return sum_weight; }
363 
364 	// returns speedlimit of ways (and if convoi enters station etc)
365 	// the convoi takes care of the max_speed of the vehicle
get_speed_limit()366 	sint32 get_speed_limit() const { return speed_limit; }
367 
get_cargo()368 	const slist_tpl<ware_t> & get_cargo() const { return fracht;}   // list of goods being transported
369 
370 	/**
371 	 * Rotate freight target coordinates, has to be called after rotating factories.
372 	 */
373 	void rotate90_freight_destinations(const sint16 y_size);
374 
375 	/**
376 	* Calculate the total quantity of goods moved
377 	*/
get_total_cargo()378 	uint16 get_total_cargo() const { return total_freight; }
379 
380 	/**
381 	* Calculate transported cargo total weight in KG
382 	* @author Hj. Malthaner
383 	*/
384 	uint32 get_cargo_weight() const;
385 
386 	/**
387 	* get the type of cargo this vehicle can transport
388 	*/
get_cargo_type()389 	const goods_desc_t* get_cargo_type() const { return desc->get_freight_type(); }
390 
391 	/**
392 	* Get the maximum capacity
393 	*/
get_cargo_max()394 	uint16 get_cargo_max() const {return desc->get_capacity(); }
395 
396 	const char * get_cargo_mass() const;
397 
398 	/**
399 	* create an info text for the freight
400 	* e.g. to display in a info window
401 	* @author Hj. Malthaner
402 	*/
403 	void get_cargo_info(cbuffer_t & buf) const;
404 
405 	/**
406 	* Delete all vehicle load
407 	* @author Hj. Malthaner
408 	*/
409 	void discard_cargo();
410 
411 	/**
412 	* Payment is done per hop. It iterates all goods and calculates
413 	* the income for the last hop. This method must be called upon
414 	* every stop.
415 	* @return income total for last hop
416 	* @author Hj. Malthaner
417 	*/
418 	sint64 calc_revenue(const koord3d& start, const koord3d& end) const;
419 
420 	// sets or query begin and end of convois
set_leading(bool janein)421 	void set_leading(bool janein) {leading = janein;}
is_leading()422 	bool is_leading() {return leading;}
423 
set_last(bool janein)424 	void set_last(bool janein) {last = janein;}
is_last()425 	bool is_last() {return last;}
426 
427 	// marks the vehicle as really used
set_driven()428 	void set_driven() { has_driven = true; }
429 
430 	virtual void set_convoi(convoi_t *c);
431 
432 	/**
433 	 * Unload freight to halt
434 	 * @return sum of unloaded goods
435 	 */
436 	uint16 unload_cargo(halthandle_t halt, bool all );
437 
438 	/**
439 	 * Load freight from halt
440 	 * @return amount loaded
441 	 */
442 	uint16 load_cargo(halthandle_t halt, const vector_tpl<halthandle_t>& destination_halts);
443 
444 	/**
445 	* Remove freight that no longer can reach it's destination
446 	* i.e. because of a changed schedule
447 	* @author Hj. Malthaner
448 	*/
449 	void remove_stale_cargo();
450 
451 	/**
452 	* Generate a matching schedule for the vehicle type
453 	* @author Hj. Malthaner
454 	*/
455 	virtual schedule_t *generate_new_schedule() const = 0;
456 
457 	const char *is_deletable(const player_t *player) OVERRIDE;
458 
459 	void rdwr(loadsave_t *file) OVERRIDE;
460 	virtual void rdwr_from_convoi(loadsave_t *file);
461 
462 	uint32 calc_sale_value() const;
463 
464 	// true, if this vehicle did not moved for some time
465 	bool is_stuck() OVERRIDE;
466 
467 	// this routine will display a tooltip for lost, on depot order, and stuck vehicles
468 #ifdef MULTI_THREAD
469 	void display_overlay(int xpos, int ypos) const OVERRIDE;
470 #else
471 	void display_after(int xpos, int ypos, bool dirty) const OVERRIDE;
472 #endif
473 };
474 
475 
476 template<> inline vehicle_t* obj_cast<vehicle_t>(obj_t* const d)
477 {
478 	return dynamic_cast<vehicle_t*>(d);
479 }
480 
481 
482 /**
483  * A class for road vehicles. Manages the look of the vehicles
484  * and the navigability of tiles.
485  *
486  * @author Hj. Malthaner
487  * @see vehicle_t
488  */
489 class road_vehicle_t : public vehicle_t
490 {
491 private:
492 	// called internally only from ist_weg_frei()
493 	// returns true on success
494 	bool choose_route(sint32 &restart_speed, ribi_t::ribi start_direction, uint16 index);
495 
496 protected:
497 	bool check_next_tile(const grund_t *bd) const OVERRIDE;
498 
499 public:
500 	void enter_tile(grund_t*) OVERRIDE;
501 
502 	void rotate90() OVERRIDE;
503 
504 	void calc_disp_lane();
505 
get_waytype()506 	waytype_t get_waytype() const OVERRIDE { return road_wt; }
507 
508 	road_vehicle_t(loadsave_t *file, bool first, bool last);
509 	road_vehicle_t(koord3d pos, const vehicle_desc_t* desc, player_t* player, convoi_t* cnv); // start and schedule
510 
511 	void set_convoi(convoi_t *c) OVERRIDE;
512 
513 	// how expensive to go here (for way search)
514 	int get_cost(const grund_t *gr, const weg_t *w, const sint32 max_speed, ribi_t::ribi from) const OVERRIDE;
515 
get_cost_upslope()516 	uint32 get_cost_upslope() const OVERRIDE { return 15; }
517 
518 	bool calc_route(koord3d start, koord3d ziel, sint32 max_speed, route_t* route) OVERRIDE;
519 
520 	bool can_enter_tile(const grund_t *gr_next, sint32 &restart_speed, uint8 second_check_count) OVERRIDE;
521 
522 	// returns true for the way search to an unknown target.
523 	bool is_target(const grund_t *,const grund_t *) const OVERRIDE;
524 
525 	// since we must consider overtaking, we use this for offset calculation
526 	void get_screen_offset( int &xoff, int &yoff, const sint16 raster_width ) const OVERRIDE;
527 
get_typ()528 	obj_t::typ get_typ() const OVERRIDE { return road_vehicle; }
529 
530 	schedule_t * generate_new_schedule() const OVERRIDE;
531 
532 	overtaker_t* get_overtaker() OVERRIDE;
533 };
534 
535 
536 /**
537  * A class for rail vehicles (trains). Manages the look of the vehicles
538  * and the navigability of tiles.
539  *
540  * @author Hj. Malthaner
541  * @see vehicle_t
542  */
543 class rail_vehicle_t : public vehicle_t
544 {
545 protected:
546 	bool check_next_tile(const grund_t *bd) const OVERRIDE;
547 
548 	void enter_tile(grund_t*) OVERRIDE;
549 
550 	bool is_signal_clear(uint16 start_index, sint32 &restart_speed);
551 	bool is_pre_signal_clear(signal_t *sig, uint16 start_index, sint32 &restart_speed);
552 	bool is_priority_signal_clear(signal_t *sig, uint16 start_index, sint32 &restart_speed);
553 	bool is_longblock_signal_clear(signal_t *sig, uint16 start_index, sint32 &restart_speed);
554 	bool is_choose_signal_clear(signal_t *sig, uint16 start_index, sint32 &restart_speed);
555 
556 public:
get_waytype()557 	waytype_t get_waytype() const OVERRIDE { return track_wt; }
558 
559 	// since we might need to un-reserve previously used blocks, we must do this before calculation a new route
560 	bool calc_route(koord3d start, koord3d ziel, sint32 max_speed, route_t* route) OVERRIDE;
561 
562 	// how expensive to go here (for way search)
563 	int get_cost(const grund_t *gr, const weg_t *w, const sint32 max_speed, ribi_t::ribi from) const OVERRIDE;
564 
get_cost_upslope()565 	uint32 get_cost_upslope() const OVERRIDE { return 25; }
566 
567 	// returns true for the way search to an unknown target.
568 	bool is_target(const grund_t *,const grund_t *) const OVERRIDE;
569 
570 	// handles all block stuff and route choosing ...
571 	bool can_enter_tile(const grund_t *gr_next, sint32 &restart_speed, uint8) OVERRIDE;
572 
573 	// reserves or un-reserves all blocks and returns the handle to the next block (if there)
574 	// returns true on successful reservation
575 	bool block_reserver(const route_t *route, uint16 start_index, uint16 &next_signal, uint16 &next_crossing, int signal_count, bool reserve, bool force_unreserve ) const;
576 
577 	void leave_tile() OVERRIDE;
578 
get_typ()579 	typ get_typ() const OVERRIDE { return rail_vehicle; }
580 
581 	rail_vehicle_t(loadsave_t *file, bool is_first, bool is_last);
582 	rail_vehicle_t(koord3d pos, const vehicle_desc_t* desc, player_t* player, convoi_t *cnv);
583 	~rail_vehicle_t();
584 
585 	void set_convoi(convoi_t *c) OVERRIDE;
586 
587 	schedule_t * generate_new_schedule() const OVERRIDE;
588 };
589 
590 
591 
592 /**
593  * very similar to normal railroad, so we can implement it here completely ...
594  * @author prissi
595  * @see vehicle_t
596  */
597 class monorail_vehicle_t : public rail_vehicle_t
598 {
599 public:
get_waytype()600 	waytype_t get_waytype() const OVERRIDE { return monorail_wt; }
601 
602 	// all handled by rail_vehicle_t
monorail_vehicle_t(loadsave_t * file,bool is_first,bool is_last)603 	monorail_vehicle_t(loadsave_t *file, bool is_first, bool is_last) : rail_vehicle_t(file,is_first, is_last) {}
monorail_vehicle_t(koord3d pos,const vehicle_desc_t * desc,player_t * player,convoi_t * cnv)604 	monorail_vehicle_t(koord3d pos, const vehicle_desc_t* desc, player_t* player, convoi_t* cnv) : rail_vehicle_t(pos, desc, player, cnv) {}
605 
get_typ()606 	typ get_typ() const OVERRIDE { return monorail_vehicle; }
607 
608 	schedule_t * generate_new_schedule() const OVERRIDE;
609 };
610 
611 
612 
613 /**
614  * very similar to normal railroad, so we can implement it here completely ...
615  * @author prissi
616  * @see vehicle_t
617  */
618 class maglev_vehicle_t : public rail_vehicle_t
619 {
620 public:
get_waytype()621 	waytype_t get_waytype() const OVERRIDE { return maglev_wt; }
622 
623 	// all handled by rail_vehicle_t
maglev_vehicle_t(loadsave_t * file,bool is_first,bool is_last)624 	maglev_vehicle_t(loadsave_t *file, bool is_first, bool is_last) : rail_vehicle_t(file, is_first, is_last) {}
maglev_vehicle_t(koord3d pos,const vehicle_desc_t * desc,player_t * player,convoi_t * cnv)625 	maglev_vehicle_t(koord3d pos, const vehicle_desc_t* desc, player_t* player, convoi_t* cnv) : rail_vehicle_t(pos, desc, player, cnv) {}
626 
get_typ()627 	typ get_typ() const OVERRIDE { return maglev_vehicle; }
628 
629 	schedule_t * generate_new_schedule() const OVERRIDE;
630 };
631 
632 
633 
634 /**
635  * very similar to normal railroad, so we can implement it here completely ...
636  * @author prissi
637  * @see vehicle_t
638  */
639 class narrowgauge_vehicle_t : public rail_vehicle_t
640 {
641 public:
get_waytype()642 	waytype_t get_waytype() const OVERRIDE { return narrowgauge_wt; }
643 
644 	// all handled by rail_vehicle_t
narrowgauge_vehicle_t(loadsave_t * file,bool is_first,bool is_last)645 	narrowgauge_vehicle_t(loadsave_t *file, bool is_first, bool is_last) : rail_vehicle_t(file, is_first, is_last) {}
narrowgauge_vehicle_t(koord3d pos,const vehicle_desc_t * desc,player_t * player,convoi_t * cnv)646 	narrowgauge_vehicle_t(koord3d pos, const vehicle_desc_t* desc, player_t* player, convoi_t* cnv) : rail_vehicle_t(pos, desc, player, cnv) {}
647 
get_typ()648 	typ get_typ() const OVERRIDE { return narrowgauge_vehicle; }
649 
650 	schedule_t * generate_new_schedule() const OVERRIDE;
651 };
652 
653 
654 
655 /**
656  * A class for naval vehicles. Manages the look of the vehicles
657  * and the navigability of tiles.
658  *
659  * @author Hj. Malthaner
660  * @see vehicle_t
661  */
662 class water_vehicle_t : public vehicle_t
663 {
664 protected:
665 	// how expensive to go here (for way search)
get_cost(const grund_t *,const weg_t *,const sint32,ribi_t::ribi)666 	int get_cost(const grund_t *, const weg_t*, const sint32, ribi_t::ribi) const OVERRIDE { return 1; }
667 
668 	void calc_friction(const grund_t *gr) OVERRIDE;
669 
670 	bool check_next_tile(const grund_t *bd) const OVERRIDE;
671 
672 	void enter_tile(grund_t*) OVERRIDE;
673 
674 public:
get_waytype()675 	waytype_t get_waytype() const OVERRIDE { return water_wt; }
676 
677 	bool can_enter_tile(const grund_t *gr_next, sint32 &restart_speed, uint8) OVERRIDE;
678 
679 	// returns true for the way search to an unknown target.
is_target(const grund_t *,const grund_t *)680 	bool is_target(const grund_t *,const grund_t *) const OVERRIDE {return 0;}
681 
682 	water_vehicle_t(loadsave_t *file, bool is_first, bool is_last);
683 	water_vehicle_t(koord3d pos, const vehicle_desc_t* desc, player_t* player, convoi_t* cnv);
684 
get_typ()685 	obj_t::typ get_typ() const OVERRIDE { return water_vehicle; }
686 
687 	schedule_t * generate_new_schedule() const OVERRIDE;
688 };
689 
690 
691 /**
692  * A class for aircrafts. Manages the look of the vehicles
693  * and the navigability of tiles.
694  *
695  * @author hsiegeln
696  * @see vehicle_t
697  */
698 class air_vehicle_t : public vehicle_t
699 {
700 public:
701 	enum flight_state { taxiing=0, departing=1, flying=2, landing=3, looking_for_parking=4, circling=5, taxiing_to_halt=6  };
702 
703 private:
704 	// only used for is_target() (do not need saving)
705 	ribi_t::ribi approach_dir;
706 #ifdef USE_DIFFERENT_WIND
707 	static uint8 get_approach_ribi( koord3d start, koord3d ziel );
708 #endif
709 	// only used for route search and approach vectors of get_ribi() (do not need saving)
710 	koord3d search_start;
711 	koord3d search_end;
712 
713 	flight_state state;	// functions needed for the search without destination from find_route
714 
715 	sint16 flying_height;
716 	sint16 target_height;
717 	uint32 search_for_stop, touchdown, takeoff;
718 
719 protected:
720 	// jumps to next tile and correct the height ...
721 	void hop(grund_t*) OVERRIDE;
722 
723 	bool check_next_tile(const grund_t *bd) const OVERRIDE;
724 
725 	void enter_tile(grund_t*) OVERRIDE;
726 
727 	bool block_reserver( uint32 start, uint32 end, bool reserve ) const;
728 
729 	// find a route and reserve the stop position
730 	bool find_route_to_stop_position();
731 
732 public:
733 	air_vehicle_t(loadsave_t *file, bool is_first, bool is_last);
734 	air_vehicle_t(koord3d pos, const vehicle_desc_t* desc, player_t* player, convoi_t* cnv); // start and schedule
735 
736 	// to shift the events around properly
get_event_index(flight_state & state_,uint32 & takeoff_,uint32 & stopsearch_,uint32 & landing_)737 	void get_event_index( flight_state &state_, uint32 &takeoff_, uint32 &stopsearch_, uint32 &landing_ ) { state_ = state; takeoff_ = takeoff; stopsearch_ = search_for_stop; landing_ = touchdown; }
set_event_index(flight_state state_,uint32 takeoff_,uint32 stopsearch_,uint32 landing_)738 	void set_event_index( flight_state state_, uint32 takeoff_, uint32 stopsearch_, uint32 landing_ ) { state = state_; takeoff = takeoff_; search_for_stop = stopsearch_; touchdown = landing_; }
739 
740 	// since we are drawing ourselves, we must mark ourselves dirty during deletion
741 	~air_vehicle_t();
742 
get_waytype()743 	waytype_t get_waytype() const OVERRIDE { return air_wt; }
744 
745 	// returns true for the way search to an unknown target.
746 	bool is_target(const grund_t *,const grund_t *) const OVERRIDE;
747 
748 	// return valid direction
749 	ribi_t::ribi get_ribi(const grund_t* ) const OVERRIDE;
750 
751 	// how expensive to go here (for way search)
752 	int get_cost(const grund_t *gr, const weg_t *w, const sint32 max_speed, ribi_t::ribi from) const OVERRIDE;
753 
754 	bool can_enter_tile(const grund_t *gr_next, sint32 &restart_speed, uint8) OVERRIDE;
755 
756 	void set_convoi(convoi_t *c) OVERRIDE;
757 
758 	bool calc_route(koord3d start, koord3d ziel, sint32 max_speed, route_t* route) OVERRIDE;
759 
get_typ()760 	typ get_typ() const OVERRIDE { return air_vehicle; }
761 
762 	schedule_t *generate_new_schedule() const OVERRIDE;
763 
764 	void rdwr_from_convoi(loadsave_t *file) OVERRIDE;
765 
get_flyingheight()766 	int get_flyingheight() const {return flying_height-get_hoff()-2;}
767 
768 	// image: when flying empty, on ground the plane
get_image()769 	image_id get_image() const OVERRIDE {return !is_on_ground() ? IMG_EMPTY : image;}
770 
771 	// image: when flying the shadow, on ground empty
get_outline_image()772 	image_id get_outline_image() const OVERRIDE {return !is_on_ground() ? image : IMG_EMPTY;}
773 
774 	// shadow has black color (when flying)
get_outline_colour()775 	FLAGGED_PIXVAL get_outline_colour() const OVERRIDE {return !is_on_ground() ? TRANSPARENT75_FLAG | OUTLINE_FLAG | color_idx_to_rgb(COL_BLACK) : 0;}
776 
777 #ifdef MULTI_THREAD
778 	// this draws the "real" aircrafts (when flying)
779 	void display_after(int xpos, int ypos, const sint8 clip_num) const OVERRIDE;
780 
781 	// this routine will display a tooltip for lost, on depot order, and stuck vehicles
782 	void display_overlay(int xpos, int ypos) const OVERRIDE;
783 #else
784 	// this draws the "real" aircrafts (when flying)
785 	void display_after(int xpos, int ypos, bool dirty) const OVERRIDE;
786 #endif
787 
calc_friction(const grund_t *)788 	void calc_friction(const grund_t*) OVERRIDE {}
789 
is_on_ground()790 	bool is_on_ground() const { return flying_height==0  &&  !(state==circling  ||  state==flying); }
791 
792 	const char *is_deletable(const player_t *player) OVERRIDE;
793 
is_flying()794 	bool is_flying() const OVERRIDE { return !is_on_ground(); }
795 };
796 
797 #endif
798