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 vehicle_base.h Base class for all vehicles. */ 9 10 #ifndef VEHICLE_BASE_H 11 #define VEHICLE_BASE_H 12 13 #include "core/smallmap_type.hpp" 14 #include "track_type.h" 15 #include "command_type.h" 16 #include "order_base.h" 17 #include "cargopacket.h" 18 #include "texteff.hpp" 19 #include "engine_type.h" 20 #include "order_func.h" 21 #include "transport_type.h" 22 #include "group_type.h" 23 #include "base_consist.h" 24 #include "network/network.h" 25 #include "saveload/saveload.h" 26 #include <list> 27 #include <map> 28 29 /** Vehicle status bits in #Vehicle::vehstatus. */ 30 enum VehStatus { 31 VS_HIDDEN = 0x01, ///< Vehicle is not visible. 32 VS_STOPPED = 0x02, ///< Vehicle is stopped by the player. 33 VS_UNCLICKABLE = 0x04, ///< Vehicle is not clickable by the user (shadow vehicles). 34 VS_DEFPAL = 0x08, ///< Use default vehicle palette. @see DoDrawVehicle 35 VS_TRAIN_SLOWING = 0x10, ///< Train is slowing down. 36 VS_SHADOW = 0x20, ///< Vehicle is a shadow vehicle. 37 VS_AIRCRAFT_BROKEN = 0x40, ///< Aircraft is broken down. 38 VS_CRASHED = 0x80, ///< Vehicle is crashed. 39 }; 40 41 /** Bit numbers in #Vehicle::vehicle_flags. */ 42 enum VehicleFlags { 43 VF_LOADING_FINISHED, ///< Vehicle has finished loading. 44 VF_CARGO_UNLOADING, ///< Vehicle is unloading cargo. 45 VF_BUILT_AS_PROTOTYPE, ///< Vehicle is a prototype (accepted as exclusive preview). 46 VF_TIMETABLE_STARTED, ///< Whether the vehicle has started running on the timetable yet. 47 VF_AUTOFILL_TIMETABLE, ///< Whether the vehicle should fill in the timetable automatically. 48 VF_AUTOFILL_PRES_WAIT_TIME, ///< Whether non-destructive auto-fill should preserve waiting times 49 VF_STOP_LOADING, ///< Don't load anymore during the next load cycle. 50 VF_PATHFINDER_LOST, ///< Vehicle's pathfinder is lost. 51 VF_SERVINT_IS_CUSTOM, ///< Service interval is custom. 52 VF_SERVINT_IS_PERCENT, ///< Service interval is percent. 53 }; 54 55 /** Bit numbers used to indicate which of the #NewGRFCache values are valid. */ 56 enum NewGRFCacheValidValues { 57 NCVV_POSITION_CONSIST_LENGTH = 0, ///< This bit will be set if the NewGRF var 40 currently stored is valid. 58 NCVV_POSITION_SAME_ID_LENGTH = 1, ///< This bit will be set if the NewGRF var 41 currently stored is valid. 59 NCVV_CONSIST_CARGO_INFORMATION = 2, ///< This bit will be set if the NewGRF var 42 currently stored is valid. 60 NCVV_COMPANY_INFORMATION = 3, ///< This bit will be set if the NewGRF var 43 currently stored is valid. 61 NCVV_POSITION_IN_VEHICLE = 4, ///< This bit will be set if the NewGRF var 4D currently stored is valid. 62 NCVV_END, ///< End of the bits. 63 }; 64 65 /** Cached often queried (NewGRF) values */ 66 struct NewGRFCache { 67 /* Values calculated when they are requested for the first time after invalidating the NewGRF cache. */ 68 uint32 position_consist_length; ///< Cache for NewGRF var 40. 69 uint32 position_same_id_length; ///< Cache for NewGRF var 41. 70 uint32 consist_cargo_information; ///< Cache for NewGRF var 42. (Note: The cargotype is untranslated in the cache because the accessing GRF is yet unknown.) 71 uint32 company_information; ///< Cache for NewGRF var 43. 72 uint32 position_in_vehicle; ///< Cache for NewGRF var 4D. 73 uint8 cache_valid; ///< Bitset that indicates which cache values are valid. 74 }; 75 76 /** Meaning of the various bits of the visual effect. */ 77 enum VisualEffect { 78 VE_OFFSET_START = 0, ///< First bit that contains the offset (0 = front, 8 = centre, 15 = rear) 79 VE_OFFSET_COUNT = 4, ///< Number of bits used for the offset 80 VE_OFFSET_CENTRE = 8, ///< Value of offset corresponding to a position above the centre of the vehicle 81 82 VE_TYPE_START = 4, ///< First bit used for the type of effect 83 VE_TYPE_COUNT = 2, ///< Number of bits used for the effect type 84 VE_TYPE_DEFAULT = 0, ///< Use default from engine class 85 VE_TYPE_STEAM = 1, ///< Steam plumes 86 VE_TYPE_DIESEL = 2, ///< Diesel fumes 87 VE_TYPE_ELECTRIC = 3, ///< Electric sparks 88 89 VE_DISABLE_EFFECT = 6, ///< Flag to disable visual effect 90 VE_ADVANCED_EFFECT = VE_DISABLE_EFFECT, ///< Flag for advanced effects 91 VE_DISABLE_WAGON_POWER = 7, ///< Flag to disable wagon power 92 93 VE_DEFAULT = 0xFF, ///< Default value to indicate that visual effect should be based on engine class 94 }; 95 96 /** Models for spawning visual effects. */ 97 enum VisualEffectSpawnModel { 98 VESM_NONE = 0, ///< No visual effect 99 VESM_STEAM, ///< Steam model 100 VESM_DIESEL, ///< Diesel model 101 VESM_ELECTRIC, ///< Electric model 102 103 VESM_END 104 }; 105 106 /** 107 * Enum to handle ground vehicle subtypes. 108 * This is defined here instead of at #GroundVehicle because some common function require access to these flags. 109 * Do not access it directly unless you have to. Use the subtype access functions. 110 */ 111 enum GroundVehicleSubtypeFlags { 112 GVSF_FRONT = 0, ///< Leading engine of a consist. 113 GVSF_ARTICULATED_PART = 1, ///< Articulated part of an engine. 114 GVSF_WAGON = 2, ///< Wagon (not used for road vehicles). 115 GVSF_ENGINE = 3, ///< Engine that can be front engine, but might be placed behind another engine (not used for road vehicles). 116 GVSF_FREE_WAGON = 4, ///< First in a wagon chain (in depot) (not used for road vehicles). 117 GVSF_MULTIHEADED = 5, ///< Engine is multiheaded (not used for road vehicles). 118 }; 119 120 /** Cached often queried values common to all vehicles. */ 121 struct VehicleCache { 122 uint16 cached_max_speed; ///< Maximum speed of the consist (minimum of the max speed of all vehicles in the consist). 123 uint16 cached_cargo_age_period; ///< Number of ticks before carried cargo is aged. 124 125 byte cached_vis_effect; ///< Visual effect to show (see #VisualEffect) 126 }; 127 128 /** Sprite sequence for a vehicle part. */ 129 struct VehicleSpriteSeq { 130 PalSpriteID seq[4]; 131 uint count; 132 133 bool operator==(const VehicleSpriteSeq &other) const 134 { 135 return this->count == other.count && MemCmpT<PalSpriteID>(this->seq, other.seq, this->count) == 0; 136 } 137 138 bool operator!=(const VehicleSpriteSeq &other) const 139 { 140 return !this->operator==(other); 141 } 142 143 /** 144 * Check whether the sequence contains any sprites. 145 */ IsValidVehicleSpriteSeq146 bool IsValid() const 147 { 148 return this->count != 0; 149 } 150 151 /** 152 * Clear all information. 153 */ ClearVehicleSpriteSeq154 void Clear() 155 { 156 this->count = 0; 157 } 158 159 /** 160 * Assign a single sprite to the sequence. 161 */ SetVehicleSpriteSeq162 void Set(SpriteID sprite) 163 { 164 this->count = 1; 165 this->seq[0].sprite = sprite; 166 this->seq[0].pal = 0; 167 } 168 169 /** 170 * Copy data from another sprite sequence, while dropping all recolouring information. 171 */ CopyWithoutPaletteVehicleSpriteSeq172 void CopyWithoutPalette(const VehicleSpriteSeq &src) 173 { 174 this->count = src.count; 175 for (uint i = 0; i < src.count; ++i) { 176 this->seq[i].sprite = src.seq[i].sprite; 177 this->seq[i].pal = 0; 178 } 179 } 180 181 void GetBounds(Rect *bounds) const; 182 void Draw(int x, int y, PaletteID default_pal, bool force_pal) const; 183 }; 184 185 /** 186 * Cache for vehicle sprites and values relating to whether they should be updated before drawing, 187 * or calculating the viewport. 188 */ 189 struct MutableSpriteCache { 190 Direction last_direction; ///< Last direction we obtained sprites for 191 bool revalidate_before_draw; ///< We need to do a GetImage() and check bounds before drawing this sprite 192 Rect old_coord; ///< Co-ordinates from the last valid bounding box 193 bool is_viewport_candidate; ///< This vehicle can potentially be drawn on a viewport 194 VehicleSpriteSeq sprite_seq; ///< Vehicle appearance. 195 }; 196 197 /** A vehicle pool for a little over 1 million vehicles. */ 198 typedef Pool<Vehicle, VehicleID, 512, 0xFF000> VehiclePool; 199 extern VehiclePool _vehicle_pool; 200 201 /* Some declarations of functions, so we can make them friendly */ 202 struct GroundVehicleCache; 203 struct LoadgameState; 204 extern bool LoadOldVehicle(LoadgameState *ls, int num); 205 extern void FixOldVehicles(); 206 207 struct GRFFile; 208 209 /** 210 * Simulated cargo type and capacity for prediction of future links. 211 */ 212 struct RefitDesc { 213 CargoID cargo; ///< Cargo type the vehicle will be carrying. 214 uint16 capacity; ///< Capacity the vehicle will have. 215 uint16 remaining; ///< Capacity remaining from before the previous refit. RefitDescRefitDesc216 RefitDesc(CargoID cargo, uint16 capacity, uint16 remaining) : 217 cargo(cargo), capacity(capacity), remaining(remaining) {} 218 }; 219 220 /** %Vehicle data structure. */ 221 struct Vehicle : VehiclePool::PoolItem<&_vehicle_pool>, BaseVehicle, BaseConsist { 222 private: 223 typedef std::list<RefitDesc> RefitList; 224 typedef std::map<CargoID, uint> CapacitiesMap; 225 226 Vehicle *next; ///< pointer to the next vehicle in the chain 227 Vehicle *previous; ///< NOSAVE: pointer to the previous vehicle in the chain 228 Vehicle *first; ///< NOSAVE: pointer to the first vehicle in the chain 229 230 Vehicle *next_shared; ///< pointer to the next vehicle that shares the order 231 Vehicle *previous_shared; ///< NOSAVE: pointer to the previous vehicle in the shared order chain 232 233 public: 234 friend void FixOldVehicles(); 235 friend void AfterLoadVehicles(bool part_of_load); ///< So we can set the #previous and #first pointers while loading 236 friend bool LoadOldVehicle(LoadgameState *ls, int num); ///< So we can set the proper next pointer while loading 237 /* So we can use private/protected variables in the saveload code */ 238 friend class SlVehicleCommon; 239 friend class SlVehicleDisaster; 240 friend void Ptrs_VEHS(); 241 242 TileIndex tile; ///< Current tile index 243 244 /** 245 * Heading for this tile. 246 * For airports and train stations this tile does not necessarily belong to the destination station, 247 * but it can be used for heuristic purposes to estimate the distance. 248 */ 249 TileIndex dest_tile; 250 251 Money profit_this_year; ///< Profit this year << 8, low 8 bits are fract 252 Money profit_last_year; ///< Profit last year << 8, low 8 bits are fract 253 Money value; ///< Value of the vehicle 254 255 CargoPayment *cargo_payment; ///< The cargo payment we're currently in 256 257 mutable Rect coord; ///< NOSAVE: Graphical bounding box of the vehicle, i.e. what to redraw on moves. 258 259 Vehicle *hash_viewport_next; ///< NOSAVE: Next vehicle in the visual location hash. 260 Vehicle **hash_viewport_prev; ///< NOSAVE: Previous vehicle in the visual location hash. 261 262 Vehicle *hash_tile_next; ///< NOSAVE: Next vehicle in the tile location hash. 263 Vehicle **hash_tile_prev; ///< NOSAVE: Previous vehicle in the tile location hash. 264 Vehicle **hash_tile_current; ///< NOSAVE: Cache of the current hash chain. 265 266 SpriteID colourmap; ///< NOSAVE: cached colour mapping 267 268 /* Related to age and service time */ 269 Year build_year; ///< Year the vehicle has been built. 270 Date age; ///< Age in days 271 Date max_age; ///< Maximum age 272 Date date_of_last_service; ///< Last date the vehicle had a service at a depot. 273 uint16 reliability; ///< Reliability. 274 uint16 reliability_spd_dec; ///< Reliability decrease speed. 275 byte breakdown_ctr; ///< Counter for managing breakdown events. @see Vehicle::HandleBreakdown 276 byte breakdown_delay; ///< Counter for managing breakdown length. 277 byte breakdowns_since_last_service; ///< Counter for the amount of breakdowns. 278 byte breakdown_chance; ///< Current chance of breakdowns. 279 280 int32 x_pos; ///< x coordinate. 281 int32 y_pos; ///< y coordinate. 282 int32 z_pos; ///< z coordinate. 283 Direction direction; ///< facing 284 285 Owner owner; ///< Which company owns the vehicle? 286 /** 287 * currently displayed sprite index 288 * 0xfd == custom sprite, 0xfe == custom second head sprite 289 * 0xff == reserved for another custom sprite 290 */ 291 byte spritenum; 292 byte x_extent; ///< x-extent of vehicle bounding box 293 byte y_extent; ///< y-extent of vehicle bounding box 294 byte z_extent; ///< z-extent of vehicle bounding box 295 int8 x_bb_offs; ///< x offset of vehicle bounding box 296 int8 y_bb_offs; ///< y offset of vehicle bounding box 297 int8 x_offs; ///< x offset for vehicle sprite 298 int8 y_offs; ///< y offset for vehicle sprite 299 EngineID engine_type; ///< The type of engine used for this vehicle. 300 301 TextEffectID fill_percent_te_id; ///< a text-effect id to a loading indicator object 302 UnitID unitnumber; ///< unit number, for display purposes only 303 304 uint16 cur_speed; ///< current speed 305 byte subspeed; ///< fractional speed 306 byte acceleration; ///< used by train & aircraft 307 uint32 motion_counter; ///< counter to occasionally play a vehicle sound. 308 byte progress; ///< The percentage (if divided by 256) this vehicle already crossed the tile unit. 309 310 byte random_bits; ///< Bits used for determining which randomized variational spritegroups to use when drawing. 311 byte waiting_triggers; ///< Triggers to be yet matched before rerandomizing the random bits. 312 313 StationID last_station_visited; ///< The last station we stopped at. 314 StationID last_loading_station; ///< Last station the vehicle has stopped at and could possibly leave from with any cargo loaded. 315 316 CargoID cargo_type; ///< type of cargo this vehicle is carrying 317 byte cargo_subtype; ///< Used for livery refits (NewGRF variations) 318 uint16 cargo_cap; ///< total capacity 319 uint16 refit_cap; ///< Capacity left over from before last refit. 320 VehicleCargoList cargo; ///< The cargo this vehicle is carrying 321 uint16 cargo_age_counter; ///< Ticks till cargo is aged next. 322 int8 trip_occupancy; ///< NOSAVE: Occupancy of vehicle of the current trip (updated after leaving a station). 323 324 byte day_counter; ///< Increased by one for each day 325 byte tick_counter; ///< Increased by one for each tick 326 byte running_ticks; ///< Number of ticks this vehicle was not stopped this day 327 328 byte vehstatus; ///< Status 329 Order current_order; ///< The current order (+ status, like: loading) 330 331 union { 332 OrderList *list; ///< Pointer to the order list for this vehicle 333 Order *old; ///< Only used during conversion of old save games 334 } orders; ///< The orders currently assigned to the vehicle. 335 336 uint16 load_unload_ticks; ///< Ticks to wait before starting next cycle. 337 GroupID group_id; ///< Index of group Pool array 338 byte subtype; ///< subtype (Filled with values from #AircraftSubType/#DisasterSubType/#EffectVehicleType/#GroundVehicleSubtypeFlags) 339 340 NewGRFCache grf_cache; ///< Cache of often used calculated NewGRF values 341 VehicleCache vcache; ///< Cache of often used vehicle values. 342 343 mutable MutableSpriteCache sprite_cache; ///< Cache of sprites and values related to recalculating them, see #MutableSpriteCache 344 345 Vehicle(VehicleType type = VEH_INVALID); 346 347 void PreDestructor(); 348 /** We want to 'destruct' the right class. */ 349 virtual ~Vehicle(); 350 351 void BeginLoading(); 352 void CancelReservation(StationID next, Station *st); 353 void LeaveStation(); 354 355 GroundVehicleCache *GetGroundVehicleCache(); 356 const GroundVehicleCache *GetGroundVehicleCache() const; 357 358 uint16 &GetGroundVehicleFlags(); 359 const uint16 &GetGroundVehicleFlags() const; 360 361 void DeleteUnreachedImplicitOrders(); 362 363 void HandleLoading(bool mode = false); 364 365 void GetConsistFreeCapacities(SmallMap<CargoID, uint> &capacities) const; 366 367 uint GetConsistTotalCapacity() const; 368 369 /** 370 * Marks the vehicles to be redrawn and updates cached variables 371 * 372 * This method marks the area of the vehicle on the screen as dirty. 373 * It can be use to repaint the vehicle. 374 * 375 * @ingroup dirty 376 */ MarkDirtyVehicle377 virtual void MarkDirty() {} 378 379 /** 380 * Updates the x and y offsets and the size of the sprite used 381 * for this vehicle. 382 */ UpdateDeltaXYVehicle383 virtual void UpdateDeltaXY() {} 384 385 /** 386 * Determines the effective direction-specific vehicle movement speed. 387 * 388 * This method belongs to the old vehicle movement method: 389 * A vehicle moves a step every 256 progress units. 390 * The vehicle speed is scaled by 3/4 when moving in X or Y direction due to the longer distance. 391 * 392 * However, this method is slightly wrong in corners, as the leftover progress is not scaled correctly 393 * when changing movement direction. #GetAdvanceSpeed() and #GetAdvanceDistance() are better wrt. this. 394 * 395 * @param speed Direction-independent unscaled speed. 396 * @return speed scaled by movement direction. 256 units are required for each movement step. 397 */ GetOldAdvanceSpeedVehicle398 inline uint GetOldAdvanceSpeed(uint speed) 399 { 400 return (this->direction & 1) ? speed : speed * 3 / 4; 401 } 402 403 /** 404 * Determines the effective vehicle movement speed. 405 * 406 * Together with #GetAdvanceDistance() this function is a replacement for #GetOldAdvanceSpeed(). 407 * 408 * A vehicle progresses independent of it's movement direction. 409 * However different amounts of "progress" are needed for moving a step in a specific direction. 410 * That way the leftover progress does not need any adaption when changing movement direction. 411 * 412 * @param speed Direction-independent unscaled speed. 413 * @return speed, scaled to match #GetAdvanceDistance(). 414 */ GetAdvanceSpeedVehicle415 static inline uint GetAdvanceSpeed(uint speed) 416 { 417 return speed * 3 / 4; 418 } 419 420 /** 421 * Determines the vehicle "progress" needed for moving a step. 422 * 423 * Together with #GetAdvanceSpeed() this function is a replacement for #GetOldAdvanceSpeed(). 424 * 425 * @return distance to drive for a movement step on the map. 426 */ GetAdvanceDistanceVehicle427 inline uint GetAdvanceDistance() 428 { 429 return (this->direction & 1) ? 192 : 256; 430 } 431 432 /** 433 * Sets the expense type associated to this vehicle type 434 * @param income whether this is income or (running) expenses of the vehicle 435 */ GetExpenseTypeVehicle436 virtual ExpensesType GetExpenseType(bool income) const { return EXPENSES_OTHER; } 437 438 /** 439 * Play the sound associated with leaving the station 440 */ PlayLeaveStationSoundVehicle441 virtual void PlayLeaveStationSound() const {} 442 443 /** 444 * Whether this is the primary vehicle in the chain. 445 */ IsPrimaryVehicleVehicle446 virtual bool IsPrimaryVehicle() const { return false; } 447 448 const Engine *GetEngine() const; 449 450 /** 451 * Gets the sprite to show for the given direction 452 * @param direction the direction the vehicle is facing 453 * @param[out] result Vehicle sprite sequence. 454 */ GetImageVehicle455 virtual void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const { result->Clear(); } 456 457 const GRFFile *GetGRF() const; 458 uint32 GetGRFID() const; 459 460 /** 461 * Invalidates cached NewGRF variables 462 * @see InvalidateNewGRFCacheOfChain 463 */ InvalidateNewGRFCacheVehicle464 inline void InvalidateNewGRFCache() 465 { 466 this->grf_cache.cache_valid = 0; 467 } 468 469 /** 470 * Invalidates cached NewGRF variables of all vehicles in the chain (after the current vehicle) 471 * @see InvalidateNewGRFCache 472 */ InvalidateNewGRFCacheOfChainVehicle473 inline void InvalidateNewGRFCacheOfChain() 474 { 475 for (Vehicle *u = this; u != nullptr; u = u->Next()) { 476 u->InvalidateNewGRFCache(); 477 } 478 } 479 480 /** 481 * Check if the vehicle is a ground vehicle. 482 * @return True iff the vehicle is a train or a road vehicle. 483 */ IsGroundVehicleVehicle484 inline bool IsGroundVehicle() const 485 { 486 return this->type == VEH_TRAIN || this->type == VEH_ROAD; 487 } 488 489 /** 490 * Gets the speed in km-ish/h that can be sent into SetDParam for string processing. 491 * @return the vehicle's speed 492 */ GetDisplaySpeedVehicle493 virtual int GetDisplaySpeed() const { return 0; } 494 495 /** 496 * Gets the maximum speed in km-ish/h that can be sent into SetDParam for string processing. 497 * @return the vehicle's maximum speed 498 */ GetDisplayMaxSpeedVehicle499 virtual int GetDisplayMaxSpeed() const { return 0; } 500 501 /** 502 * Calculates the maximum speed of the vehicle under its current conditions. 503 * @return Current maximum speed in native units. 504 */ GetCurrentMaxSpeedVehicle505 virtual int GetCurrentMaxSpeed() const { return 0; } 506 507 /** 508 * Gets the running cost of a vehicle 509 * @return the vehicle's running cost 510 */ GetRunningCostVehicle511 virtual Money GetRunningCost() const { return 0; } 512 513 /** 514 * Check whether the vehicle is in the depot. 515 * @return true if and only if the vehicle is in the depot. 516 */ IsInDepotVehicle517 virtual bool IsInDepot() const { return false; } 518 519 /** 520 * Check whether the whole vehicle chain is in the depot. 521 * @return true if and only if the whole chain is in the depot. 522 */ IsChainInDepotVehicle523 virtual bool IsChainInDepot() const { return this->IsInDepot(); } 524 525 /** 526 * Check whether the vehicle is in the depot *and* stopped. 527 * @return true if and only if the vehicle is in the depot and stopped. 528 */ IsStoppedInDepotVehicle529 bool IsStoppedInDepot() const 530 { 531 assert(this == this->First()); 532 /* Free wagons have no VS_STOPPED state */ 533 if (this->IsPrimaryVehicle() && !(this->vehstatus & VS_STOPPED)) return false; 534 return this->IsChainInDepot(); 535 } 536 537 /** 538 * Calls the tick handler of the vehicle 539 * @return is this vehicle still valid? 540 */ TickVehicle541 virtual bool Tick() { return true; }; 542 543 /** 544 * Calls the new day handler of the vehicle 545 */ OnNewDayVehicle546 virtual void OnNewDay() {}; 547 548 /** 549 * Crash the (whole) vehicle chain. 550 * @param flooded whether the cause of the crash is flooding or not. 551 * @return the number of lost souls. 552 */ 553 virtual uint Crash(bool flooded = false); 554 555 /** 556 * Returns the Trackdir on which the vehicle is currently located. 557 * Works for trains and ships. 558 * Currently works only sortof for road vehicles, since they have a fuzzy 559 * concept of being "on" a trackdir. Dunno really what it returns for a road 560 * vehicle that is halfway a tile, never really understood that part. For road 561 * vehicles that are at the beginning or end of the tile, should just return 562 * the diagonal trackdir on which they are driving. I _think_. 563 * For other vehicles types, or vehicles with no clear trackdir (such as those 564 * in depots), returns 0xFF. 565 * @return the trackdir of the vehicle 566 */ GetVehicleTrackdirVehicle567 virtual Trackdir GetVehicleTrackdir() const { return INVALID_TRACKDIR; } 568 569 /** 570 * Gets the running cost of a vehicle that can be sent into SetDParam for string processing. 571 * @return the vehicle's running cost 572 */ GetDisplayRunningCostVehicle573 Money GetDisplayRunningCost() const { return (this->GetRunningCost() >> 8); } 574 575 /** 576 * Gets the profit vehicle had this year. It can be sent into SetDParam for string processing. 577 * @return the vehicle's profit this year 578 */ GetDisplayProfitThisYearVehicle579 Money GetDisplayProfitThisYear() const { return (this->profit_this_year >> 8); } 580 581 /** 582 * Gets the profit vehicle had last year. It can be sent into SetDParam for string processing. 583 * @return the vehicle's profit last year 584 */ GetDisplayProfitLastYearVehicle585 Money GetDisplayProfitLastYear() const { return (this->profit_last_year >> 8); } 586 587 void SetNext(Vehicle *next); 588 589 /** 590 * Get the next vehicle of this vehicle. 591 * @note articulated parts are also counted as vehicles. 592 * @return the next vehicle or nullptr when there isn't a next vehicle. 593 */ NextVehicle594 inline Vehicle *Next() const { return this->next; } 595 596 /** 597 * Get the previous vehicle of this vehicle. 598 * @note articulated parts are also counted as vehicles. 599 * @return the previous vehicle or nullptr when there isn't a previous vehicle. 600 */ PreviousVehicle601 inline Vehicle *Previous() const { return this->previous; } 602 603 /** 604 * Get the first vehicle of this vehicle chain. 605 * @return the first vehicle of the chain. 606 */ FirstVehicle607 inline Vehicle *First() const { return this->first; } 608 609 /** 610 * Get the last vehicle of this vehicle chain. 611 * @return the last vehicle of the chain. 612 */ LastVehicle613 inline Vehicle *Last() 614 { 615 Vehicle *v = this; 616 while (v->Next() != nullptr) v = v->Next(); 617 return v; 618 } 619 620 /** 621 * Get the last vehicle of this vehicle chain. 622 * @return the last vehicle of the chain. 623 */ LastVehicle624 inline const Vehicle *Last() const 625 { 626 const Vehicle *v = this; 627 while (v->Next() != nullptr) v = v->Next(); 628 return v; 629 } 630 631 /** 632 * Get the vehicle at offset \a n of this vehicle chain. 633 * @param n Offset from the current vehicle. 634 * @return The new vehicle or nullptr if the offset is out-of-bounds. 635 */ MoveVehicle636 inline Vehicle *Move(int n) 637 { 638 Vehicle *v = this; 639 if (n < 0) { 640 for (int i = 0; i != n && v != nullptr; i--) v = v->Previous(); 641 } else { 642 for (int i = 0; i != n && v != nullptr; i++) v = v->Next(); 643 } 644 return v; 645 } 646 647 /** 648 * Get the vehicle at offset \a n of this vehicle chain. 649 * @param n Offset from the current vehicle. 650 * @return The new vehicle or nullptr if the offset is out-of-bounds. 651 */ MoveVehicle652 inline const Vehicle *Move(int n) const 653 { 654 const Vehicle *v = this; 655 if (n < 0) { 656 for (int i = 0; i != n && v != nullptr; i--) v = v->Previous(); 657 } else { 658 for (int i = 0; i != n && v != nullptr; i++) v = v->Next(); 659 } 660 return v; 661 } 662 663 /** 664 * Get the first order of the vehicles order list. 665 * @return first order of order list. 666 */ GetFirstOrderVehicle667 inline Order *GetFirstOrder() const { return (this->orders.list == nullptr) ? nullptr : this->orders.list->GetFirstOrder(); } 668 669 void AddToShared(Vehicle *shared_chain); 670 void RemoveFromShared(); 671 672 /** 673 * Get the next vehicle of the shared vehicle chain. 674 * @return the next shared vehicle or nullptr when there isn't a next vehicle. 675 */ NextSharedVehicle676 inline Vehicle *NextShared() const { return this->next_shared; } 677 678 /** 679 * Get the previous vehicle of the shared vehicle chain 680 * @return the previous shared vehicle or nullptr when there isn't a previous vehicle. 681 */ PreviousSharedVehicle682 inline Vehicle *PreviousShared() const { return this->previous_shared; } 683 684 /** 685 * Get the first vehicle of this vehicle chain. 686 * @return the first vehicle of the chain. 687 */ FirstSharedVehicle688 inline Vehicle *FirstShared() const { return (this->orders.list == nullptr) ? this->First() : this->orders.list->GetFirstSharedVehicle(); } 689 690 /** 691 * Check if we share our orders with another vehicle. 692 * @return true if there are other vehicles sharing the same order 693 */ IsOrderListSharedVehicle694 inline bool IsOrderListShared() const { return this->orders.list != nullptr && this->orders.list->IsShared(); } 695 696 /** 697 * Get the number of orders this vehicle has. 698 * @return the number of orders this vehicle has. 699 */ GetNumOrdersVehicle700 inline VehicleOrderID GetNumOrders() const { return (this->orders.list == nullptr) ? 0 : this->orders.list->GetNumOrders(); } 701 702 /** 703 * Get the number of manually added orders this vehicle has. 704 * @return the number of manually added orders this vehicle has. 705 */ GetNumManualOrdersVehicle706 inline VehicleOrderID GetNumManualOrders() const { return (this->orders.list == nullptr) ? 0 : this->orders.list->GetNumManualOrders(); } 707 708 /** 709 * Get the next station the vehicle will stop at. 710 * @return ID of the next station the vehicle will stop at or INVALID_STATION. 711 */ GetNextStoppingStationVehicle712 inline StationIDStack GetNextStoppingStation() const 713 { 714 return (this->orders.list == nullptr) ? INVALID_STATION : this->orders.list->GetNextStoppingStation(this); 715 } 716 717 void ResetRefitCaps(); 718 719 /** 720 * Copy certain configurations and statistics of a vehicle after successful autoreplace/renew 721 * The function shall copy everything that cannot be copied by a command (like orders / group etc), 722 * and that shall not be resetted for the new vehicle. 723 * @param src The old vehicle 724 */ CopyVehicleConfigAndStatisticsVehicle725 inline void CopyVehicleConfigAndStatistics(const Vehicle *src) 726 { 727 this->CopyConsistPropertiesFrom(src); 728 729 this->unitnumber = src->unitnumber; 730 731 this->current_order = src->current_order; 732 this->dest_tile = src->dest_tile; 733 734 this->profit_this_year = src->profit_this_year; 735 this->profit_last_year = src->profit_last_year; 736 } 737 738 739 bool HandleBreakdown(); 740 741 bool NeedsAutorenewing(const Company *c, bool use_renew_setting = true) const; 742 743 bool NeedsServicing() const; 744 bool NeedsAutomaticServicing() const; 745 746 /** 747 * Determine the location for the station where the vehicle goes to next. 748 * Things done for example are allocating slots in a road stop or exact 749 * location of the platform is determined for ships. 750 * @param station the station to make the next location of the vehicle. 751 * @return the location (tile) to aim for. 752 */ GetOrderStationLocationVehicle753 virtual TileIndex GetOrderStationLocation(StationID station) { return INVALID_TILE; } 754 755 /** 756 * Find the closest depot for this vehicle and tell us the location, 757 * DestinationID and whether we should reverse. 758 * @param location where do we go to? 759 * @param destination what hangar do we go to? 760 * @param reverse should the vehicle be reversed? 761 * @return true if a depot could be found. 762 */ FindClosestDepotVehicle763 virtual bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse) { return false; } 764 SetDestTileVehicle765 virtual void SetDestTile(TileIndex tile) { this->dest_tile = tile; } 766 767 CommandCost SendToDepot(DoCommandFlag flags, DepotCommand command); 768 769 void UpdateVisualEffect(bool allow_power_change = true); 770 void ShowVisualEffect() const; 771 772 void UpdatePosition(); 773 void UpdateViewport(bool dirty); 774 void UpdateBoundingBoxCoordinates(bool update_cache) const; 775 void UpdatePositionAndViewport(); 776 bool MarkAllViewportsDirty() const; 777 GetServiceIntervalVehicle778 inline uint16 GetServiceInterval() const { return this->service_interval; } 779 SetServiceIntervalVehicle780 inline void SetServiceInterval(uint16 interval) { this->service_interval = interval; } 781 ServiceIntervalIsCustomVehicle782 inline bool ServiceIntervalIsCustom() const { return HasBit(this->vehicle_flags, VF_SERVINT_IS_CUSTOM); } 783 ServiceIntervalIsPercentVehicle784 inline bool ServiceIntervalIsPercent() const { return HasBit(this->vehicle_flags, VF_SERVINT_IS_PERCENT); } 785 SetServiceIntervalIsCustomVehicle786 inline void SetServiceIntervalIsCustom(bool on) { SB(this->vehicle_flags, VF_SERVINT_IS_CUSTOM, 1, on); } 787 SetServiceIntervalIsPercentVehicle788 inline void SetServiceIntervalIsPercent(bool on) { SB(this->vehicle_flags, VF_SERVINT_IS_PERCENT, 1, on); } 789 790 private: 791 /** 792 * Advance cur_real_order_index to the next real order. 793 * cur_implicit_order_index is not touched. 794 */ SkipToNextRealOrderIndexVehicle795 void SkipToNextRealOrderIndex() 796 { 797 if (this->GetNumManualOrders() > 0) { 798 /* Advance to next real order */ 799 do { 800 this->cur_real_order_index++; 801 if (this->cur_real_order_index >= this->GetNumOrders()) this->cur_real_order_index = 0; 802 } while (this->GetOrder(this->cur_real_order_index)->IsType(OT_IMPLICIT)); 803 } else { 804 this->cur_real_order_index = 0; 805 } 806 } 807 808 public: 809 /** 810 * Increments cur_implicit_order_index, keeps care of the wrap-around and invalidates the GUI. 811 * cur_real_order_index is incremented as well, if needed. 812 * Note: current_order is not invalidated. 813 */ IncrementImplicitOrderIndexVehicle814 void IncrementImplicitOrderIndex() 815 { 816 if (this->cur_implicit_order_index == this->cur_real_order_index) { 817 /* Increment real order index as well */ 818 this->SkipToNextRealOrderIndex(); 819 } 820 821 assert(this->cur_real_order_index == 0 || this->cur_real_order_index < this->GetNumOrders()); 822 823 /* Advance to next implicit order */ 824 do { 825 this->cur_implicit_order_index++; 826 if (this->cur_implicit_order_index >= this->GetNumOrders()) this->cur_implicit_order_index = 0; 827 } while (this->cur_implicit_order_index != this->cur_real_order_index && !this->GetOrder(this->cur_implicit_order_index)->IsType(OT_IMPLICIT)); 828 829 InvalidateVehicleOrder(this, 0); 830 } 831 832 /** 833 * Advanced cur_real_order_index to the next real order, keeps care of the wrap-around and invalidates the GUI. 834 * cur_implicit_order_index is incremented as well, if it was equal to cur_real_order_index, i.e. cur_real_order_index is skipped 835 * but not any implicit orders. 836 * Note: current_order is not invalidated. 837 */ IncrementRealOrderIndexVehicle838 void IncrementRealOrderIndex() 839 { 840 if (this->cur_implicit_order_index == this->cur_real_order_index) { 841 /* Increment both real and implicit order */ 842 this->IncrementImplicitOrderIndex(); 843 } else { 844 /* Increment real order only */ 845 this->SkipToNextRealOrderIndex(); 846 InvalidateVehicleOrder(this, 0); 847 } 848 } 849 850 /** 851 * Skip implicit orders until cur_real_order_index is a non-implicit order. 852 */ UpdateRealOrderIndexVehicle853 void UpdateRealOrderIndex() 854 { 855 /* Make sure the index is valid */ 856 if (this->cur_real_order_index >= this->GetNumOrders()) this->cur_real_order_index = 0; 857 858 if (this->GetNumManualOrders() > 0) { 859 /* Advance to next real order */ 860 while (this->GetOrder(this->cur_real_order_index)->IsType(OT_IMPLICIT)) { 861 this->cur_real_order_index++; 862 if (this->cur_real_order_index >= this->GetNumOrders()) this->cur_real_order_index = 0; 863 } 864 } else { 865 this->cur_real_order_index = 0; 866 } 867 } 868 869 /** 870 * Returns order 'index' of a vehicle or nullptr when it doesn't exists 871 * @param index the order to fetch 872 * @return the found (or not) order 873 */ GetOrderVehicle874 inline Order *GetOrder(int index) const 875 { 876 return (this->orders.list == nullptr) ? nullptr : this->orders.list->GetOrderAt(index); 877 } 878 879 /** 880 * Returns the last order of a vehicle, or nullptr if it doesn't exists 881 * @return last order of a vehicle, if available 882 */ GetLastOrderVehicle883 inline Order *GetLastOrder() const 884 { 885 return (this->orders.list == nullptr) ? nullptr : this->orders.list->GetLastOrder(); 886 } 887 888 bool IsEngineCountable() const; 889 bool HasEngineType() const; 890 bool HasDepotOrder() const; 891 void HandlePathfindingResult(bool path_found); 892 893 /** 894 * Check if the vehicle is a front engine. 895 * @return Returns true if the vehicle is a front engine. 896 */ IsFrontEngineVehicle897 inline bool IsFrontEngine() const 898 { 899 return this->IsGroundVehicle() && HasBit(this->subtype, GVSF_FRONT); 900 } 901 902 /** 903 * Check if the vehicle is an articulated part of an engine. 904 * @return Returns true if the vehicle is an articulated part. 905 */ IsArticulatedPartVehicle906 inline bool IsArticulatedPart() const 907 { 908 return this->IsGroundVehicle() && HasBit(this->subtype, GVSF_ARTICULATED_PART); 909 } 910 911 /** 912 * Check if an engine has an articulated part. 913 * @return True if the engine has an articulated part. 914 */ HasArticulatedPartVehicle915 inline bool HasArticulatedPart() const 916 { 917 return this->Next() != nullptr && this->Next()->IsArticulatedPart(); 918 } 919 920 /** 921 * Get the next part of an articulated engine. 922 * @return Next part of the articulated engine. 923 * @pre The vehicle is an articulated engine. 924 */ GetNextArticulatedPartVehicle925 inline Vehicle *GetNextArticulatedPart() const 926 { 927 assert(this->HasArticulatedPart()); 928 return this->Next(); 929 } 930 931 /** 932 * Get the first part of an articulated engine. 933 * @return First part of the engine. 934 */ GetFirstEnginePartVehicle935 inline Vehicle *GetFirstEnginePart() 936 { 937 Vehicle *v = this; 938 while (v->IsArticulatedPart()) v = v->Previous(); 939 return v; 940 } 941 942 /** 943 * Get the first part of an articulated engine. 944 * @return First part of the engine. 945 */ GetFirstEnginePartVehicle946 inline const Vehicle *GetFirstEnginePart() const 947 { 948 const Vehicle *v = this; 949 while (v->IsArticulatedPart()) v = v->Previous(); 950 return v; 951 } 952 953 /** 954 * Get the last part of an articulated engine. 955 * @return Last part of the engine. 956 */ GetLastEnginePartVehicle957 inline Vehicle *GetLastEnginePart() 958 { 959 Vehicle *v = this; 960 while (v->HasArticulatedPart()) v = v->GetNextArticulatedPart(); 961 return v; 962 } 963 964 /** 965 * Get the next real (non-articulated part) vehicle in the consist. 966 * @return Next vehicle in the consist. 967 */ GetNextVehicleVehicle968 inline Vehicle *GetNextVehicle() const 969 { 970 const Vehicle *v = this; 971 while (v->HasArticulatedPart()) v = v->GetNextArticulatedPart(); 972 973 /* v now contains the last articulated part in the engine */ 974 return v->Next(); 975 } 976 977 /** 978 * Get the previous real (non-articulated part) vehicle in the consist. 979 * @return Previous vehicle in the consist. 980 */ GetPrevVehicleVehicle981 inline Vehicle *GetPrevVehicle() const 982 { 983 Vehicle *v = this->Previous(); 984 while (v != nullptr && v->IsArticulatedPart()) v = v->Previous(); 985 986 return v; 987 } 988 989 /** 990 * Iterator to iterate orders 991 * Supports deletion of current order 992 */ 993 struct OrderIterator { 994 typedef Order value_type; 995 typedef Order* pointer; 996 typedef Order& reference; 997 typedef size_t difference_type; 998 typedef std::forward_iterator_tag iterator_category; 999 OrderIteratorVehicle::OrderIterator1000 explicit OrderIterator(OrderList *list) : list(list), prev(nullptr) 1001 { 1002 this->order = (this->list == nullptr) ? nullptr : this->list->GetFirstOrder(); 1003 } 1004 1005 bool operator==(const OrderIterator &other) const { return this->order == other.order; } 1006 bool operator!=(const OrderIterator &other) const { return !(*this == other); } 1007 Order * operator*() const { return this->order; } 1008 OrderIterator & operator++() 1009 { 1010 this->prev = (this->prev == nullptr) ? this->list->GetFirstOrder() : this->prev->next; 1011 this->order = (this->prev == nullptr) ? nullptr : this->prev->next; 1012 return *this; 1013 } 1014 1015 private: 1016 OrderList *list; 1017 Order *order; 1018 Order *prev; 1019 }; 1020 1021 /** 1022 * Iterable ensemble of orders 1023 */ 1024 struct IterateWrapper { 1025 OrderList *list; listVehicle::IterateWrapper1026 IterateWrapper(OrderList *list = nullptr) : list(list) {} beginVehicle::IterateWrapper1027 OrderIterator begin() { return OrderIterator(this->list); } endVehicle::IterateWrapper1028 OrderIterator end() { return OrderIterator(nullptr); } emptyVehicle::IterateWrapper1029 bool empty() { return this->begin() == this->end(); } 1030 }; 1031 1032 /** 1033 * Returns an iterable ensemble of orders of a vehicle 1034 * @return an iterable ensemble of orders of a vehicle 1035 */ OrdersVehicle1036 IterateWrapper Orders() const { return IterateWrapper(this->orders.list); } 1037 }; 1038 1039 /** 1040 * Class defining several overloaded accessors so we don't 1041 * have to cast vehicle types that often 1042 */ 1043 template <class T, VehicleType Type> 1044 struct SpecializedVehicle : public Vehicle { 1045 static const VehicleType EXPECTED_TYPE = Type; ///< Specialized type 1046 1047 typedef SpecializedVehicle<T, Type> SpecializedVehicleBase; ///< Our type 1048 1049 /** 1050 * Set vehicle type correctly 1051 */ VehicleSpecializedVehicle1052 inline SpecializedVehicle<T, Type>() : Vehicle(Type) 1053 { 1054 this->sprite_cache.sprite_seq.count = 1; 1055 } 1056 1057 /** 1058 * Get the first vehicle in the chain 1059 * @return first vehicle in the chain 1060 */ FirstSpecializedVehicle1061 inline T *First() const { return (T *)this->Vehicle::First(); } 1062 1063 /** 1064 * Get the last vehicle in the chain 1065 * @return last vehicle in the chain 1066 */ LastSpecializedVehicle1067 inline T *Last() { return (T *)this->Vehicle::Last(); } 1068 1069 /** 1070 * Get the last vehicle in the chain 1071 * @return last vehicle in the chain 1072 */ LastSpecializedVehicle1073 inline const T *Last() const { return (const T *)this->Vehicle::Last(); } 1074 1075 /** 1076 * Get next vehicle in the chain 1077 * @return next vehicle in the chain 1078 */ NextSpecializedVehicle1079 inline T *Next() const { return (T *)this->Vehicle::Next(); } 1080 1081 /** 1082 * Get previous vehicle in the chain 1083 * @return previous vehicle in the chain 1084 */ PreviousSpecializedVehicle1085 inline T *Previous() const { return (T *)this->Vehicle::Previous(); } 1086 1087 /** 1088 * Get the next part of an articulated engine. 1089 * @return Next part of the articulated engine. 1090 * @pre The vehicle is an articulated engine. 1091 */ GetNextArticulatedPartSpecializedVehicle1092 inline T *GetNextArticulatedPart() { return (T *)this->Vehicle::GetNextArticulatedPart(); } 1093 1094 /** 1095 * Get the next part of an articulated engine. 1096 * @return Next part of the articulated engine. 1097 * @pre The vehicle is an articulated engine. 1098 */ GetNextArticulatedPartSpecializedVehicle1099 inline T *GetNextArticulatedPart() const { return (T *)this->Vehicle::GetNextArticulatedPart(); } 1100 1101 /** 1102 * Get the first part of an articulated engine. 1103 * @return First part of the engine. 1104 */ GetFirstEnginePartSpecializedVehicle1105 inline T *GetFirstEnginePart() { return (T *)this->Vehicle::GetFirstEnginePart(); } 1106 1107 /** 1108 * Get the first part of an articulated engine. 1109 * @return First part of the engine. 1110 */ GetFirstEnginePartSpecializedVehicle1111 inline const T *GetFirstEnginePart() const { return (const T *)this->Vehicle::GetFirstEnginePart(); } 1112 1113 /** 1114 * Get the last part of an articulated engine. 1115 * @return Last part of the engine. 1116 */ GetLastEnginePartSpecializedVehicle1117 inline T *GetLastEnginePart() { return (T *)this->Vehicle::GetLastEnginePart(); } 1118 1119 /** 1120 * Get the next real (non-articulated part) vehicle in the consist. 1121 * @return Next vehicle in the consist. 1122 */ GetNextVehicleSpecializedVehicle1123 inline T *GetNextVehicle() const { return (T *)this->Vehicle::GetNextVehicle(); } 1124 1125 /** 1126 * Get the previous real (non-articulated part) vehicle in the consist. 1127 * @return Previous vehicle in the consist. 1128 */ GetPrevVehicleSpecializedVehicle1129 inline T *GetPrevVehicle() const { return (T *)this->Vehicle::GetPrevVehicle(); } 1130 1131 /** 1132 * Tests whether given index is a valid index for vehicle of this type 1133 * @param index tested index 1134 * @return is this index valid index of T? 1135 */ IsValidIDSpecializedVehicle1136 static inline bool IsValidID(size_t index) 1137 { 1138 return Vehicle::IsValidID(index) && Vehicle::Get(index)->type == Type; 1139 } 1140 1141 /** 1142 * Gets vehicle with given index 1143 * @return pointer to vehicle with given index casted to T * 1144 */ GetSpecializedVehicle1145 static inline T *Get(size_t index) 1146 { 1147 return (T *)Vehicle::Get(index); 1148 } 1149 1150 /** 1151 * Returns vehicle if the index is a valid index for this vehicle type 1152 * @return pointer to vehicle with given index if it's a vehicle of this type 1153 */ GetIfValidSpecializedVehicle1154 static inline T *GetIfValid(size_t index) 1155 { 1156 return IsValidID(index) ? Get(index) : nullptr; 1157 } 1158 1159 /** 1160 * Converts a Vehicle to SpecializedVehicle with type checking. 1161 * @param v Vehicle pointer 1162 * @return pointer to SpecializedVehicle 1163 */ FromSpecializedVehicle1164 static inline T *From(Vehicle *v) 1165 { 1166 assert(v->type == Type); 1167 return (T *)v; 1168 } 1169 1170 /** 1171 * Converts a const Vehicle to const SpecializedVehicle with type checking. 1172 * @param v Vehicle pointer 1173 * @return pointer to SpecializedVehicle 1174 */ FromSpecializedVehicle1175 static inline const T *From(const Vehicle *v) 1176 { 1177 assert(v->type == Type); 1178 return (const T *)v; 1179 } 1180 1181 /** 1182 * Update vehicle sprite- and position caches 1183 * @param force_update Force updating the vehicle on the viewport. 1184 * @param update_delta Also update the delta? 1185 */ UpdateViewportSpecializedVehicle1186 inline void UpdateViewport(bool force_update, bool update_delta) 1187 { 1188 bool sprite_has_changed = false; 1189 1190 /* Skip updating sprites on dedicated servers without screen */ 1191 if (_network_dedicated) return; 1192 1193 /* Explicitly choose method to call to prevent vtable dereference - 1194 * it gives ~3% runtime improvements in games with many vehicles */ 1195 if (update_delta) ((T *)this)->T::UpdateDeltaXY(); 1196 1197 /* 1198 * Only check for a new sprite sequence if the vehicle direction 1199 * has changed since we last checked it, assuming that otherwise 1200 * there won't be enough change in bounding box or offsets to need 1201 * to resolve a new sprite. 1202 */ 1203 if (this->direction != this->sprite_cache.last_direction || this->sprite_cache.is_viewport_candidate) { 1204 VehicleSpriteSeq seq; 1205 1206 ((T*)this)->T::GetImage(this->direction, EIT_ON_MAP, &seq); 1207 if (this->sprite_cache.sprite_seq != seq) { 1208 sprite_has_changed = true; 1209 this->sprite_cache.sprite_seq = seq; 1210 } 1211 1212 this->sprite_cache.last_direction = this->direction; 1213 this->sprite_cache.revalidate_before_draw = false; 1214 } else { 1215 /* 1216 * A change that could potentially invalidate the sprite has been 1217 * made, signal that we should still resolve it before drawing on a 1218 * viewport. 1219 */ 1220 this->sprite_cache.revalidate_before_draw = true; 1221 } 1222 1223 if (force_update || sprite_has_changed) { 1224 this->Vehicle::UpdateViewport(true); 1225 } 1226 } 1227 1228 /** 1229 * Returns an iterable ensemble of all valid vehicles of type T 1230 * @param from index of the first vehicle to consider 1231 * @return an iterable ensemble of all valid vehicles of type T 1232 */ 1233 static Pool::IterateWrapper<T> Iterate(size_t from = 0) { return Pool::IterateWrapper<T>(from); } 1234 }; 1235 1236 /** Generates sequence of free UnitID numbers */ 1237 struct FreeUnitIDGenerator { 1238 bool *cache; ///< array of occupied unit id numbers 1239 UnitID maxid; ///< maximum ID at the moment of constructor call 1240 UnitID curid; ///< last ID returned; 0 if none 1241 1242 FreeUnitIDGenerator(VehicleType type, CompanyID owner); 1243 UnitID NextID(); 1244 1245 /** Releases allocated memory */ ~FreeUnitIDGeneratorFreeUnitIDGenerator1246 ~FreeUnitIDGenerator() { free(this->cache); } 1247 }; 1248 1249 /** Sentinel for an invalid coordinate. */ 1250 static const int32 INVALID_COORD = 0x7fffffff; 1251 1252 #endif /* VEHICLE_BASE_H */ 1253